BadBehavior added

This commit is contained in:
Duion 2016-08-12 20:39:56 +02:00
parent b16f99d51c
commit eaa28844c9
63 changed files with 5698 additions and 0 deletions

View file

@ -0,0 +1,125 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "RandomWait.h"
#include "BadBehavior/core/Runner.h"
#include "math/mMathFn.h"
#include "console/consoleTypes.h"
using namespace BadBehavior;
//------------------------------------------------------------------------------
// RandomWait leaf node
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(RandomWait);
RandomWait::RandomWait()
: mWaitMinMs(0),
mWaitMaxMs(99999)
{
}
void RandomWait::initPersistFields()
{
addGroup( "Behavior" );
addProtectedField( "waitMinMs", TypeS32, Offset(mWaitMinMs, RandomWait), &_setWaitMin, &defaultProtectedGetFn,
"The minimum time period in ms to wait before completion." );
addProtectedField( "waitMaxMs", TypeS32, Offset(mWaitMaxMs, RandomWait), &_setWaitMax, &defaultProtectedGetFn,
"The maximum time period in ms to wait before completion." );
endGroup( "Behavior" );
Parent::initPersistFields();
}
bool RandomWait::_setWaitMin(void *object, const char *index, const char *data)
{
RandomWait *node = static_cast<RandomWait *>( object );
node->mWaitMinMs = getMin(node->mWaitMaxMs, dAtoi( data ));
return false;
}
bool RandomWait::_setWaitMax(void *object, const char *index, const char *data)
{
RandomWait *node = static_cast<RandomWait *>( object );
node->mWaitMaxMs = getMax(node->mWaitMinMs, dAtoi( data ));
return false;
}
Task *RandomWait::createTask(SimObject &owner, BehaviorTreeRunner &runner)
{
return new RandomWaitTask(*this, owner, runner);
}
//------------------------------------------------------------------------------
// RandomWait task
//------------------------------------------------------------------------------
RandomWaitTask::RandomWaitTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
: Parent(node, owner, runner)
{
}
RandomWaitTask::~RandomWaitTask()
{
cancelEvent();
}
void RandomWaitTask::cancelEvent()
{
if(Sim::isEventPending(mEventId))
{
Sim::cancelEvent(mEventId);
mEventId = 0;
}
}
void RandomWaitTask::onInitialize()
{
Parent::onInitialize();
cancelEvent();
}
void RandomWaitTask::onTerminate()
{
Parent::onTerminate();
cancelEvent();
}
Task* RandomWaitTask::update()
{
if(mStatus == RESUME)
{
mStatus = SUCCESS;
mIsComplete = true;
}
else if(mStatus == INVALID)
{
RandomWait *node = static_cast<RandomWait*>(mNodeRep);
mEventId = Sim::postEvent(mRunner, new TaskReactivateEvent(*this), Sim::getCurrentTime() + mRandI(node->getWaitMinMs(), node->getWaitMaxMs()));
mStatus = SUSPENDED;
}
return NULL;
}

View file

@ -0,0 +1,83 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _BB_RANDOMWAIT_H_
#define _BB_RANDOMWAIT_H_
#ifndef _BB_CORE_H_
#include "BadBehavior/core/Core.h"
#endif
namespace BadBehavior
{
//---------------------------------------------------------------------------
// RandomWait leaf
// Pauses for a random period of time between delayMin and delayMax ms before completing.
//---------------------------------------------------------------------------
class RandomWait : public LeafNode
{
typedef LeafNode Parent;
protected:
static bool _setWaitMin(void *object, const char *index, const char *data);
static bool _setWaitMax(void *object, const char *index, const char *data);
S32 mWaitMinMs;
S32 mWaitMaxMs;
public:
RandomWait();
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
static void initPersistFields();
S32 getWaitMinMs() const { return mWaitMinMs; }
S32 getWaitMaxMs() const { return mWaitMaxMs; }
DECLARE_CONOBJECT(RandomWait);
};
//---------------------------------------------------------------------------
// RandomWait leaf task
//---------------------------------------------------------------------------
class RandomWaitTask : public Task
{
typedef Task Parent;
protected:
U32 mEventId;
virtual void onInitialize();
virtual void onTerminate();
virtual Task* update();
void cancelEvent();
public:
RandomWaitTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
virtual ~RandomWaitTask();
};
} // namespace BadBehavior
#endif

