mirror of
https://github.com/jmarshall23/DoomRTX.git
synced 2026-08-17 19:23:51 +02:00
Added typeinfogen with state system
This commit is contained in:
@@ -90,6 +90,7 @@ class idLocationEntity;
|
||||
void gameError( const char *fmt, ... );
|
||||
|
||||
#include "gamesys/Event.h"
|
||||
#include "gamesys/State.h"
|
||||
#include "gamesys/Class.h"
|
||||
#include "gamesys/SysCvar.h"
|
||||
#include "gamesys/SysCmds.h"
|
||||
|
||||
@@ -747,8 +747,6 @@ public:
|
||||
|
||||
private:
|
||||
void Event_Activate( idEntity *activator );
|
||||
void Event_Throw( void );
|
||||
void Event_ShakeObject( idEntity *object, int starttime );
|
||||
|
||||
int end_time;
|
||||
float throw_time;
|
||||
|
||||
@@ -229,8 +229,6 @@ public:
|
||||
protected:
|
||||
virtual void DoneMoving( void );
|
||||
virtual void BeginMove( idThread *thread = NULL );
|
||||
void SpawnTrigger( const idVec3 &pos );
|
||||
void GetLocalTriggerPosition();
|
||||
void Event_Touch( idEntity *other, trace_t *trace );
|
||||
|
||||
private:
|
||||
|
||||
@@ -639,7 +639,6 @@ private:
|
||||
idAngles GunTurningOffset( void );
|
||||
idVec3 GunAcceleratingOffset( void );
|
||||
|
||||
void UseObjects( void );
|
||||
void CrashLand( const idVec3 &oldOrigin, const idVec3 &oldVelocity );
|
||||
void BobCycle( const idVec3 &pushVelocity );
|
||||
void UpdateViewAngles( void );
|
||||
@@ -676,7 +675,6 @@ private:
|
||||
void Event_SelectWeapon( const char *weaponName );
|
||||
void Event_GetWeaponEntity( void );
|
||||
void Event_OpenPDA( void );
|
||||
void Event_PDAAvailable( void );
|
||||
void Event_InPDA( void );
|
||||
void Event_ExitTeleporter( void );
|
||||
void Event_HideTip( void );
|
||||
|
||||
@@ -221,7 +221,6 @@ private:
|
||||
|
||||
void FreeBeams();
|
||||
void Event_RemoveBeams();
|
||||
void ApplyDamage();
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
+10
-2
@@ -422,7 +422,6 @@ protected:
|
||||
void Think(void);
|
||||
void Activate(idEntity* activator);
|
||||
int ReactionTo(const idEntity* ent);
|
||||
bool CheckForEnemy(void);
|
||||
void EnemyDead(void);
|
||||
virtual bool CanPlayChatterSounds(void) const;
|
||||
void SetChatSound(void);
|
||||
@@ -485,7 +484,6 @@ protected:
|
||||
// effects
|
||||
const idDeclParticle* SpawnParticlesOnJoint(particleEmitter_t& pe, const char* particleName, const char* jointName);
|
||||
void SpawnParticles(const char* keyName);
|
||||
bool ParticlesActive(void);
|
||||
|
||||
// turning
|
||||
bool FacingIdeal(void);
|
||||
@@ -801,4 +799,14 @@ private:
|
||||
void Event_MarkUsed(void);
|
||||
};
|
||||
|
||||
class idAI_Vagary : public idAI {
|
||||
public:
|
||||
CLASS_PROTOTYPE(idAI_Vagary);
|
||||
|
||||
private:
|
||||
void Event_ChooseObjectToThrow(const idVec3& mins, const idVec3& maxs, float speed, float minDist, float offset);
|
||||
void Event_ThrowObjectAtEnemy(idEntity* ent, float speed);
|
||||
};
|
||||
|
||||
|
||||
#endif /* !__AI_H__ */
|
||||
|
||||
@@ -38,15 +38,6 @@ Vagary specific AI code
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
class idAI_Vagary : public idAI {
|
||||
public:
|
||||
CLASS_PROTOTYPE( idAI_Vagary );
|
||||
|
||||
private:
|
||||
void Event_ChooseObjectToThrow( const idVec3 &mins, const idVec3 &maxs, float speed, float minDist, float offset );
|
||||
void Event_ThrowObjectAtEnemy( idEntity *ent, float speed );
|
||||
};
|
||||
|
||||
const idEventDef AI_Vagary_ChooseObjectToThrow( "vagary_ChooseObjectToThrow", "vvfff", 'e' );
|
||||
const idEventDef AI_Vagary_ThrowObjectAtEnemy( "vagary_ThrowObjectAtEnemy", "ef" );
|
||||
|
||||
|
||||
@@ -97,6 +97,8 @@ public: \
|
||||
static idClass *CreateInstance( void ); \
|
||||
virtual idTypeInfo *GetType( void ) const; \
|
||||
static idTypeInfo &GetClassType( void ); \
|
||||
virtual intptr_t Invoke(const char* functionName, void *param1) override; \
|
||||
virtual bool HasNativeFunction(const char* functionName) override; \
|
||||
static idEventFunc<nameofclass> eventCallbacks[]
|
||||
|
||||
/*
|
||||
@@ -205,6 +207,28 @@ public:
|
||||
const char* GetSuperclass(void) const;
|
||||
void FindUninitializedMemory(void);
|
||||
|
||||
// jmarshall
|
||||
template< typename T >
|
||||
T* Cast(void)
|
||||
{
|
||||
return this ? (IsType(T::Type) ? static_cast<T*>(this) : NULL) : NULL;
|
||||
}
|
||||
|
||||
template< typename T >
|
||||
const T* Cast(void) const
|
||||
{
|
||||
return this ? (IsType(T::Type) ? static_cast<const T*>(this) : NULL) : NULL;
|
||||
}
|
||||
|
||||
virtual void StateThreadChanged(void) {};
|
||||
virtual idClass* InvokeChild()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
virtual intptr_t Invoke(const char* functionName, void* param1);
|
||||
virtual bool HasNativeFunction(const char* functionName);
|
||||
// jmarshall end
|
||||
|
||||
void Save(idSaveGame* savefile) const {};
|
||||
void Restore(idRestoreGame* savefile) {};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,496 @@
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "../Game_local.h"
|
||||
|
||||
const int HISTORY_COUNT = 50;
|
||||
|
||||
/*
|
||||
=====================
|
||||
stateParms_t::Wait
|
||||
=====================
|
||||
*/
|
||||
void stateParms_t::Wait( float seconds )
|
||||
{
|
||||
time = gameLocal.time + SEC2MS( seconds );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
stateParms_t::Save
|
||||
=====================
|
||||
*/
|
||||
void stateParms_t::Save( idSaveGame* saveFile ) const
|
||||
{
|
||||
saveFile->WriteInt( blendFrames );
|
||||
saveFile->WriteInt( time );
|
||||
saveFile->WriteInt( stage );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
stateParms_t::Restore
|
||||
=====================
|
||||
*/
|
||||
void stateParms_t::Restore( idRestoreGame* saveFile )
|
||||
{
|
||||
saveFile->ReadInt( blendFrames );
|
||||
saveFile->ReadInt( time );
|
||||
saveFile->ReadInt( stage );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
stateCall_t::Save
|
||||
=====================
|
||||
*/
|
||||
void stateCall_t::Save( idSaveGame* saveFile ) const
|
||||
{
|
||||
saveFile->WriteString( state );
|
||||
// TOSAVE: idLinkList<stateCall_t> node;
|
||||
saveFile->WriteInt( flags );
|
||||
saveFile->WriteInt( delay );
|
||||
parms.Save( saveFile );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
stateCall_t::Save
|
||||
=====================
|
||||
*/
|
||||
void stateCall_t::Restore( idRestoreGame* saveFile, const idClass* owner )
|
||||
{
|
||||
saveFile->ReadString( state );
|
||||
saveFile->ReadInt( flags );
|
||||
saveFile->ReadInt( delay );
|
||||
parms.Restore( saveFile );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::rvStateThread
|
||||
=====================
|
||||
*/
|
||||
rvStateThread::rvStateThread( void )
|
||||
{
|
||||
owner = NULL;
|
||||
insertAfter = NULL;
|
||||
lastResult = SRESULT_DONE;
|
||||
|
||||
states.Clear( );
|
||||
interrupted.Clear( );
|
||||
|
||||
memset( &fl, 0, sizeof( fl ) );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::~rvStateThread
|
||||
=====================
|
||||
*/
|
||||
rvStateThread::~rvStateThread( void )
|
||||
{
|
||||
Clear( true );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::SetOwner
|
||||
=====================
|
||||
*/
|
||||
void rvStateThread::SetOwner( idClass* _owner )
|
||||
{
|
||||
owner = _owner;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::Post
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvStateThread::PostState( const char* name, int blendFrames, int delay, int flags )
|
||||
{
|
||||
stateCall_t* call;
|
||||
call = new stateCall_t;
|
||||
call->state = name;
|
||||
call->delay = delay;
|
||||
call->flags = flags;
|
||||
call->parms.blendFrames = blendFrames;
|
||||
call->parms.time = -1;
|
||||
call->parms.stage = 0;
|
||||
call->parms.substage = 0;
|
||||
call->parms.param1 = 0;
|
||||
call->parms.param2 = 0;
|
||||
|
||||
call->parms.subparam1 = 0;
|
||||
call->parms.subparam2 = 0;
|
||||
|
||||
call->node.SetOwner( call );
|
||||
|
||||
if( fl.executing && insertAfter )
|
||||
{
|
||||
call->node.InsertAfter( insertAfter->node );
|
||||
}
|
||||
else
|
||||
{
|
||||
call->node.AddToEnd( states );
|
||||
}
|
||||
|
||||
insertAfter = call;
|
||||
|
||||
return SRESULT_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::Set
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvStateThread::SetState( const char* name, int blendFrames, int delay, int flags )
|
||||
{
|
||||
Clear( );
|
||||
return PostState( name, blendFrames, delay, flags );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::InterruptState
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvStateThread::InterruptState( const char* name, int blendFrames, int delay, int flags )
|
||||
{
|
||||
stateCall_t* call;
|
||||
|
||||
// Move all states to the front of the interrupted list in the same order
|
||||
for( call = states.Prev(); call; call = states.Prev() )
|
||||
{
|
||||
call->node.Remove( );
|
||||
call->node.AddToFront( interrupted );
|
||||
}
|
||||
|
||||
// Nothing to insert after anymore
|
||||
insertAfter = NULL;
|
||||
fl.stateInterrupted = true;
|
||||
|
||||
// Post the state now
|
||||
return PostState( name, blendFrames, delay, flags );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::CurrentStateIs
|
||||
=====================
|
||||
*/
|
||||
bool rvStateThread::CurrentStateIs( const char* name ) const
|
||||
{
|
||||
return ( !IsIdle() ) ? name == GetState()->state : false;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::Clear
|
||||
=====================
|
||||
*/
|
||||
void rvStateThread::Clear( bool ignoreStateCalls )
|
||||
{
|
||||
stateCall_t* call;
|
||||
|
||||
// Clear all states from the main state list
|
||||
for( call = states.Next(); call != NULL; call = states.Next() )
|
||||
{
|
||||
if( !ignoreStateCalls && ( call->flags & ( SFLAG_ONCLEAR | SFLAG_ONCLEARONLY ) ) )
|
||||
{
|
||||
//owner->ProcessState ( call->state, call->parms );
|
||||
//owner->SetStateParms(call->parms);
|
||||
owner->Invoke( call->state, &call->parms );
|
||||
}
|
||||
call->node.Remove();
|
||||
delete call;
|
||||
}
|
||||
|
||||
// Clear all interrupted states
|
||||
for( call = interrupted.Next(); call != NULL; call = interrupted.Next() )
|
||||
{
|
||||
if( !ignoreStateCalls && ( call->flags & ( SFLAG_ONCLEAR | SFLAG_ONCLEARONLY ) ) )
|
||||
{
|
||||
//owner->ProcessState ( call->state, call->parms );
|
||||
// owner->SetStateParms(call->parms);
|
||||
owner->Invoke( call->state, &call->parms );
|
||||
}
|
||||
call->node.Remove();
|
||||
delete call;
|
||||
}
|
||||
|
||||
insertAfter = NULL;
|
||||
fl.stateCleared = true;
|
||||
|
||||
states.Clear( );
|
||||
interrupted.Clear( );
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::Execute
|
||||
=====================
|
||||
*/
|
||||
stateResult_t rvStateThread::Execute( void )
|
||||
{
|
||||
stateCall_t* call = NULL;
|
||||
int count;
|
||||
const char* stateName;
|
||||
int stateStage;
|
||||
const char* historyState[HISTORY_COUNT];
|
||||
int historyStage[HISTORY_COUNT];
|
||||
int historyStart;
|
||||
int historyEnd;
|
||||
|
||||
// If our main state loop is empty copy over any states in the interrupted state
|
||||
if( !states.Next( ) )
|
||||
{
|
||||
for( call = interrupted.Next(); call; call = interrupted.Next() )
|
||||
{
|
||||
call->node.Remove( );
|
||||
call->node.AddToEnd( states );
|
||||
}
|
||||
assert( !interrupted.Next( ) );
|
||||
}
|
||||
|
||||
// State thread is idle if there are no states
|
||||
if( !states.Next() )
|
||||
{
|
||||
return SRESULT_IDLE;
|
||||
}
|
||||
|
||||
fl.executing = true;
|
||||
|
||||
// Run through the states until there are no more or one of them tells us to wait
|
||||
count = 0;
|
||||
historyStart = 0;
|
||||
historyEnd = 0;
|
||||
|
||||
for( call = states.Next(); call && count < HISTORY_COUNT; call = states.Next(), ++count )
|
||||
{
|
||||
insertAfter = call;
|
||||
fl.stateCleared = false;
|
||||
fl.stateInterrupted = false;
|
||||
|
||||
// If this state is only called when being cleared then just skip it
|
||||
if( call->flags & SFLAG_ONCLEARONLY )
|
||||
{
|
||||
call->node.Remove( );
|
||||
delete call;
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the call has a delay on it the time will be set to negative initially and then
|
||||
// converted to game time.
|
||||
if( call->parms.time <= 0 )
|
||||
{
|
||||
call->parms.time = gameLocal.time;
|
||||
}
|
||||
|
||||
// Check for delayed states
|
||||
if( gameLocal.time < call->parms.time + call->delay )
|
||||
{
|
||||
fl.executing = false;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
|
||||
// Debugging
|
||||
if( lastResult != SRESULT_WAIT )
|
||||
{
|
||||
// Keep a history of the called states so we can dump them on an overflow
|
||||
historyState[historyEnd] = call->state;
|
||||
historyStage[historyEnd] = call->parms.stage;
|
||||
historyEnd = ( historyEnd + 1 ) % HISTORY_COUNT;
|
||||
if( historyEnd == historyStart )
|
||||
{
|
||||
historyStart = ( historyEnd + 1 ) % HISTORY_COUNT;
|
||||
}
|
||||
}
|
||||
|
||||
// Cache name and stage for error messages
|
||||
stateName = call->state;
|
||||
stateStage = call->parms.stage;
|
||||
|
||||
if( g_debugState.GetBool() )
|
||||
{
|
||||
if( call->parms.stage )
|
||||
{
|
||||
gameLocal.Printf( "%s: %s (%d)\n", ((idEntity *)owner)->GetClassname(), call->state.c_str(), call->parms.stage );
|
||||
}
|
||||
else
|
||||
{
|
||||
gameLocal.Printf( "%s: %s\n", ((idEntity*)owner)->GetClassname(), call->state.c_str() );
|
||||
}
|
||||
}
|
||||
|
||||
// Actually call the state function
|
||||
lastResult = ( stateResult_t )owner->Invoke( call->state, &call->parms );
|
||||
switch( lastResult )
|
||||
{
|
||||
case SRESULT_DONE_FRAME:
|
||||
fl.executing = false;
|
||||
return SRESULT_DONE;
|
||||
case SRESULT_WAIT:
|
||||
fl.executing = false;
|
||||
return SRESULT_WAIT;
|
||||
|
||||
case SRESULT_ERROR:
|
||||
gameLocal.Error( "rvStateThread: error reported by state '%s (%d)'", stateName, stateStage );
|
||||
fl.executing = false;
|
||||
return SRESULT_ERROR;
|
||||
}
|
||||
|
||||
if (lastResult == SRESULT_DONE) {
|
||||
owner->StateThreadChanged();
|
||||
}
|
||||
|
||||
// Dont remove the node if it was interrupted or cleared in the last process
|
||||
if( !fl.stateCleared && !fl.stateInterrupted )
|
||||
{
|
||||
if( lastResult >= SRESULT_SETDELAY )
|
||||
{
|
||||
call->delay = lastResult - SRESULT_SETDELAY;
|
||||
call->parms.time = gameLocal.GetTime();
|
||||
continue;
|
||||
}
|
||||
else if( lastResult >= SRESULT_SETSTAGE )
|
||||
{
|
||||
call->parms.stage = lastResult - SRESULT_SETSTAGE;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Done with state so remove it from list
|
||||
call->node.Remove( );
|
||||
delete call;
|
||||
}
|
||||
|
||||
// Finished the last state but wait a frame for next one
|
||||
if( lastResult == SRESULT_DONE_WAIT )
|
||||
{
|
||||
fl.executing = false;
|
||||
return SRESULT_WAIT;
|
||||
}
|
||||
}
|
||||
|
||||
// Runaway state loop?
|
||||
if( count >= HISTORY_COUNT )
|
||||
{
|
||||
idFile* file;
|
||||
|
||||
fileSystem->RemoveFile( "statedump.txt" );
|
||||
file = fileSystem->OpenFileWrite( "statedump.txt" );
|
||||
|
||||
for( ; historyStart != historyEnd; historyStart = ( historyStart + 1 ) % HISTORY_COUNT )
|
||||
{
|
||||
if( historyStage[historyStart] )
|
||||
{
|
||||
gameLocal.Printf( "rvStateThread: %s (%d)\n", historyState[historyStart], historyStage[historyStart] );
|
||||
}
|
||||
else
|
||||
{
|
||||
gameLocal.Printf( "rvStateThread: %s\n", historyState[historyStart] );
|
||||
}
|
||||
if( file )
|
||||
{
|
||||
if( historyStage[historyStart] )
|
||||
{
|
||||
file->Printf( "rvStateThread: %s (%d)\n", historyState[historyStart], historyStage[historyStart] );
|
||||
}
|
||||
else
|
||||
{
|
||||
file->Printf( "rvStateThread: %s\n", historyState[historyStart] );
|
||||
}
|
||||
}
|
||||
}
|
||||
if( file )
|
||||
{
|
||||
fileSystem->CloseFile( file );
|
||||
}
|
||||
|
||||
gameLocal.Error( "rvStateThread: run away state loop '%s'", name.c_str() );
|
||||
}
|
||||
|
||||
insertAfter = NULL;
|
||||
fl.executing = false;
|
||||
|
||||
// Move interrupted states back into the main state list when the main state list is empty
|
||||
if( !states.Next() && interrupted.Next( ) )
|
||||
{
|
||||
return Execute( );
|
||||
}
|
||||
|
||||
return lastResult;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::Save
|
||||
=====================
|
||||
*/
|
||||
void rvStateThread::Save( idSaveGame* saveFile ) const
|
||||
{
|
||||
saveFile->WriteString( name.c_str() );
|
||||
|
||||
// No need to save owner, its setup in restore
|
||||
|
||||
saveFile->WriteInt( lastResult );
|
||||
saveFile->Write( &fl, sizeof( fl ) );
|
||||
|
||||
saveFile->WriteInt( states.Num() );
|
||||
for( idLinkList<stateCall_t>* node = states.NextNode(); node; node = node->NextNode() )
|
||||
{
|
||||
node->Owner()->Save( saveFile );
|
||||
}
|
||||
|
||||
saveFile->WriteInt( interrupted.Num() );
|
||||
for( idLinkList<stateCall_t>* node = interrupted.NextNode(); node; node = node->NextNode() )
|
||||
{
|
||||
node->Owner()->Save( saveFile );
|
||||
}
|
||||
|
||||
// TOSAVE: stateCall_t* insertAfter;
|
||||
// TOSAVE: stateResult_t lastResult;
|
||||
}
|
||||
|
||||
/*
|
||||
=====================
|
||||
rvStateThread::Restore
|
||||
=====================
|
||||
*/
|
||||
void rvStateThread::Restore( idRestoreGame* saveFile, idClass* owner )
|
||||
{
|
||||
int numStates;
|
||||
stateCall_t* call = NULL;
|
||||
|
||||
saveFile->ReadString( name );
|
||||
|
||||
this->owner = owner;
|
||||
|
||||
saveFile->ReadInt( ( int& )lastResult );
|
||||
saveFile->Read( &fl, sizeof( fl ) );
|
||||
|
||||
saveFile->ReadInt( numStates );
|
||||
for( ; numStates > 0; numStates-- )
|
||||
{
|
||||
call = new stateCall_t;
|
||||
assert( call );
|
||||
|
||||
call->Restore( saveFile, owner );
|
||||
|
||||
call->node.SetOwner( call );
|
||||
call->node.AddToEnd( states );
|
||||
}
|
||||
|
||||
saveFile->ReadInt( numStates );
|
||||
for( ; numStates > 0; numStates-- )
|
||||
{
|
||||
call = new stateCall_t;
|
||||
assert( call );
|
||||
|
||||
call->Restore( saveFile, owner );
|
||||
|
||||
call->node.SetOwner( call );
|
||||
call->node.AddToEnd( interrupted );
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
#ifndef __SYS_STATE_H__
|
||||
#define __SYS_STATE_H__
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SRESULT_OK, // Call was made successfully
|
||||
SRESULT_ERROR, // An unrecoverable error occurred
|
||||
SRESULT_DONE, // Done with current state, move to next
|
||||
SRESULT_DONE_WAIT, // Done with current state, wait a frame then move to next
|
||||
SRESULT_WAIT, // Wait a frame and re-run current state
|
||||
SRESULT_IDLE, // State thread is currently idle (ie. no states)
|
||||
SRESULT_SETSTAGE, // Sets the current stage of the current state and reruns the state
|
||||
SRESULT_DONE_FRAME,
|
||||
// NOTE: this has to be the last result becuase the stage is added to
|
||||
// the result.
|
||||
SRESULT_SETDELAY = SRESULT_SETSTAGE + 20
|
||||
} stateResult_t;
|
||||
|
||||
#define MAX_STATE_CALLS 50
|
||||
|
||||
#define SRESULT_STAGE(x) ((stateResult_t)((int)SRESULT_SETSTAGE + (int)(x)))
|
||||
#define SRESULT_DELAY(x) ((stateResult_t)((int)SRESULT_SETDELAY + (int)(x)))
|
||||
|
||||
struct stateParms_t
|
||||
{
|
||||
int blendFrames;
|
||||
int time;
|
||||
int stage;
|
||||
int substage;
|
||||
float param1;
|
||||
float param2;
|
||||
|
||||
float subparam1;
|
||||
float subparam2;
|
||||
|
||||
|
||||
void Wait( float seconds );
|
||||
|
||||
void Save( idSaveGame* saveFile ) const;
|
||||
void Restore( idRestoreGame* saveFile );
|
||||
};
|
||||
|
||||
/*
|
||||
================
|
||||
CLASS_STATES_PROTOTYPE
|
||||
|
||||
This macro must be included in the definition of any subclass of idClass that
|
||||
wishes to have its own custom states. Its prototypes variables used in the process
|
||||
of managing states.
|
||||
================
|
||||
*/
|
||||
#define CLASS_STATES_PROTOTYPE(nameofclass) \
|
||||
protected: \
|
||||
static rvStateFunc<nameofclass> stateCallbacks[]
|
||||
|
||||
/*
|
||||
================
|
||||
CLASS_STATES_DECLARATION
|
||||
|
||||
This macro must be included in the code to properly initialize variables
|
||||
used in state processing for a idClass dervied class
|
||||
================
|
||||
*/
|
||||
#define CLASS_STATES_DECLARATION(nameofclass) \
|
||||
rvStateFunc<nameofclass> nameofclass::stateCallbacks[] = {
|
||||
|
||||
/*
|
||||
================
|
||||
STATE
|
||||
|
||||
This macro declares a single state. It must be surrounded by the CLASS_STATES_DECLARATION
|
||||
and END_CLASS_STATES macros.
|
||||
================
|
||||
*/
|
||||
#define STATE(statename,function) { statename, (stateCallback_t)( &function ) },
|
||||
|
||||
/*
|
||||
================
|
||||
END_CLASS_STATES
|
||||
|
||||
Terminates a state block
|
||||
================
|
||||
*/
|
||||
#define END_CLASS_STATES { NULL, NULL } };
|
||||
|
||||
struct stateCall_t
|
||||
{
|
||||
idStr state;
|
||||
idLinkList<stateCall_t> node;
|
||||
int flags;
|
||||
int delay;
|
||||
stateParms_t parms;
|
||||
|
||||
void Save( idSaveGame* saveFile ) const;
|
||||
void Restore( idRestoreGame* saveFile, const idClass* owner );
|
||||
};
|
||||
|
||||
class idClass;
|
||||
|
||||
const int SFLAG_ONCLEAR = BIT( 0 ); // Executes, even if the state queue is cleared
|
||||
const int SFLAG_ONCLEARONLY = BIT( 1 ); // Executes only if the state queue is cleared
|
||||
|
||||
class rvStateThread
|
||||
{
|
||||
public:
|
||||
|
||||
rvStateThread( void );
|
||||
~rvStateThread( void );
|
||||
|
||||
void SetName( const char* name );
|
||||
void SetOwner( idClass* owner );
|
||||
|
||||
bool Interrupt( void );
|
||||
|
||||
stateResult_t InterruptState( const char* state, int blendFrames = 0, int delay = 0, int flags = 0 );
|
||||
stateResult_t PostState( const char* state, int blendFrames = 0, int delay = 0, int flags = 0 );
|
||||
stateResult_t SetState( const char* state, int blendFrames = 0, int delay = 0, int flags = 0 );
|
||||
stateCall_t* GetState( void ) const;
|
||||
bool CurrentStateIs( const char* name ) const;
|
||||
|
||||
stateResult_t Execute( void );
|
||||
|
||||
void Clear( bool ignoreStateCalls = false );
|
||||
|
||||
bool IsIdle( void ) const;
|
||||
bool IsExecuting( void ) const;
|
||||
|
||||
void Save( idSaveGame* saveFile ) const;
|
||||
void Restore( idRestoreGame* saveFile, idClass* owner );
|
||||
|
||||
protected:
|
||||
|
||||
struct flags
|
||||
{
|
||||
bool stateCleared : 1; // State list was cleared
|
||||
bool stateInterrupted : 1; // State list was interrupted
|
||||
bool executing : 1; // Execute is currently processing states
|
||||
} fl;
|
||||
|
||||
idStr name;
|
||||
idClass* owner;
|
||||
idLinkList<stateCall_t> states;
|
||||
idLinkList<stateCall_t> interrupted;
|
||||
stateCall_t* insertAfter;
|
||||
stateResult_t lastResult;
|
||||
};
|
||||
|
||||
ID_INLINE void rvStateThread::SetName( const char* _name )
|
||||
{
|
||||
name = _name;
|
||||
}
|
||||
|
||||
ID_INLINE stateCall_t* rvStateThread::GetState( void ) const
|
||||
{
|
||||
return states.Next();
|
||||
}
|
||||
|
||||
ID_INLINE bool rvStateThread::IsIdle( void ) const
|
||||
{
|
||||
return !states.Next() && !interrupted.Next();
|
||||
}
|
||||
|
||||
ID_INLINE bool rvStateThread::IsExecuting( void ) const
|
||||
{
|
||||
return fl.executing;
|
||||
}
|
||||
|
||||
#endif // __SYS_STATE_H__
|
||||
Reference in New Issue
Block a user