#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