View file

@ -0,0 +1,94 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "ScriptEval.h"
#include "console/engineAPI.h"
#include "platform/profiler.h"
using namespace BadBehavior;
//------------------------------------------------------------------------------
// ScriptEval node - warning, slow!
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(ScriptEval);
ScriptEval::ScriptEval()
: mDefaultReturnStatus(SUCCESS)
{
}
void ScriptEval::initPersistFields()
{
addGroup( "Behavior" );
addField( "behaviorScript", TypeCommand, Offset(mBehaviorScript, ScriptEval),
"@brief The command to execute when the leaf is ticked. Max 255 characters." );
addField( "defaultReturnStatus", TYPEID< BadBehavior::Status >(), Offset(mDefaultReturnStatus, ScriptEval),
"@brief The default value for this node to return.");
endGroup( "Behavior" );
Parent::initPersistFields();
}
Task *ScriptEval::createTask(SimObject &owner, BehaviorTreeRunner &runner)
{
return new ScriptEvalTask(*this, owner, runner);
}
Status ScriptEval::evaluateScript( SimObject *owner )
{
PROFILE_SCOPE(ScriptEval_evaluateScript);
if(mBehaviorScript.isEmpty())
return mDefaultReturnStatus;
// get the result
const char *result = Con::evaluatef("%%obj=%s; %s return %s;",
owner->getIdString(),
mBehaviorScript.c_str(),
EngineMarshallData< BehaviorReturnType >(mDefaultReturnStatus));
if(result[0] == '1' || result[0] == '0')
// map true or false to SUCCEED or FAILURE
return static_cast<Status>(dAtoi(result));
// convert the returned value to our internal enum type
return EngineUnmarshallData< BehaviorReturnType >()( result );
}
//------------------------------------------------------------------------------
// RunScript task
//------------------------------------------------------------------------------
ScriptEvalTask::ScriptEvalTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
: Parent(node, owner, runner)
{
}
Task* ScriptEvalTask::update()
{
mStatus = static_cast<ScriptEval*>(mNodeRep)->evaluateScript( mOwner );
return NULL; // leaves don't have children
}

View file

@ -0,0 +1,75 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _BB_SCRIPTEVAL_H_
#define _BB_SCRIPTEVAL_H_
#ifndef _BB_CORE_H_
#include "BadBehavior/core/Core.h"
#endif
namespace BadBehavior
{
//---------------------------------------------------------------------------
// ScriptEval - evaluates a set of Torque Script commands when run
// Warning - slow, handle with care!
//---------------------------------------------------------------------------
class ScriptEval : public LeafNode
{
typedef LeafNode Parent;
private:
// status to return if the command does not return a value
Status mDefaultReturnStatus;
// the torque script to evaluate
String mBehaviorScript;
public:
ScriptEval();
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
static void initPersistFields();
// execute the script
Status evaluateScript(SimObject *owner);
DECLARE_CONOBJECT(ScriptEval);
};
//---------------------------------------------------------------------------
// ScriptEval task
//---------------------------------------------------------------------------
class ScriptEvalTask : public Task
{
typedef Task Parent;
protected:
virtual Task* update();
public:
ScriptEvalTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
};
} // namespace BadBehavior
#endif

View file

