791 lines
18 KiB
C++
791 lines
18 KiB
C++
#ifndef _SEQUENCER_ACTION_HPP
|
|
#define _SEQUENCER_ACTION_HPP
|
|
//-----------------------------------------------------------------------------
|
|
// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
|
|
//
|
|
// action.hpp
|
|
//
|
|
// Description: An atomic unit of execution in the Sequencer, the Action class
|
|
// is the base class for all logical actions that operate on
|
|
// a character for movement and animation.
|
|
//
|
|
// Modification History:
|
|
// + Created Aug 14, 2001 -- Gary Keong
|
|
// - Snapshot from Hair Club (rev 1) Owner: Laurent Ancessi
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//---------------------------------------------------------------------
|
|
// Includes
|
|
//---------------------------------------------------------------------
|
|
|
|
//========================================
|
|
// Nested Includes
|
|
//========================================
|
|
#include <memory/memorypool.h>
|
|
#include <p3d/memory.hpp>
|
|
|
|
#include <ai/sequencer/task.h>
|
|
#include <ai/statemanager.h>
|
|
#include <p3d/p3dtypes.hpp>
|
|
#include <events/eventenum.h>
|
|
#include <events/eventmanager.h>
|
|
|
|
#include <worldsim/character/charactercontroller.h>
|
|
#include <radmath/radmath.hpp>
|
|
#include <worldsim/redbrick/vehicle.h>
|
|
|
|
class tName;
|
|
|
|
class Action: public Task
|
|
{
|
|
public:
|
|
|
|
virtual ~Action();
|
|
|
|
virtual bool IsSlave() const;
|
|
|
|
virtual void WakeUp(float time);
|
|
virtual void DoSimulation(float time);
|
|
virtual void Update(float time);
|
|
virtual void Clear();
|
|
virtual void Abort() {};
|
|
|
|
// Pool allocators.
|
|
//
|
|
static void* operator new( size_t size )
|
|
{
|
|
void *memPtr = sMemoryPool.Allocate( size );
|
|
#ifdef RADLOAD_HEAP_DEBUGGING
|
|
radLoadHeapDebugAddAddress( memPtr );
|
|
#endif
|
|
return memPtr;
|
|
}
|
|
static void operator delete( void* deadObject, size_t size )
|
|
{
|
|
sMemoryPool.Free( deadObject, size );
|
|
//This is done in the radObject...
|
|
//#ifdef RADLOAD_HEAP_DEBUGGING
|
|
// radLoadHeapDebugRemoveAddress( deadObject );
|
|
//#endif
|
|
}
|
|
|
|
// Declared but not defined to prevent access.
|
|
static void* operator new[]( size_t size );
|
|
static void operator delete[]( void* pMemory );
|
|
|
|
private:
|
|
static FBMemoryPool sMemoryPool;
|
|
};
|
|
|
|
class SlaveAction: public Action
|
|
{
|
|
public:
|
|
|
|
virtual bool IsSlave() const;
|
|
};
|
|
namespace choreo
|
|
{
|
|
class AnimationDriver;
|
|
class RootTransformController;
|
|
class RootDriver;
|
|
class Locomotion;
|
|
class LocomotionDriver;
|
|
}
|
|
|
|
class TriggerEventAction
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
TriggerEventAction( EventEnum eventId, void* pUserData )
|
|
:
|
|
mEventId( eventId ),
|
|
mpUserData( pUserData )
|
|
{
|
|
}
|
|
virtual void WakeUp( float timeins )
|
|
{
|
|
GetEventManager()->TriggerEvent( mEventId, mpUserData );
|
|
Done( );
|
|
}
|
|
private:
|
|
EventEnum mEventId;
|
|
void* mpUserData;
|
|
};
|
|
|
|
|
|
class DelayAction
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
DelayAction( float timeins ) : mTime( timeins) { }
|
|
|
|
virtual void Update( float timeins )
|
|
{
|
|
mTime -= timeins;
|
|
if(mTime <= 0.0f)
|
|
{
|
|
Done( );
|
|
}
|
|
}
|
|
|
|
private:
|
|
float mTime;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class WalkerLocomotionAction
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class WalkerLocomotionAction : public SlaveAction
|
|
{
|
|
public:
|
|
WalkerLocomotionAction( Character* pCharacter );
|
|
~WalkerLocomotionAction( );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins);
|
|
virtual void Update( float timeins);
|
|
void PlayDriver(void);
|
|
void StopDriver(void);
|
|
|
|
void SetDesiredSpeed( float fSpeed )
|
|
{
|
|
mfDesiredSpeed = fSpeed;
|
|
}
|
|
|
|
void SwitchLocomotion(void);
|
|
|
|
choreo::LocomotionDriver* GetDriver(void) { return mpLocomotionDriver;}
|
|
|
|
void AllowIdle(bool b) { mAllowIdle = b; }
|
|
|
|
protected:
|
|
static rmt::Randomizer sRandom;
|
|
static bool sRandomSeeded;
|
|
|
|
float SolveActualDir( float fDesiredDir, float timeins );
|
|
float SolveActualSpeed( float fDesiredSpeed, float timeins );
|
|
|
|
float mfDesiredSpeed;
|
|
float mIdleTime;
|
|
float mNextIdle;
|
|
bool mAllowIdle : 1;
|
|
|
|
Character* mpCharacter;
|
|
|
|
choreo::Locomotion* mpLocomotion;
|
|
choreo::LocomotionDriver* mpLocomotionDriver;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class InCarAction : public Action
|
|
{
|
|
public:
|
|
InCarAction( Character* pCharacter );
|
|
~InCarAction( );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins);
|
|
virtual void Update( float timeins);
|
|
virtual void Clear( void );
|
|
|
|
protected:
|
|
void IWannaRock(bool);
|
|
|
|
Character* mpCharacter;
|
|
choreo::AnimationDriver* mpAnimationDriver;
|
|
bool mIsDriver : 1;
|
|
bool rockinIsMyBusiness : 1;
|
|
float timeBetweenBeats;
|
|
float timeSinceLastBeat;
|
|
float lastBeatValue;
|
|
|
|
float mIdleTime;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class HoldAnimationAction : public Action
|
|
{
|
|
public:
|
|
HoldAnimationAction( Character* pCharacter, const char* animName, float holdFrame);
|
|
~HoldAnimationAction( );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins);
|
|
virtual void Update( float timeins);
|
|
virtual void Clear( void );
|
|
|
|
protected:
|
|
virtual bool ShouldRelease(void) = 0;
|
|
|
|
Character* mpCharacter;
|
|
tUID mAnimUID;
|
|
choreo::AnimationDriver* mpAnimationDriver;
|
|
float mHoldFrame;
|
|
float mOrigFrames;
|
|
};
|
|
|
|
class SteerAction : public HoldAnimationAction
|
|
{
|
|
public:
|
|
|
|
SteerAction( Character* pCharacter, const char* anim, float frame);
|
|
|
|
protected:
|
|
virtual bool ShouldRelease(void);
|
|
|
|
};
|
|
|
|
class ReverseAction : public HoldAnimationAction
|
|
{
|
|
public:
|
|
ReverseAction( Character* pCharacter, const char* anim, float frame);
|
|
|
|
protected:
|
|
virtual bool ShouldRelease(void);
|
|
float mRelease;
|
|
|
|
};
|
|
|
|
class AccelAction : public HoldAnimationAction
|
|
{
|
|
public:
|
|
AccelAction( Character* pCharacter, const char* anim, float frame);
|
|
|
|
protected:
|
|
virtual bool ShouldRelease(void);
|
|
|
|
};
|
|
|
|
class DecelAction : public HoldAnimationAction
|
|
{
|
|
public:
|
|
DecelAction( Character* pCharacter, const char* anim, float frame);
|
|
|
|
protected:
|
|
virtual bool ShouldRelease(void);
|
|
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class JumpAction
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class JumpAction
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
JumpAction( Character* pCharacter, const char* name, float fUpVelocity );
|
|
virtual ~JumpAction( void );
|
|
enum eJumpState
|
|
{
|
|
NoTranslate = 1 << 16,
|
|
InitJump,
|
|
PostTurboJumpRecover,
|
|
IdleJump,
|
|
|
|
AllowTranslate = 1 << 17,
|
|
PreJump,
|
|
Jump,
|
|
PostJump,
|
|
JumpDone
|
|
};
|
|
virtual void WakeUp( float timeins );
|
|
float Reset( float fJumpHeight, bool bFalling = false );
|
|
void Reset( const rmt::Vector& jumpTarget, bool bFalling = false );
|
|
virtual void DoSimulation( float timeins );
|
|
virtual void Update( float timeins );
|
|
void TestForJumpAgain( const rmt::Vector& currentPos, float fUpVelocity, rmt::Vector& groundPos );
|
|
virtual void Clear( );
|
|
|
|
void SetRootTransform( void );
|
|
void SetRootPosition( const rmt::Vector& position );
|
|
bool IsInJump( void )
|
|
{
|
|
return mJumpState == Jump
|
|
// if we are in the PreJump state with no animation,
|
|
// then we are as good as jumping.
|
|
// had to do it for the launching platforms.
|
|
// Bounce.
|
|
//
|
|
|| ( mJumpState == PreJump && mpAnimationDriver == 0 )
|
|
|| ( mJumpState == PreJump && mbJumpAgain );
|
|
}
|
|
|
|
bool IsJumpState( eJumpState state )
|
|
{
|
|
return ( state == mJumpState );
|
|
}
|
|
const rmt::Vector& GetJumpVelocity( void ) const
|
|
{
|
|
return mVelocity;
|
|
}
|
|
|
|
float GetGravity( void ) const
|
|
{
|
|
return mfGravity;
|
|
}
|
|
|
|
protected:
|
|
void SetJumpVelocity( float fVelocity )
|
|
{
|
|
mVelocity.y = fVelocity;
|
|
}
|
|
float SolveActualDir( float fDesiredDir, float timeins );
|
|
float SolveActualSpeed( float fDesiredSpeed, float timeins );
|
|
private:
|
|
|
|
Character* mpCharacter;
|
|
eJumpState mJumpState;
|
|
rmt::Vector mVelocity;
|
|
tUID mAnimUid;
|
|
float mfTime;
|
|
float mfGravity;
|
|
float mfStartHeight;
|
|
float mfJumpHeight;
|
|
float mfMaxSpeed;
|
|
choreo::AnimationDriver* mpAnimationDriver;
|
|
choreo::RootTransformController* mpRootController;
|
|
choreo::RootDriver* mpRootDriver;
|
|
bool mbBoost : 1;
|
|
bool mbFalling : 1;
|
|
bool mbJumpAgain : 1;
|
|
bool mbTurboJump : 1;
|
|
bool mbInJumpKick : 1;
|
|
bool mbDoJumpKick : 1;
|
|
bool mbSlam : 1;
|
|
bool mbPreSlam : 1;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class DodgeAction
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class DodgeAction
|
|
:
|
|
public Action
|
|
{
|
|
|
|
public:
|
|
DodgeAction( Character* pCharacter );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins);
|
|
virtual void Update( float timeins);
|
|
virtual void Clear();
|
|
|
|
protected:
|
|
float SolveActualDir( float fDesiredDir, float timeins );
|
|
float SolveActualSpeed( float fDesiredSpeed, float timeins );
|
|
|
|
choreo::AnimationDriver* mpAnimationDriver; // stores handle for dodge animation
|
|
Character* mpCharacter;
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class CringeAction
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class CringeAction
|
|
:
|
|
public Action
|
|
{
|
|
|
|
public:
|
|
CringeAction( Character* pCharacter );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins);
|
|
virtual void Update( float timeins);
|
|
virtual void Clear();
|
|
|
|
protected:
|
|
float SolveActualDir( float fDesiredDir, float timeins );
|
|
float SolveActualSpeed( float fDesiredSpeed, float timeins );
|
|
choreo::AnimationDriver* mpAnimationDriver; // stores handle for dodge animation
|
|
Character* mpCharacter;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class FlailAction
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class FlailAction
|
|
:
|
|
public Action
|
|
{
|
|
|
|
public:
|
|
FlailAction( Character* pCharacter );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins);
|
|
virtual void Update( float timeins);
|
|
virtual void Clear();
|
|
|
|
|
|
protected:
|
|
float SolveActualDir( float fDesiredDir, float timeins );
|
|
float SolveActualSpeed( float fDesiredSpeed, float timeins );
|
|
|
|
choreo::AnimationDriver* mpAnimationDriver; // stores handle for dodge animation
|
|
Character* mpCharacter;
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class GetUpAction
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class GetUpAction
|
|
:
|
|
public Action
|
|
{
|
|
|
|
public:
|
|
GetUpAction( Character* pCharacter );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins);
|
|
virtual void Update( float timeins);
|
|
virtual void Clear();
|
|
|
|
protected:
|
|
float SolveActualDir( float fDesiredDir, float timeins );
|
|
float SolveActualSpeed( float fDesiredSpeed, float timeins );
|
|
choreo::AnimationDriver* mpAnimationDriver; // stores handle for dodge animation
|
|
Character* mpCharacter;
|
|
};
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class PlayAnimationAction
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class PlayAnimationAction: public Action
|
|
{
|
|
public:
|
|
PlayAnimationAction( Character* pCharacter, const char* anim, float fFrameRate = 30.0f );
|
|
PlayAnimationAction( Character* pCharacter, const tName& anim, float fFrameRate = 30.0f );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins );
|
|
virtual void Update( float timeins );
|
|
virtual void Clear( void );
|
|
void AbortWhenMovementOccurs( bool abort );
|
|
void SetLoop(bool b) { loop = b;}
|
|
|
|
private:
|
|
PlayAnimationAction( void );
|
|
|
|
protected:
|
|
virtual bool ShouldAbort(void);
|
|
|
|
Character* mpCharacter;
|
|
tUID mAnimUID;
|
|
float mfFrameRate;
|
|
choreo::AnimationDriver* mpAnimationDriver;
|
|
bool mbAbortWhenMovementOccurs : 1;
|
|
bool loop : 1;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class PlayIdleAnimationAction
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class PlayIdleAnimationAction: public PlayAnimationAction
|
|
{
|
|
public:
|
|
PlayIdleAnimationAction( Character* pCharacter, const char* anim, float fFrameRate = 30.0f );
|
|
PlayIdleAnimationAction( Character* pCharacter, const tName& anim, float fFrameRate = 30.0f );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void Clear( void );
|
|
virtual void Abort( void );
|
|
|
|
private:
|
|
PlayIdleAnimationAction( void );
|
|
|
|
protected:
|
|
};
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class CarDoorAction
|
|
//
|
|
// Action for opening and closing car doors
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
class Sequencer;
|
|
|
|
class CarDoorAction: public Action
|
|
{
|
|
public:
|
|
CarDoorAction( Vehicle* vehicle, Vehicle::DoorAction, Vehicle::Door, float delay, float timeins, Character* character = NULL, Sequencer* seq = NULL);
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins );
|
|
virtual void Update( float timeins );
|
|
virtual void Clear( void );
|
|
|
|
private:
|
|
CarDoorAction( void );
|
|
|
|
Vehicle* mpVehicle;
|
|
Vehicle::DoorAction mAction;
|
|
Vehicle::Door mDoor;
|
|
float mTime;
|
|
float mDelay;
|
|
float mCurrentTime;
|
|
|
|
Character* character;
|
|
Sequencer* sequencer;
|
|
};
|
|
|
|
class ReleaseDoorsAction: public Action
|
|
{
|
|
public:
|
|
ReleaseDoorsAction( Vehicle* v ) : mVehicle(v) {};
|
|
virtual void Update( float timeins );
|
|
|
|
protected:
|
|
Vehicle* mVehicle;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class Arrive
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class Arrive
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
Arrive( Character* pCharacter, rmt::Vector& destination, bool strict = false );
|
|
virtual ~Arrive( void );
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins );
|
|
virtual void Update( float timeins );
|
|
virtual void Clear( );
|
|
protected:
|
|
private:
|
|
Character* mpCharacter;
|
|
rmt::Vector mDestination;
|
|
float mfDecelTime;
|
|
float mfMaxSpeed;
|
|
float mEstTime;
|
|
float mElapsedTime;
|
|
bool mbSolveState : 1;
|
|
bool mbPrevLocoMode : 1;
|
|
bool mStrict : 1;
|
|
};
|
|
|
|
class FragileArrive : public Arrive
|
|
{
|
|
public:
|
|
FragileArrive( Character* pCharacter, rmt::Vector& destination, bool strict = false ) :
|
|
Arrive( pCharacter, destination, strict ) {}
|
|
bool IsSlave() const { return true; }
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class Orient
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class Orient
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
Orient( Character* pCharacter, rmt::Vector& facing );
|
|
virtual ~Orient( void );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins );
|
|
virtual void Update( float timeins );
|
|
protected:
|
|
private:
|
|
Character* mpCharacter;
|
|
float mfTarget;
|
|
};
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class Position
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class Position
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
Position( Character* pCharacter, rmt::Vector& position, float fDuration, bool local = false );
|
|
virtual ~Position( void );
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins );
|
|
virtual void Update( float timeins );
|
|
protected:
|
|
private:
|
|
Character* mpCharacter;
|
|
rmt::Vector mDestination;
|
|
float mfDuration;
|
|
float mfTimeLeft;
|
|
bool mLocal : 1;
|
|
};
|
|
|
|
class GroundSnap
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
GroundSnap( Character* pCharacter) : mpCharacter( pCharacter ) {}
|
|
virtual ~GroundSnap( void ) {}
|
|
|
|
virtual void WakeUp( float timeins );
|
|
virtual void DoSimulation( float timeins ) {}
|
|
virtual void Update( float timeins ) {}
|
|
protected:
|
|
private:
|
|
Character* mpCharacter;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// class AssignValueToFloat
|
|
//
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
class AssignValueToFloat
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
AssignValueToFloat( float& refFloat, float fValue )
|
|
:
|
|
mRefFloat( refFloat ),
|
|
mfValue( fValue )
|
|
{
|
|
}
|
|
virtual void WakeUp( float timeins )
|
|
{
|
|
mRefFloat = mfValue;
|
|
Done( );
|
|
}
|
|
private:
|
|
float& mRefFloat;
|
|
float mfValue;
|
|
};
|
|
|
|
|
|
class ChangeLocomotion
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
enum LocoType { INCAR, WALKING };
|
|
|
|
ChangeLocomotion( Character* c, LocoType type) : mpCharacter(c), mType(type) { }
|
|
|
|
virtual void Update( float timeins );
|
|
|
|
private:
|
|
Character* mpCharacter;
|
|
LocoType mType;
|
|
};
|
|
|
|
|
|
class ChangeNPCControllerState
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
ChangeNPCControllerState( Character* c, NPCController::State state) : mpCharacter(c), mState(state) { }
|
|
virtual void Update( float timeins );
|
|
virtual void Abort( void );
|
|
private:
|
|
Character* mpCharacter;
|
|
NPCController::State mState;
|
|
};
|
|
|
|
|
|
class KickAction
|
|
:
|
|
public SlaveAction
|
|
{
|
|
public:
|
|
KickAction( Character* c, float contact) : mpCharacter(c), mTime(0.0f), mContact(contact) { }
|
|
|
|
virtual void Update( float timeins );
|
|
|
|
private:
|
|
Character* mpCharacter;
|
|
float mTime;
|
|
float mContact;
|
|
};
|
|
|
|
class SurfAction : public PlayAnimationAction
|
|
{
|
|
public:
|
|
SurfAction(Character*);
|
|
|
|
protected:
|
|
unsigned mLowCount;
|
|
bool ShouldAbort(void);
|
|
void Update(float);
|
|
};
|
|
|
|
template <class STATE> class ChangeState
|
|
:
|
|
public Action
|
|
{
|
|
public:
|
|
ChangeState( Character* c) : mpCharacter(c) { }
|
|
|
|
virtual void Update( float timeins )
|
|
{
|
|
CharacterAi::SetState<STATE>( mpCharacter->GetStateManager() );
|
|
Done();
|
|
}
|
|
|
|
private:
|
|
Character* mpCharacter;
|
|
};
|
|
|
|
|
|
#endif // HC_SEQUENCER_ACTION_HPP
|