@ -0,0 +1,121 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "ScriptFunc.h"
#include "console/engineAPI.h"
#include "platform/profiler.h"
using namespace BadBehavior;
//------------------------------------------------------------------------------
// ScriptFunc node
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(ScriptFunc);
ScriptFunc::ScriptFunc()
: mDefaultReturnStatus(SUCCESS),
mScriptFunction(StringTable->insert(""))
{
for(U8 i = 0; i < MAX_COMMAND_ARGS; ++i)
mScriptArgs[i] = StringTable->insert("");
}
void ScriptFunc::initPersistFields()
{
addGroup( "Behavior" );
addField( "func", TypeCaseString, Offset(mScriptFunction, ScriptFunc),
"@brief The function to execute when the leaf is ticked." );
addField( "args", TypeCaseString, Offset(mScriptArgs, ScriptFunc), MAX_COMMAND_ARGS,
"@brief The arguments to be passed to the function to be executed." );
addField( "defaultReturnStatus", TYPEID< BadBehavior::Status >(), Offset(mDefaultReturnStatus, ScriptFunc),
"@brief The default value for this node to return.");
endGroup( "Behavior" );
Parent::initPersistFields();
}
Task *ScriptFunc::createTask(SimObject &owner, BehaviorTreeRunner &runner)
{
return new ScriptFuncTask(*this, owner, runner);
}
Status ScriptFunc::evaluate( SimObject *owner )
{
PROFILE_SCOPE(ScriptFunc_evaluate);
if(!owner)
return INVALID;
if(!mScriptFunction || !mScriptFunction[0])
return mDefaultReturnStatus;
S32 argc = 0;
const char *args[MAX_COMMAND_ARGS + 2];
args[0] = mScriptFunction;
while(argc < MAX_COMMAND_ARGS && (mScriptArgs[argc] && mScriptArgs[argc][0]))
{
args[argc + 2] = mScriptArgs[argc];
++argc;
}
argc += 2;
// get the result
const char *result = Con::execute(owner, argc, args);
// if function didn't return a result, return our default status
if(!result || !result[0])
return mDefaultReturnStatus;
// map true or false to SUCCEED or FAILURE
if(result[0] == '1' || result[0] == '0')
return static_cast<Status>(dAtoi(result));
// convert the returned value to our internal enum type
return EngineUnmarshallData< BehaviorReturnType >()( result );
}
//------------------------------------------------------------------------------
// ScriptFunc task
//------------------------------------------------------------------------------
ScriptFuncTask::ScriptFuncTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
: Parent(node, owner, runner)
{
}
Task* ScriptFuncTask::update()
{
mStatus = static_cast<ScriptFunc*>(mNodeRep)->evaluate( mOwner );
if(mStatus != RUNNING && mStatus != SUSPENDED)
mIsComplete = true;
return NULL; // leaves don't have children
}

View file

@ -0,0 +1,79 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _BB_SCRIPTFUNC_H_
#define _BB_SCRIPTFUNC_H_
#ifndef _BB_CORE_H_
#include "BadBehavior/core/Core.h"
#endif
namespace BadBehavior
{
static const U8 MAX_COMMAND_ARGS = 4;
//---------------------------------------------------------------------------
// ScriptFunc - executes a function on the owner object
//---------------------------------------------------------------------------
class ScriptFunc : public LeafNode
{
typedef LeafNode Parent;
protected:
// the function to call
StringTableEntry mScriptFunction;
// the arguments for the function
StringTableEntry mScriptArgs[MAX_COMMAND_ARGS];
// status to return if the command does not return a value
Status mDefaultReturnStatus;
public:
ScriptFunc();
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
static void initPersistFields();
// execute the command
Status evaluate(SimObject *owner);
DECLARE_CONOBJECT(ScriptFunc);
};
//---------------------------------------------------------------------------
// ScriptFunc task
//---------------------------------------------------------------------------
class ScriptFuncTask : public Task
{
typedef Task Parent;
protected:
virtual Task* update();
public:
ScriptFuncTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
};
} // namespace BadBehavior
#endif

View file

@ -0,0 +1,83 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "ScriptedBehavior.h"
#include "console/engineAPI.h"
#include "platform/profiler.h"
using namespace BadBehavior;
//------------------------------------------------------------------------------
// ScriptedBehavior node
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(ScriptedBehavior);
IMPLEMENT_CALLBACK( ScriptedBehavior, onEnter, void, ( SimObject* owner ), ( owner ),
"Called when the behavior is first run.\n"
"@param owner The object that this behavior tree belongs to." );
IMPLEMENT_CALLBACK( ScriptedBehavior, onExit, void, ( SimObject* owner ), ( owner ),
"Called when the behavior is complete.\n"
"@param owner The object that this behavior tree belongs to." );
IMPLEMENT_CALLBACK( ScriptedBehavior, precondition, bool, ( SimObject* owner ), ( owner ),
"Called prior to evaluating the behavior.\n"
"@param owner The object that this behavior tree belongs to.\n"
"A return value of false indicates that evaluation of the behavior should stop.\n"
"A return value of true indicates that evaluation of the behavior should continue.");
IMPLEMENT_CALLBACK( ScriptedBehavior, behavior, Status, ( SimObject* owner ), ( owner ),
"Evaluate the main behavior of this node.\n"
"@param owner The object that this behavior tree belongs to.\n");
ScriptedBehavior::ScriptedBehavior()
{
}
bool ScriptedBehavior::precondition( SimObject *owner )
{
PROFILE_SCOPE( ScriptedBehavior_precondition);
if(isMethod("precondition"))
return precondition_callback(owner);
return true;
}
void ScriptedBehavior::onEnter( SimObject *owner )
{
PROFILE_SCOPE( ScriptedBehavior_onEnter );
onEnter_callback(owner);
}
void ScriptedBehavior::onExit( SimObject *owner )
{
PROFILE_SCOPE( ScriptedBehavior_onExit );
onExit_callback(owner);
}
Status ScriptedBehavior::behavior( SimObject *owner )
{
PROFILE_SCOPE( ScriptedBehavior_behavior );
return behavior_callback( owner );
}

View file

@ -0,0 +1,56 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _BB_SCRIPTEDBEHAVIOR_H_
#define _BB_SCRIPTEDBEHAVIOR_H_
#ifndef _BB_CORE_H_
#include "BadBehavior/core/behavior.h"
#endif
namespace BadBehavior
{
//---------------------------------------------------------------------------
// ScriptedBehavior - A structured behavior leaf node which defines a series
// Of scripted callbacks
//---------------------------------------------------------------------------
class ScriptedBehavior : public Behavior
{
typedef Behavior Parent;
public:
ScriptedBehavior();
virtual bool precondition( SimObject *owner );
virtual void onEnter( SimObject *owner );
virtual void onExit( SimObject *owner );
virtual Status behavior( SimObject *owner );
DECLARE_CONOBJECT(ScriptedBehavior);
DECLARE_CALLBACK(void, onEnter, (SimObject *owner));
DECLARE_CALLBACK(void, onExit, (SimObject *owner));
DECLARE_CALLBACK(bool, precondition, (SimObject *owner));
DECLARE_CALLBACK(Status, behavior, (SimObject *owner));
};
} // namespace BadBehavior
#endif

View file

@ -0,0 +1,76 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "SubTree.h"
#include "console/consoleTypes.h"
using namespace BadBehavior;
//------------------------------------------------------------------------------
// SubTree node - links to another behavior tree
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(SubTree);
SubTree::SubTree()
: mSubTreeName(0)
{
}
void SubTree::initPersistFields()
{
addGroup( "Behavior" );
addField( "subTreeName", TypeString, Offset(mSubTreeName, SubTree),
"@brief The name of the behavior tree that this node links to. Max 255 characters." );
endGroup( "Behavior" );
Parent::initPersistFields();
}
Task *SubTree::createTask(SimObject &owner, BehaviorTreeRunner &runner)
{
if(!mSubTreeName || mSubTreeName[0] == 0)
{
Con::errorf("SubTree::onInitialize: no sub tree specified");
return NULL;
}
SimObject *subTreeNode;
if(!Sim::findObject(mSubTreeName, subTreeNode))
{
Con::errorf("SubTree:onInitialize: the specified sub tree does not exist");
return NULL;
}
Node *node = dynamic_cast<Node*>(subTreeNode);
if(!node)
{
Con::errorf("SubTree::onInitialize: the specified sub tree is not a behavior tree node");
return NULL;
}
return node->createTask(owner, runner);
}

View file

@ -0,0 +1,56 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _BB_SUBTREE_H_
#define _BB_SUBTREE_H_
#ifndef _BB_CORE_H_
#include "BadBehavior/core/Core.h"
#endif
namespace BadBehavior
{
//---------------------------------------------------------------------------
// SubTree decorator
// Turns a named Behavior into a subtree of this node.
// Does not actually have a child, so is a subclass of leaf
//---------------------------------------------------------------------------
class SubTree : public LeafNode
{
typedef LeafNode Parent;
protected:
const char* mSubTreeName;
public:
SubTree();
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
static void initPersistFields();
DECLARE_CONOBJECT(SubTree);
};
} // namespace BadBehavior
#endif

View file

@ -0,0 +1,115 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "Wait.h"
#include "BadBehavior/core/Runner.h"
#include "math/mMathFn.h"
#include "console/consoleTypes.h"
using namespace BadBehavior;
//------------------------------------------------------------------------------
// Wait leaf node
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(Wait);
Wait::Wait()
: mWaitMs(1000)
{
}
void Wait::initPersistFields()
{
addGroup( "Behavior" );
addProtectedField( "waitMs", TypeS32, Offset(mWaitMs, Wait), &_setWait, &defaultProtectedGetFn,
"The time in ms that the node should wait before completion." );
endGroup( "Behavior" );
Parent::initPersistFields();
}
bool Wait::_setWait(void *object, const char *index, const char *data)
{
Wait *node = static_cast<Wait *>( object );
node->mWaitMs = getMax(0, dAtoi( data ));
return false;
}
Task *Wait::createTask(SimObject &owner, BehaviorTreeRunner &runner)
{
return new WaitTask(*this, owner, runner);
}
//------------------------------------------------------------------------------
// Wait task
//------------------------------------------------------------------------------
WaitTask::WaitTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
: Parent(node, owner, runner),
mEventId(0)
{
}
WaitTask::~WaitTask()
{
cancelEvent();
}
void WaitTask::cancelEvent()
{
if(Sim::isEventPending(mEventId))
{
Sim::cancelEvent(mEventId);
mEventId = 0;
}
}
void WaitTask::onInitialize()
{
Parent::onInitialize();
cancelEvent();
}
void WaitTask::onTerminate()
{
Parent::onTerminate();
cancelEvent();
}
Task* WaitTask::update()
{
if(mStatus == RESUME)
{
mStatus = SUCCESS;
mIsComplete = true;
}
else if(mStatus == INVALID)
{
mEventId = Sim::postEvent(mRunner, new TaskReactivateEvent(*this), Sim::getCurrentTime() + static_cast<Wait*>(mNodeRep)->getWaitMs());
mStatus = SUSPENDED;
}
return NULL;
}

View file

@ -0,0 +1,80 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _BB_WAIT_H_
#define _BB_WAIT_H_
#ifndef _BB_CORE_H_
#include "BadBehavior/core/Core.h"
#endif
namespace BadBehavior
{
//---------------------------------------------------------------------------
// Wait leaf
// Pauses for a set time period.
//---------------------------------------------------------------------------
class Wait : public LeafNode
{
typedef LeafNode Parent;
protected:
static bool _setWait(void *object, const char *index, const char *data);
S32 mWaitMs;
public:
Wait();
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
static void initPersistFields();
S32 getWaitMs() const { return mWaitMs; }
DECLARE_CONOBJECT(Wait);
};
//---------------------------------------------------------------------------
// Wait leaf task
//---------------------------------------------------------------------------
class WaitTask : public Task
{
typedef Task Parent;
protected:
U32 mEventId;
virtual void onInitialize();
virtual void onTerminate();
virtual Task* update();
void cancelEvent();
public:
WaitTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
virtual ~WaitTask();
};
} // namespace BadBehavior
#endif

View file

@ -0,0 +1,145 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "WaitForSignal.h"
#include "BadBehavior/core/Runner.h"
#include "console/consoleTypes.h"
using namespace BadBehavior;
//------------------------------------------------------------------------------
// WaitForSignal leaf node
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(WaitForSignal);
WaitForSignal::WaitForSignal()
: mTimeoutMs(0)
{
}
void WaitForSignal::initPersistFields()
{
addGroup( "Behavior" );
addField( "signalName", TypeRealString, Offset(mSignalName, WaitForSignal),
"The time in ms that the node should wait before completion." );
addProtectedField( "timeoutMs", TypeS32, Offset(mTimeoutMs, WaitForSignal), &_setTimeout, &defaultProtectedGetFn,
"The maximum time in ms that the node should wait for the signal.\n"
"A value of 0 indicates no limit");
endGroup( "Behavior" );
Parent::initPersistFields();
}
Task *WaitForSignal::createTask(SimObject &owner, BehaviorTreeRunner &runner)
{
return new WaitForSignalTask(*this, owner, runner);
}
bool WaitForSignal::_setTimeout(void *object, const char *index, const char *data)
{
WaitForSignal *node = static_cast<WaitForSignal *>( object );
node->mTimeoutMs = getMax(0, dAtoi( data ));
return false;
}
//------------------------------------------------------------------------------
// Wait task
//------------------------------------------------------------------------------
WaitForSignalTask::WaitForSignalTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner)
: Parent(node, owner, runner),
mEventId(0)
{
}
WaitForSignalTask::~WaitForSignalTask()
{
unsubscribe();
cancelEvent();
}
void WaitForSignalTask::subscribe()
{
mRunner->subscribeToSignal(static_cast<WaitForSignal *>(mNodeRep)->getSignalName().c_str(), this);
}
void WaitForSignalTask::unsubscribe()
{
mRunner->unsubscribeFromSignal(static_cast<WaitForSignal *>(mNodeRep)->getSignalName().c_str(), this);
}
void WaitForSignalTask::onSignal()
{
onResume();
}
void WaitForSignalTask::onTimeout()
{
mStatus = FAILURE;
}
void WaitForSignalTask::cancelEvent()
{
if(mEventId != 0 && Sim::isEventPending(mEventId))
{
Sim::cancelEvent(mEventId);
mEventId = 0;
}
}
void WaitForSignalTask::onInitialize()
{
Parent::onInitialize();
subscribe();
cancelEvent();
}
void WaitForSignalTask::onTerminate()
{
Parent::onTerminate();
unsubscribe();
cancelEvent();
}
Task* WaitForSignalTask::update()
{
if(mStatus == RESUME)
{
mStatus = SUCCESS;
}
else if (mStatus == INVALID)
{
mStatus = SUSPENDED;
S32 timeout = static_cast<WaitForSignal *>(mNodeRep)->getTimeoutMs();
if(timeout > 0)
mEventId = Sim::postEvent(mRunner, new WaitForSignalTimeoutEvent(*this), Sim::getCurrentTime() + timeout);
}
if(mStatus == SUCCESS || mStatus == FAILURE)
mIsComplete = true;
return NULL;
}

View file

@ -0,0 +1,114 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _BB_WAITFORSIGNAL_H_
#define _BB_WAITFORSIGNAL_H_
#ifndef _BB_CORE_H_
#include "BadBehavior/core/Core.h"
#endif
#ifndef _BB_SIGNAL_H_
#include "BadBehavior/core/Signal.h"
#endif
#ifndef _SIMEVENTS_H_
#include "console/simEvents.h"
#endif
namespace BadBehavior
{
//---------------------------------------------------------------------------
// WaitForSignal leaf
// Waits until it receives the requested signal.
//---------------------------------------------------------------------------
class WaitForSignal : public LeafNode
{
typedef LeafNode Parent;
protected:
String mSignalName;
S32 mTimeoutMs;
static bool _setTimeout(void *object, const char *index, const char *data);
public:
WaitForSignal();
virtual Task *createTask(SimObject &owner, BehaviorTreeRunner &runner);
static void initPersistFields();
const String &getSignalName() const { return mSignalName; }
S32 getTimeoutMs() const { return mTimeoutMs; }
DECLARE_CONOBJECT(WaitForSignal);
};
//---------------------------------------------------------------------------
// WaitForSignal leaf task
//---------------------------------------------------------------------------
class WaitForSignalTask : public Task, public virtual SignalSubscriber
{
typedef Task Parent;
protected:
U32 mEventId;
virtual void onInitialize();
virtual void onTerminate();
virtual Task* update();
void cancelEvent();
// SignalSubscriber
virtual void subscribe();
virtual void unsubscribe();
public:
WaitForSignalTask(Node &node, SimObject &owner, BehaviorTreeRunner &runner);
virtual ~WaitForSignalTask();
// SignalSubscriber
virtual void onSignal();
// timeout
void onTimeout();
};
class WaitForSignalTimeoutEvent : public SimEvent
{
WaitForSignalTask *mTask;
public:
WaitForSignalTimeoutEvent(WaitForSignalTask &task)
{
mTask = &task;
}
void process( SimObject *object )
{
mTask->onTimeout();
}
};
} // namespace BadBehavior
#endif

View file

@ -0,0 +1,109 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#include "followBehaviorAction.h"
#include "T3D/aiPlayer.h"
using namespace BadBehavior;
//------------------------------------------------------------------------------
// FollowBehavior node
//------------------------------------------------------------------------------
IMPLEMENT_CONOBJECT(FollowBehaviorAction);
FollowBehaviorAction::FollowBehaviorAction()
{
}
bool FollowBehaviorAction::precondition( SimObject *owner )
{
PROFILE_SCOPE( FollowBehaviorAction_precondition);
// check that our owner is an AIPlayer
AIPlayer *aiPlayer = dynamic_cast<AIPlayer *>(owner);
if(!aiPlayer)
return false;
return true;
}
void FollowBehaviorAction::onEnter( SimObject *owner )
{
//PROFILE_SCOPE( FollowBehaviorAction_onEnter );
}
void FollowBehaviorAction::onExit( SimObject *owner )
{
//PROFILE_SCOPE( FollowBehaviorAction_onExit );
}
Status FollowBehaviorAction::behavior( SimObject *owner )
{
PROFILE_SCOPE( FollowBehaviorAction_behavior );
// get the owning AIPlayer object
AIPlayer *aiPlayer = dynamic_cast<AIPlayer *>(owner);
if(!aiPlayer)
return FAILURE;
// get the script-specified followObject
const char *followFieldName = StringTable->insert("followObject");
const char *followFieldValue = owner->getDataField(followFieldName, NULL);
if(!followFieldValue || !followFieldValue[0])
return FAILURE;
SimObject *followSimObj = Sim::findObject(dAtoi(followFieldValue));
if(!followSimObj)
return FAILURE;
// check that the follow object is a SceneObject
SceneObject *followObject = dynamic_cast<SceneObject *>(followSimObj);
if(!followObject)
return FAILURE;
// get the script-specified followDistance field
const char *distanceFieldName = StringTable->insert("followDistance");
const char *distanceFieldValue = owner->getDataField(distanceFieldName, NULL);
float followDistance = 1.f;
if(distanceFieldValue && distanceFieldValue[0])
followDistance = dAtof(distanceFieldValue);
// try and stay at followDistance from the followObject
Point3F targetPos = followObject->getPosition();
Point3F followVec = aiPlayer->getPosition() - targetPos;
// get current distance (ignore z component)
F32 curDist = Point3F(followVec.x, followVec.y, 0.f).len();
if(mFabs(curDist - followDistance) > aiPlayer->getMoveTolerance())
{
followVec.normalize();
followVec *= followDistance;
Point3F destination = targetPos + followVec;
aiPlayer->setMoveDestination(destination, true);
return RUNNING;
}
return SUCCESS;
}

View file

@ -0,0 +1,52 @@
//-----------------------------------------------------------------------------
// Copyright (c) 2014 Guy Allard
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
#ifndef _BB_FOLLOWBEHAVIORACTION_H_
#define _BB_FOLLOWBEHAVIORACTION_H_
#ifndef _BB_CORE_H_
#include "BadBehavior/core/behavior.h"
#endif
namespace BadBehavior
{
//---------------------------------------------------------------------------
// FollowBehaviorAction - Make an AIPlayer follow another object
// Demonstrates how to create a compiled behavior by subclassing Behavior
//---------------------------------------------------------------------------
class FollowBehaviorAction : public Behavior
{
typedef Behavior Parent;
public:
FollowBehaviorAction();
virtual bool precondition( SimObject *owner );
virtual void onEnter( SimObject *owner );
virtual void onExit( SimObject *owner );
virtual Status behavior( SimObject *owner );
DECLARE_CONOBJECT(FollowBehaviorAction);
};
} // namespace BadBehavior
#endif