Initial commit.

This commit is contained in:
Jim Gray
2013-04-04 14:32:05 -07:00
parent ba5c81da32
commit d71d53e8ec
2180 changed files with 1393544 additions and 1 deletions

586
code/icarus/BlockStream.cpp Normal file
View File

@@ -0,0 +1,586 @@
// Interpreted Block Stream Functions
//
// -- jweier
// this include must remain at the top of every Icarus CPP file
#include "stdafx.h"
#include "IcarusInterface.h"
#include "IcarusImplementation.h"
#include "BlockStream.h"
/*
===================================================================================================
CBlockMember
===================================================================================================
*/
inline CBlockMember::CBlockMember( void )
{
m_id = -1;
m_size = -1;
m_data = NULL;
}
inline CBlockMember::~CBlockMember( void )
{
}
/*
-------------------------
Free
-------------------------
*/
void CBlockMember::Free(IGameInterface* game)
{
if ( m_data != NULL )
{
game->Free ( m_data );
m_data = NULL;
m_id = m_size = -1;
}
delete this;
}
/*
-------------------------
GetInfo
-------------------------
*/
void CBlockMember::GetInfo( int *id, int *size, void **data )
{
*id = m_id;
*size = m_size;
*data = m_data;
}
/*
-------------------------
SetData overloads
-------------------------
*/
void CBlockMember::SetData( const char *data , CIcarus* icarus)
{
WriteDataPointer( data, strlen(data)+1, icarus );
}
void CBlockMember::SetData( vec3_t data , CIcarus* icarus)
{
WriteDataPointer( data, 3 , icarus);
}
void CBlockMember::SetData( void *data, int size, CIcarus* icarus)
{
IGameInterface* game = icarus->GetGame();
if ( m_data )
game->Free( m_data );
m_data = game->Malloc( size );
memcpy( m_data, data, size );
m_size = size;
}
// Member I/O functions
/*
-------------------------
ReadMember
-------------------------
*/
int CBlockMember::ReadMember( char **stream, long *streamPos, CIcarus* icarus )
{
IGameInterface* game = icarus->GetGame();
m_id = *(int *) (*stream + *streamPos);
*streamPos += sizeof( int );
if ( m_id == CIcarus::ID_RANDOM )
{//special case, need to initialize this member's data to Q3_INFINITE so we can randomize the number only the first time random is checked when inside a wait
m_size = sizeof( float );
*streamPos += sizeof( long );
m_data = game->Malloc( m_size );
float infinite = game->MaxFloat();
memcpy( m_data, &infinite, m_size );
}
else
{
m_size = *(long *) (*stream + *streamPos);
*streamPos += sizeof( long );
m_data = game->Malloc( m_size );
memcpy( m_data, (*stream + *streamPos), m_size );
}
*streamPos += m_size;
return true;
}
/*
-------------------------
WriteMember
-------------------------
*/
int CBlockMember::WriteMember( FILE *m_fileHandle )
{
fwrite( &m_id, sizeof(m_id), 1, m_fileHandle );
fwrite( &m_size, sizeof(m_size), 1, m_fileHandle );
fwrite( m_data, m_size, 1, m_fileHandle );
return true;
}
/*
-------------------------
Duplicate
-------------------------
*/
CBlockMember *CBlockMember::Duplicate( CIcarus* icarus )
{
CBlockMember *newblock = new CBlockMember;
if ( newblock == NULL )
return NULL;
newblock->SetData( m_data, m_size, icarus );
newblock->SetSize( m_size );
newblock->SetID( m_id );
return newblock;
}
/*
===================================================================================================
CBlock
===================================================================================================
*/
/*
-------------------------
Init
-------------------------
*/
int CBlock::Init( void )
{
m_flags = 0;
m_id = 0;
return true;
}
/*
-------------------------
Create
-------------------------
*/
int CBlock::Create( int block_id )
{
Init();
m_id = block_id;
return true;
}
/*
-------------------------
Free
-------------------------
*/
int CBlock::Free( CIcarus* icarus )
{
IGameInterface* game = icarus->GetGame();
int numMembers = GetNumMembers();
CBlockMember *bMember;
while ( numMembers-- )
{
bMember = GetMember( numMembers );
if (!bMember)
return false;
bMember->Free(game);
}
m_members.clear(); //List of all CBlockMembers owned by this list
return true;
}
// Write overloads
/*
-------------------------
Write
-------------------------
*/
int CBlock::Write( int member_id, const char *member_data, CIcarus* icarus )
{
CBlockMember *bMember = new CBlockMember;
bMember->SetID( member_id );
bMember->SetData( member_data, icarus );
bMember->SetSize( strlen(member_data) + 1 );
AddMember( bMember );
return true;
}
int CBlock::Write( int member_id, vec3_t member_data, CIcarus* icarus )
{
CBlockMember *bMember;
bMember = new CBlockMember;
bMember->SetID( member_id );
bMember->SetData( member_data, icarus );
bMember->SetSize( sizeof(vec3_t) );
AddMember( bMember );
return true;
}
int CBlock::Write( int member_id, float member_data, CIcarus* icarus )
{
CBlockMember *bMember = new CBlockMember;
bMember->SetID( member_id );
bMember->WriteData( member_data, icarus );
bMember->SetSize( sizeof(member_data) );
AddMember( bMember );
return true;
}
int CBlock::Write( int member_id, int member_data, CIcarus* icarus )
{
CBlockMember *bMember = new CBlockMember;
bMember->SetID( member_id );
bMember->WriteData( member_data , icarus);
bMember->SetSize( sizeof(member_data) );
AddMember( bMember );
return true;
}
int CBlock::Write( CBlockMember *bMember, CIcarus* )
{
// findme: this is wrong: bMember->SetSize( sizeof(bMember->GetData()) );
AddMember( bMember );
return true;
}
// Member list functions
/*
-------------------------
AddMember
-------------------------
*/
int CBlock::AddMember( CBlockMember *member )
{
m_members.insert( m_members.end(), member );
return true;
}
/*
-------------------------
GetMember
-------------------------
*/
CBlockMember *CBlock::GetMember( int memberNum )
{
if ( memberNum > GetNumMembers()-1 )
{
return false;
}
return m_members[ memberNum ];
}
/*
-------------------------
GetMemberData
-------------------------
*/
void *CBlock::GetMemberData( int memberNum )
{
if ( memberNum > GetNumMembers()-1 )
{
return NULL;
}
return (void *) ((GetMember( memberNum ))->GetData());
}
/*
-------------------------
Duplicate
-------------------------
*/
CBlock *CBlock::Duplicate( CIcarus* icarus )
{
blockMember_v::iterator mi;
CBlock *newblock;
newblock = new CBlock;
if ( newblock == NULL )
return false;
newblock->Create( m_id );
//Duplicate entire block and return the cc
for ( mi = m_members.begin(); mi != m_members.end(); mi++ )
{
newblock->AddMember( (*mi)->Duplicate(icarus) );
}
return newblock;
}
/*
===================================================================================================
CBlockStream
===================================================================================================
*/
char* CBlockStream::s_IBI_EXT = ".IBI"; //(I)nterpreted (B)lock (I)nstructions
char* CBlockStream::s_IBI_HEADER_ID = "IBI";
const float CBlockStream::s_IBI_VERSION = 1.57f;
/*
-------------------------
Free
-------------------------
*/
int CBlockStream::Free( void )
{
//NOTENOTE: It is assumed that the user will free the passed memory block (m_stream) immediately after the run call
// That's why this doesn't free the memory, it only clears its internal pointer
m_stream = NULL;
m_streamPos = 0;
return true;
}
/*
-------------------------
Create
-------------------------
*/
int CBlockStream::Create( char *filename )
{
// strip extension
int extensionloc = strlen(filename);
while ( (filename[extensionloc] != '.') && (extensionloc >= 0) )
{
extensionloc--;
}
if ( extensionloc < 0 )
{
strcpy(m_fileName, filename);
}
else
{
strncpy(m_fileName, filename, extensionloc);
m_fileName[extensionloc] = '\0';
}
// add extension
strcat((char *) m_fileName, s_IBI_EXT);
if ( ((m_fileHandle = fopen(m_fileName, "wb")) == NULL) )
{
return false;
}
fwrite( s_IBI_HEADER_ID, 1, sizeof(s_IBI_HEADER_ID), m_fileHandle );
fwrite( &s_IBI_VERSION, 1, sizeof(s_IBI_VERSION), m_fileHandle );
return true;
}
/*
-------------------------
Init
-------------------------
*/
int CBlockStream::Init( void )
{
m_fileHandle = NULL;
memset(m_fileName, 0, sizeof(m_fileName));
m_stream = NULL;
m_streamPos = 0;
return true;
}
// Block I/O functions
/*
-------------------------
WriteBlock
-------------------------
*/
int CBlockStream::WriteBlock( CBlock *block, CIcarus* icarus )
{
CBlockMember *bMember;
int id = block->GetBlockID();
int numMembers = block->GetNumMembers();
unsigned char flags = block->GetFlags();
fwrite ( &id, sizeof(id), 1, m_fileHandle );
fwrite ( &numMembers, sizeof(numMembers), 1, m_fileHandle );
fwrite ( &flags, sizeof( flags ), 1, m_fileHandle );
for ( int i = 0; i < numMembers; i++ )
{
bMember = block->GetMember( i );
bMember->WriteMember( m_fileHandle );
}
block->Free(icarus);
return true;
}
/*
-------------------------
BlockAvailable
-------------------------
*/
int CBlockStream::BlockAvailable( void )
{
if ( m_streamPos >= m_fileSize )
return false;
return true;
}
/*
-------------------------
ReadBlock
-------------------------
*/
int CBlockStream::ReadBlock( CBlock *get, CIcarus* icarus )
{
CBlockMember *bMember;
int b_id, numMembers;
unsigned char flags;
if (!BlockAvailable())
return false;
b_id = *(int *) (m_stream + m_streamPos);
m_streamPos += sizeof( b_id );
numMembers = *(int *) (m_stream + m_streamPos);
m_streamPos += sizeof( numMembers );
flags = *(unsigned char*) (m_stream + m_streamPos);
m_streamPos += sizeof( flags );
if (numMembers < 0)
return false;
get->Create( b_id );
get->SetFlags( flags );
// Stream blocks are generally temporary as they
// are just used in an initial parsing phase...
#ifdef _XBOX
extern void Z_SetNewDeleteTemporary(bool bTemp);
Z_SetNewDeleteTemporary(true);
#endif
while ( numMembers-- > 0)
{
bMember = new CBlockMember;
bMember->ReadMember( &m_stream, &m_streamPos, icarus );
get->AddMember( bMember );
}
#ifdef _XBOX
Z_SetNewDeleteTemporary(false);
#endif
return true;
}
/*
-------------------------
Open
-------------------------
*/
int CBlockStream::Open( char *buffer, long size )
{
char id_header[sizeof(s_IBI_HEADER_ID)];
float version;
Init();
m_fileSize = size;
m_stream = buffer;
for ( int i = 0; i < sizeof( id_header ); i++ )
{
id_header[i] = *(m_stream + m_streamPos++);
}
version = *(float *) (m_stream + m_streamPos);
m_streamPos += sizeof( version );
//Check for valid header
if ( strcmp( id_header, s_IBI_HEADER_ID ) )
{
Free();
return false;
}
//Check for valid version
if ( version != s_IBI_VERSION )
{
Free();
return false;
}
return true;
}

View File

@@ -0,0 +1,809 @@
// IcarusImplementation.cpp
#include "stdafx.h"
#include "IcarusImplementation.h"
#include "BlockStream.h"
#include "Sequence.h"
#include "TaskManager.h"
#include "Sequencer.h"
#define STL_ITERATE( a, b ) for ( a = b.begin(); a != b.end(); a++ )
#define STL_INSERT( a, b ) a.insert( a.end(), b );
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// required implementation of CIcarusInterface
IIcarusInterface* IIcarusInterface::GetIcarus(int flavor,bool constructIfNecessary)
{
if(!CIcarus::s_instances && constructIfNecessary)
{
CIcarus::s_flavorsAvailable = IGameInterface::s_IcarusFlavorsNeeded;
if (!CIcarus::s_flavorsAvailable)
{
return NULL;
}
CIcarus::s_instances = new CIcarus*[CIcarus::s_flavorsAvailable];
for (int index = 0; index < CIcarus::s_flavorsAvailable; index++)
{
CIcarus::s_instances[index] = new CIcarus(index);
//OutputDebugString( "ICARUS flavor successfully created\n" );
}
}
if(flavor >= CIcarus::s_flavorsAvailable || !CIcarus::s_instances )
{
return NULL;
}
return CIcarus::s_instances[flavor];
}
void IIcarusInterface::DestroyIcarus()
{
for(int index = 0; index < CIcarus::s_flavorsAvailable; index++)
{
delete CIcarus::s_instances[index];
}
delete[] CIcarus::s_instances;
CIcarus::s_instances = NULL;
CIcarus::s_flavorsAvailable = 0;
}
IIcarusInterface::~IIcarusInterface()
{
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// CIcarus
double CIcarus::ICARUS_VERSION = 1.40;
int CIcarus::s_flavorsAvailable = 0;
CIcarus** CIcarus::s_instances = NULL;
CIcarus::CIcarus(int flavor) :
m_flavor(flavor), m_nextSequencerID(0)
{
m_GUID = 0;
#ifdef _DEBUG
m_DEBUG_NumSequencerAlloc = 0;
m_DEBUG_NumSequencerFreed = 0;
m_DEBUG_NumSequencerResidual = 0;
m_DEBUG_NumSequenceAlloc = 0;
m_DEBUG_NumSequenceFreed = 0;
m_DEBUG_NumSequenceResidual = 0;
#endif
m_ulBufferCurPos = 0;
m_ulBytesRead = 0;
m_byBuffer = NULL;
}
CIcarus::~CIcarus()
{
Delete();
}
#if defined (_DEBUG) && defined (_WIN32)
#include "../qcommon/platform.h" // for OutputDebugString
#endif
void CIcarus::Delete( void )
{
Free();
#ifdef _DEBUG
char buffer[1024];
OutputDebugString( "\nICARUS Instance Debug Info:\n---------------------------\n" );
sprintf( (char *) buffer, "Sequencers Allocated:\t%d\n", m_DEBUG_NumSequencerAlloc );
OutputDebugString( (const char *) &buffer );
sprintf( (char *) buffer, "Sequencers Freed:\t\t%d\n", m_DEBUG_NumSequencerFreed );
OutputDebugString( (const char *) &buffer );
sprintf( (char *) buffer, "Sequencers Residual:\t%d\n\n", m_DEBUG_NumSequencerResidual );
OutputDebugString( (const char *) &buffer );
sprintf( (char *) buffer, "Sequences Allocated:\t%d\n", m_DEBUG_NumSequenceAlloc );
OutputDebugString( (const char *) &buffer );
sprintf( (char *) buffer, "Sequences Freed:\t\t%d\n", m_DEBUG_NumSequenceFreed );
OutputDebugString( (const char *) &buffer );
sprintf( (char *) buffer, "Sequences Residual:\t\t%d\n\n", m_DEBUG_NumSequenceResidual );
OutputDebugString( (const char *) &buffer );
OutputDebugString( "\n" );
#endif
}
void CIcarus::Signal( const char *identifier )
{
m_signals[ identifier ] = 1;
}
bool CIcarus::CheckSignal( const char *identifier )
{
signal_m::iterator smi;
smi = m_signals.find( identifier );
if ( smi == m_signals.end() )
return false;
return true;
}
void CIcarus::ClearSignal( const char *identifier )
{
m_signals.erase( identifier );
}
void CIcarus::Free( void )
{
sequencer_l::iterator sri;
//Delete any residual sequencers
STL_ITERATE( sri, m_sequencers )
{
(*sri)->Free(this);
#ifdef _DEBUG
m_DEBUG_NumSequencerResidual++;
#endif
}
m_sequencers.clear();
m_signals.clear();
sequence_l::iterator si;
//Delete any residual sequences
STL_ITERATE( si, m_sequences )
{
(*si)->Delete(this);
delete (*si);
#ifdef _DEBUG
m_DEBUG_NumSequenceResidual++;
#endif
}
m_sequences.clear();
m_sequencerMap.clear();
}
int CIcarus::GetIcarusID( int gameID )
{
CSequencer *sequencer = CSequencer::Create();
CTaskManager *taskManager = CTaskManager::Create();
sequencer->Init( gameID, taskManager );
taskManager->Init( sequencer );
STL_INSERT( m_sequencers, sequencer );
m_sequencerMap[sequencer->GetID()] = sequencer;
#ifdef _DEBUG
m_DEBUG_NumSequencerAlloc++;
#endif
return sequencer->GetID();
}
void CIcarus::DeleteIcarusID( int& icarusID )
{
CSequencer* sequencer = FindSequencer(icarusID);
if(!sequencer)
{
icarusID = -1;
return;
}
CTaskManager *taskManager = sequencer->GetTaskManager();
if (taskManager->IsResident())
{
IGameInterface::GetGame()->DebugPrint( IGameInterface::WL_ERROR, "Refusing DeleteIcarusID(%d) because it is running!\n", icarusID);
assert(0);
return;
}
m_sequencerMap.erase(icarusID);
// added 2/12/2 to properly delete blocks that were passed to the task manager
sequencer->Recall(this);
if ( taskManager )
{
taskManager->Free();
delete taskManager;
}
m_sequencers.remove( sequencer );
sequencer->Free(this);
#ifdef _DEBUG
m_DEBUG_NumSequencerFreed++;
#endif
icarusID = -1;
}
CSequence *CIcarus::GetSequence( void )
{
CSequence *sequence = CSequence::Create();
//Assign the GUID
sequence->SetID( m_GUID++ );
STL_INSERT( m_sequences, sequence );
#ifdef _DEBUG
m_DEBUG_NumSequenceAlloc++;
#endif
return sequence;
}
CSequence *CIcarus::GetSequence( int id )
{
sequence_l::iterator si;
STL_ITERATE( si, m_sequences )
{
if ( (*si)->GetID() == id )
return (*si);
}
return NULL;
}
void CIcarus::DeleteSequence( CSequence *sequence )
{
m_sequences.remove( sequence );
sequence->Delete(this);
delete sequence;
#ifdef _DEBUG
m_DEBUG_NumSequenceFreed++;
#endif
}
int CIcarus::AllocateSequences( int numSequences, int *idTable )
{
CSequence *sequence;
for ( int i = 0; i < numSequences; i++ )
{
//If the GUID of this sequence is higher than the current, take this a the "current" GUID
if ( idTable[i] > m_GUID )
m_GUID = idTable[i];
//Allocate the container sequence
if ( ( sequence = GetSequence() ) == NULL )
return false;
//Override the given GUID with the real one
sequence->SetID( idTable[i] );
}
return true;
}
void CIcarus::Precache(char* buffer, long length)
{
IGameInterface* game = IGameInterface::GetGame(m_flavor);
CBlockStream stream;
CBlockMember *blockMember;
CBlock block;
if ( stream.Open( buffer, length ) == 0 )
return;
const char *sVal1, *sVal2;
//Now iterate through all blocks of the script, searching for keywords
while ( stream.BlockAvailable() )
{
//Get a block
if ( stream.ReadBlock( &block, this ) == 0 )
return;
//Determine what type of block this is
switch( block.GetBlockID() )
{
case ID_CAMERA: // to cache ROFF files
{
float f = *(float *) block.GetMemberData( 0 );
if (f == TYPE_PATH)
{
sVal1 = (const char *) block.GetMemberData( 1 );
game->PrecacheRoff(sVal1);
}
}
break;
case ID_PLAY: // to cache ROFF files
sVal1 = (const char *) block.GetMemberData( 0 );
if (!stricmp(sVal1,"PLAY_ROFF"))
{
sVal1 = (const char *) block.GetMemberData( 1 );
game->PrecacheRoff(sVal1);
}
break;
//Run commands
case ID_RUN:
sVal1 = (const char *) block.GetMemberData( 0 );
game->PrecacheScript( sVal1 );
break;
case ID_SOUND:
sVal1 = (const char *) block.GetMemberData( 1 ); //0 is channel, 1 is filename
game->PrecacheSound(sVal1);
break;
case ID_SET:
blockMember = block.GetMember( 0 );
//NOTENOTE: This will not catch special case get() inlines! (There's not really a good way to do that)
//Make sure we're testing against strings
if ( blockMember->GetID() == TK_STRING )
{
sVal1 = (const char *) block.GetMemberData( 0 );
sVal2 = (const char *) block.GetMemberData( 1 );
game->PrecacheFromSet( sVal1 , sVal2);
}
break;
default:
break;
}
//Clean out the block for the next pass
block.Free(this);
}
//All done
stream.Free();
}
CSequencer* CIcarus::FindSequencer(int sequencerID)
{
sequencer_m::iterator mi = m_sequencerMap.find( sequencerID );
if ( mi == m_sequencerMap.end() )
return NULL;
return (*mi).second;
}
int CIcarus::Run(int icarusID, char* buffer, long length)
{
CSequencer* sequencer = FindSequencer(icarusID);
if(sequencer)
{
return sequencer->Run(buffer, length, this);
}
return ICARUS_INVALID;
}
int CIcarus::SaveSequenceIDTable()
{
//Save out the number of sequences to follow
int numSequences = m_sequences.size();
BufferWrite( &numSequences, sizeof( numSequences ) );
//Sequences are saved first, by ID and information
sequence_l::iterator sqi;
//First pass, save all sequences ID for reconstruction
int *idTable = new int[ numSequences ];
int itr = 0;
if ( idTable == NULL )
return false;
STL_ITERATE( sqi, m_sequences )
{
idTable[itr++] = (*sqi)->GetID();
}
//game->WriteSaveData( 'SQTB', idTable, sizeof( int ) * numSequences );
BufferWrite( idTable, sizeof( int ) * numSequences );
delete[] idTable;
return true;
}
int CIcarus::SaveSequences()
{
//Save out a listing of all the used sequences by ID
SaveSequenceIDTable();
//Save all the information in order
sequence_l::iterator sqi;
STL_ITERATE( sqi, m_sequences )
{
(*sqi)->Save();
}
return true;
}
int CIcarus::SaveSequencers()
{
//Save out the number of sequences to follow
int numSequencers = m_sequencers.size();
BufferWrite( &numSequencers, sizeof( numSequencers ) );
//The sequencers are then saved
int sequencessaved = 0;
sequencer_l::iterator si;
STL_ITERATE( si, m_sequencers )
{
(*si)->Save();
sequencessaved++;
}
assert( sequencessaved == numSequencers );
return true;
}
int CIcarus::SaveSignals()
{
int numSignals = m_signals.size();
//game->WriteSaveData( 'ISIG', &numSignals, sizeof( numSignals ) );
BufferWrite( &numSignals, sizeof( numSignals ) );
signal_m::iterator si;
STL_ITERATE( si, m_signals )
{
//game->WriteSaveData( 'ISIG', &numSignals, sizeof( numSignals ) );
const char *name = ((*si).first).c_str();
int length = strlen( name ) + 1;
//Save out the string size
BufferWrite( &length, sizeof( length ) );
//Write out the string
BufferWrite( (void *) name, length );
}
return true;
}
// Get the current Game flavor.
int CIcarus::GetFlavor()
{
return m_flavor;
}
int CIcarus::Save()
{
// Allocate the temporary buffer.
CreateBuffer();
IGameInterface* game = IGameInterface::GetGame(m_flavor);
//Save out a ICARUS save block header with the ICARUS version
double version = ICARUS_VERSION;
game->WriteSaveData( 'ICAR', &version, sizeof( version ) );
//Save out the signals
if ( SaveSignals() == false )
{
DestroyBuffer();
return false;
}
//Save out the sequences
if ( SaveSequences() == false )
{
DestroyBuffer();
return false;
}
//Save out the sequencers
if ( SaveSequencers() == false )
{
DestroyBuffer();
return false;
}
// Write out the buffer with all our collected data.
game->WriteSaveData( 'ISEQ', m_byBuffer, m_ulBufferCurPos );
// De-allocate the temporary buffer.
DestroyBuffer();
return true;
}
int CIcarus::LoadSignals()
{
int numSignals;
BufferRead( &numSignals, sizeof( numSignals ) );
for ( int i = 0; i < numSignals; i++ )
{
char buffer[1024];
int length;
//Get the size of the string
BufferRead( &length, sizeof( length ) );
//Get the string
BufferRead( &buffer, length );
//Turn it on and add it to the system
Signal( (const char *) &buffer );
}
return true;
}
int CIcarus::LoadSequence()
{
CSequence *sequence = GetSequence();
//Load the sequence back in
sequence->Load(this);
//If this sequence had a higher GUID than the current, save it
if ( sequence->GetID() > m_GUID )
m_GUID = sequence->GetID();
return true;
}
int CIcarus::LoadSequences()
{
CSequence *sequence;
int numSequences;
//Get the number of sequences to read in
BufferRead( &numSequences, sizeof( numSequences ) );
int *idTable = new int[ numSequences ];
if ( idTable == NULL )
return false;
//Load the sequencer ID table
BufferRead( idTable, sizeof( int ) * numSequences );
//First pass, allocate all container sequences and give them their proper IDs
if ( AllocateSequences( numSequences, idTable ) == false )
return false;
//Second pass, load all sequences
for ( int i = 0; i < numSequences; i++ )
{
//Get the proper sequence for this load
if ( ( sequence = GetSequence( idTable[i] ) ) == NULL )
return false;
//Load the sequence
if ( ( sequence->Load(this) ) == false )
return false;
}
//Free the idTable
delete[] idTable;
return true;
}
int CIcarus::LoadSequencers()
{
CSequencer *sequencer;
int numSequencers;
IGameInterface* game = IGameInterface::GetGame(m_flavor);
//Get the number of sequencers to load
BufferRead( &numSequencers, sizeof( numSequencers ) );
//Load all sequencers
for ( int i = 0; i < numSequencers; i++ )
{
//NOTENOTE: The ownerID will be replaced in the loading process
int sequencerID = GetIcarusID(-1);
if ( ( sequencer = FindSequencer(sequencerID) ) == NULL )
return false;
if ( sequencer->Load(this, game) == false )
return false;
}
return true;
}
int CIcarus::Load()
{
CreateBuffer();
IGameInterface* game = IGameInterface::GetGame(m_flavor);
//Clear out any old information
Free();
//Check to make sure we're at the ICARUS save block
double version;
game->ReadSaveData( 'ICAR', &version, sizeof( version ) );
//Versions must match!
if ( version != ICARUS_VERSION )
{
DestroyBuffer();
game->DebugPrint( IGameInterface::WL_ERROR, "save game data contains outdated ICARUS version information!\n");
return false;
}
// Read into the buffer all our data.
/*m_ulBytesAvailable = */game->ReadSaveData( 'ISEQ', m_byBuffer, 0 ); //fixme, use real buff size
//Load all signals
if ( LoadSignals() == false )
{
DestroyBuffer();
game->DebugPrint( IGameInterface::WL_ERROR, "failed to load signals from save game!\n");
return false;
}
//Load in all sequences
if ( LoadSequences() == false )
{
DestroyBuffer();
game->DebugPrint( IGameInterface::WL_ERROR, "failed to load sequences from save game!\n");
return false;
}
//Load in all sequencers
if ( LoadSequencers() == false )
{
DestroyBuffer();
game->DebugPrint( IGameInterface::WL_ERROR, "failed to load sequencers from save game!\n");
return false;
}
DestroyBuffer();
return true;
}
int CIcarus::Update(int icarusID)
{
CSequencer* sequencer = FindSequencer(icarusID);
if(sequencer)
{
return sequencer->GetTaskManager()->Update(this);
}
return -1;
}
int CIcarus::IsRunning(int icarusID)
{
CSequencer* sequencer = FindSequencer(icarusID);
if(sequencer)
{
return sequencer->GetTaskManager()->IsRunning();
}
return false;
}
void CIcarus::Completed( int icarusID, int taskID )
{
CSequencer* sequencer = FindSequencer(icarusID);
if(sequencer)
{
sequencer->GetTaskManager()->Completed(taskID);
}
}
// Destroy the File Buffer.
void CIcarus::DestroyBuffer()
{
if ( m_byBuffer )
{
IGameInterface::GetGame()->Free( m_byBuffer );
m_byBuffer = NULL;
}
}
// Create the File Buffer.
void CIcarus::CreateBuffer()
{
DestroyBuffer();
m_byBuffer = (unsigned char *)IGameInterface::GetGame()->Malloc( MAX_BUFFER_SIZE );
m_ulBufferCurPos = 0;
}
// Write to a buffer.
void CIcarus::BufferWrite( void *pSrcData, unsigned long ulNumBytesToWrite )
{
if ( !pSrcData )
return;
// Make sure we have enough space in the buffer to write to.
if ( MAX_BUFFER_SIZE - m_ulBufferCurPos < ulNumBytesToWrite )
{ // Write out the buffer with all our collected data so far...
IGameInterface::GetGame()->DebugPrint( IGameInterface::WL_ERROR, "BufferWrite: Out of buffer space, Flushing." );
IGameInterface::GetGame()->WriteSaveData( 'ISEQ', m_byBuffer, m_ulBufferCurPos );
m_ulBufferCurPos = 0; //reset buffer
}
assert( MAX_BUFFER_SIZE - m_ulBufferCurPos >= ulNumBytesToWrite );
{
memcpy( m_byBuffer + m_ulBufferCurPos, pSrcData, ulNumBytesToWrite );
m_ulBufferCurPos += ulNumBytesToWrite;
}
}
// Read from a buffer.
void CIcarus::BufferRead( void *pDstBuff, unsigned long ulNumBytesToRead )
{
if ( !pDstBuff )
return;
// If we can read this data...
if ( m_ulBytesRead + ulNumBytesToRead > MAX_BUFFER_SIZE )
{// We've tried to read past the buffer...
IGameInterface::GetGame()->DebugPrint( IGameInterface::WL_ERROR, "BufferRead: Buffer underflow, Looking for new block." );
// Read in the next block.
/*m_ulBytesAvailable = */IGameInterface::GetGame()->ReadSaveData( 'ISEQ', m_byBuffer, 0 ); //FIXME, to actually check underflows, use real buff size
m_ulBytesRead = 0; //reset buffer
}
assert(m_ulBytesRead + ulNumBytesToRead <= MAX_BUFFER_SIZE);
{
memcpy( pDstBuff, m_byBuffer + m_ulBytesRead, ulNumBytesToRead );
m_ulBytesRead += ulNumBytesToRead;
}
}

View File

@@ -0,0 +1,253 @@
// IcarusImplementation.h
#ifndef ICARUSIMPLEMENTATION_DEFINED
#define ICARUSIMPLEMENTATION_DEFINED
#ifndef ICARUSINTERFACE_DEFINED
#include "IcarusInterface.h"
#endif
#pragma warning( disable : 4786 ) // identifier was truncated
#pragma warning (push, 3) // go back down to 3 for the stl include
#pragma warning (disable:4503) // decorated name length xceeded, name was truncated
#include <string>
#include <vector>
#include <map>
#include <list>
#include <algorithm>
#pragma warning (pop)
#pragma warning (disable:4503) // decorated name length xceeded, name was truncated
using namespace std;
class CSequence;
class CSequencer;
class CIcarusSequencer;
class CIcarusSequence;
class CIcarus : public IIcarusInterface
{
public:
CIcarus(int flavor);
virtual ~CIcarus();
inline IGameInterface* GetGame() {return IGameInterface::GetGame(m_flavor);};
enum
{
MAX_STRING_SIZE = 256,
MAX_FILENAME_LENGTH = 1024,
};
protected:
int m_flavor;
int m_nextSequencerID;
int m_GUID;
typedef list< CSequence * > sequence_l;
typedef list< CSequencer * > sequencer_l;
typedef map < int, CSequencer* > sequencer_m;
sequence_l m_sequences;
sequencer_l m_sequencers;
sequencer_m m_sequencerMap;
typedef map < string, unsigned char > signal_m;
signal_m m_signals;
static double ICARUS_VERSION;
#ifdef _DEBUG
int m_DEBUG_NumSequencerAlloc;
int m_DEBUG_NumSequencerFreed;
int m_DEBUG_NumSequencerResidual;
int m_DEBUG_NumSequenceAlloc;
int m_DEBUG_NumSequenceFreed;
int m_DEBUG_NumSequenceResidual;
#endif
public:
static int s_flavorsAvailable;
static CIcarus** s_instances;
// mandatory overrides
// Get the current Game flavor.
int GetFlavor();
int Save();
int Load();
int Run(int icarusID, char* buffer, long length);
void DeleteIcarusID(int& icarusID);
int GetIcarusID(int ownerID);
int Update(int icarusID);
int IsRunning(int icarusID);
void Completed( int icarusID, int taskID );
void Precache(char* buffer, long length);
protected:
void Delete();
void Free();
public:
CSequence* GetSequence(int id);
void DeleteSequence( CSequence *sequence );
int AllocateSequences( int numSequences, int *idTable );
CSequencer* FindSequencer(int sequencerID);
CSequence* GetSequence();
protected:
int SaveSequenceIDTable();
int SaveSequences();
int SaveSequencers();
int SaveSignals();
int LoadSignals();
int LoadSequence();
int LoadSequences();
int LoadSequencers();
public:
void Signal( const char *identifier );
bool CheckSignal( const char *identifier );
void ClearSignal( const char *identifier );
// Overloaded new operator.
inline void *operator new( size_t size )
{
return IGameInterface::GetGame()->Malloc( size );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{
// Free the Memory.
IGameInterface::GetGame()->Free( pRawData );
}
public:
enum
{
TK_EOF = -1,
TK_UNDEFINED,
TK_COMMENT,
TK_EOL,
TK_CHAR,
TK_STRING,
TK_INT,
TK_INTEGER = TK_INT,
TK_FLOAT,
TK_IDENTIFIER,
TK_USERDEF,
TK_BLOCK_START = TK_USERDEF,
TK_BLOCK_END,
TK_VECTOR_START,
TK_VECTOR_END,
TK_OPEN_PARENTHESIS,
TK_CLOSED_PARENTHESIS,
TK_VECTOR,
TK_GREATER_THAN,
TK_LESS_THAN,
TK_EQUALS,
TK_NOT,
NUM_USER_TOKENS
};
//ID defines
enum
{
ID_AFFECT = NUM_USER_TOKENS,
ID_SOUND,
ID_MOVE,
ID_ROTATE,
ID_WAIT,
ID_BLOCK_START,
ID_BLOCK_END,
ID_SET,
ID_LOOP,
ID_LOOPEND,
ID_PRINT,
ID_USE,
ID_FLUSH,
ID_RUN,
ID_KILL,
ID_REMOVE,
ID_CAMERA,
ID_GET,
ID_RANDOM,
ID_IF,
ID_ELSE,
ID_REM,
ID_TASK,
ID_DO,
ID_DECLARE,
ID_FREE,
ID_DOWAIT,
ID_SIGNAL,
ID_WAITSIGNAL,
ID_PLAY,
ID_TAG,
ID_EOF,
NUM_IDS
};
//Type defines
enum
{
//Wait types
TYPE_WAIT_COMPLETE = NUM_IDS,
TYPE_WAIT_TRIGGERED,
//Set types
TYPE_ANGLES,
TYPE_ORIGIN,
//Affect types
TYPE_INSERT,
TYPE_FLUSH,
//Camera types
TYPE_PAN,
TYPE_ZOOM,
TYPE_MOVE,
TYPE_FADE,
TYPE_PATH,
TYPE_ENABLE,
TYPE_DISABLE,
TYPE_SHAKE,
TYPE_ROLL,
TYPE_TRACK,
TYPE_DISTANCE,
TYPE_FOLLOW,
//Variable type
TYPE_VARIABLE,
TYPE_EOF,
NUM_TYPES
};
// Used by the new Icarus Save code.
enum { MAX_BUFFER_SIZE = 100000 };
unsigned long m_ulBufferCurPos;
unsigned long m_ulBytesRead;
unsigned char *m_byBuffer;
// Destroy the File Buffer.
void DestroyBuffer();
// Create the File Buffer.
void CreateBuffer();
// Reset the buffer completely.
void ResetBuffer();
// Write to a buffer.
void BufferWrite( void *pSrcData, unsigned long ulNumBytesToWrite );
// Read from a buffer.
void BufferRead( void *pDstBuff, unsigned long ulNumBytesToRead );
};
#endif

View File

@@ -0,0 +1,143 @@
#pragma once
#ifndef ICARUSINTERFACE_DEFINED
#define ICARUSINTERFACE_DEFINED
// IcarusInterface.h: ICARUS Interface header file.
// -Date: ~October, 2002
// -Created by: Mike Crowns and Aurelio Reis.
// -Description: The new interface between a Game Engine and the Icarus Scripting Language.
// An Interface is an Abstract Base Class with pure virtual members that MUST be implemented
// in order for the compile to succeed. Because of this, all needed functionality can be
// added without compromising other core systems.
// -Usage: To use the new Icarus Interface, two classes must be derived. The first is the
// actual Icarus Interface class which contains all relevent functionality to the scripting
// system. The second is the Game Interface which is very much more broad and thus implemented
// by the user. Icarus functions by calling the Game Interface to do certain tasks for it. This
// is why the Game Interface is required to have certain functions implemented.
// The basic Icarus Interface ABC.
class IIcarusInterface
{
public:
enum { ICARUS_INVALID = 0 };
virtual ~IIcarusInterface();
// Get a static singleton instance (of a specific flavor).
static IIcarusInterface* GetIcarus(int flavor = 0,bool constructIfNecessary=true); // must be implemented along with concrete class
static void DestroyIcarus(); // Destroy the static singleton instance.
virtual int GetFlavor() = 0;
virtual int Save() = 0; // Save all Icarus states.
virtual int Load() = 0; // Load all Icarus states.
virtual int Run(int icarusID, char* buffer, long length) = 0; // Execute a script.
virtual void DeleteIcarusID(int &icarusID) = 0; // Delete an Icarus ID from the list (making the ID Invalid on the other end through reference).
virtual int GetIcarusID(int gameID) = 0; // Get an Icarus ID.
virtual int Update( int icarusID ) = 0; // Update all internal Icarus structures.
virtual int IsRunning( int icarusID ) = 0; // Whether a Icarus is running or not.
virtual void Completed( int icarusID, int taskID ) = 0; // Tells Icarus a task is completed.
virtual void Precache( char* buffer, long length ) = 0; // Precache a Script in memory.
};
// Description: The Game Interface is used by the Icarus Interface to access specific
// data or initiate certain things within the engine being used. It is made to be
// as generic as possible to allow any engine to derive it's own interface for use.
// Created: 10/08/02 by Aurelio Reis.
class IGameInterface
{
protected:
// Pure Virtual Destructor.
virtual ~IGameInterface();
public:
//For system-wide prints
enum e_DebugPrintLevel { WL_ERROR = 1, WL_WARNING, WL_VERBOSE, WL_DEBUG };
// How many flavors are needed.
static int s_IcarusFlavorsNeeded;
// Get a static singleton instance (of a specific flavor).
static IGameInterface *GetGame( int flavor = 0 );
// Destroy the static singleton instance (NOTE: Destroy the Game Interface BEFORE the Icarus Interface).
static void Destroy();
// General
// Load a script File into the destination buffer. If the script has already been loaded
// NOTE: This is what was called before:
/*
// Description : Reads in a file and attaches the script directory properly
extern int ICARUS_GetScript( const char *name, char **buf ); //g_icarus.cpp
static int Q3_ReadScript( const char *name, void **buf )
{
return ICARUS_GetScript( va( "%s/%s", Q3_SCRIPT_DIR, name ), (char**)buf ); //get a (hopefully) cached file
}
*/
virtual int GetFlavor() = 0;
virtual int LoadFile( const char *name, void **buf ) = 0;
virtual void CenterPrint( const char *format, ... ) = 0;
virtual void DebugPrint( e_DebugPrintLevel, const char *, ... ) = 0;
virtual unsigned int GetTime( void ) = 0; //Gets the current time
virtual int PlaySound( int taskID, int gameID, const char *name, const char *channel ) = 0;
virtual void Lerp2Pos( int taskID, int gameID, float origin[3], float angles[3], float duration ) = 0;
virtual void Lerp2Angles( int taskID, int gameID, float angles[3], float duration ) = 0;
virtual int GetTag( int gameID, const char *name, int lookup, float info[3] ) = 0;
virtual void Set( int taskID, int gameID, const char *type_name, const char *data ) = 0;
virtual void Use( int gameID, const char *name ) = 0;
virtual void Activate( int gameID, const char *name ) = 0;
virtual void Deactivate( int gameID, const char *name ) = 0;
virtual void Kill( int gameID, const char *name ) = 0;
virtual void Remove( int gameID, const char *name ) = 0;
virtual float Random( float min, float max ) = 0;
virtual void Play( int taskID, int gameID, const char *type, const char *name ) = 0;
// Camera functions
virtual void CameraPan( float angles[3], float dir[3], float duration ) = 0;
virtual void CameraMove( float origin[3], float duration ) = 0;
virtual void CameraZoom( float fov, float duration ) = 0;
virtual void CameraRoll( float angle, float duration ) = 0;
virtual void CameraFollow( const char *name, float speed, float initLerp ) = 0;
virtual void CameraTrack( const char *name, float speed, float initLerp ) = 0;
virtual void CameraDistance( float dist, float initLerp ) = 0;
virtual void CameraFade( float sr, float sg, float sb, float sa, float dr, float dg, float db, float da, float duration ) = 0;
virtual void CameraPath( const char *name ) = 0;
virtual void CameraEnable( void ) = 0;
virtual void CameraDisable( void ) = 0;
virtual void CameraShake( float intensity, int duration ) = 0;
virtual int GetFloat( int gameID, const char *name, float *value ) = 0;
// Should be float return type?
virtual int GetVector( int gameID, const char *name, float value[3] ) = 0;
virtual int GetString( int gameID, const char *name, char **value ) = 0;
virtual int Evaluate( int p1Type, const char *p1, int p2Type, const char *p2, int operatorType ) = 0;
virtual void DeclareVariable( int type, const char *name ) = 0;
virtual void FreeVariable( const char *name ) = 0;
// Save / Load functions
virtual int WriteSaveData( unsigned long chid, void *data, int length ) = 0;
virtual int ReadSaveData( unsigned long chid, void *address, int length, void **addressptr = NULL ) = 0;
virtual int LinkGame( int gameID, int icarusID ) = 0;
// Access functions
virtual int CreateIcarus( int gameID) = 0;
virtual int GetByName( const char *name ) = 0; //Polls the engine for the sequencer of the entity matching the name passed
virtual int IsFrozen(int gameID) = 0; // (g_entities[m_ownerID].svFlags&SVF_ICARUS_FREEZE) // return -1 indicates invalid
virtual void Free(void* data) = 0;
virtual void* Malloc( int size ) = 0;
virtual float MaxFloat(void) = 0;
// Script precache functions.
virtual void PrecacheRoff(const char* name) = 0; // G_LoadRoff
virtual void PrecacheScript(const char* name) = 0; // must strip extension COM_StripExtension()
virtual void PrecacheSound(const char* name) = 0; // G_SoundIndex
virtual void PrecacheFromSet(const char* setname, const char* filename) = 0;
};
#endif

674
code/icarus/Sequence.cpp Normal file
View File

@@ -0,0 +1,674 @@
// Script Command Sequences
//
// -- jweier
// this include must remain at the top of every Icarus CPP file
#include "stdafx.h"
#include "IcarusImplementation.h"
#include "BlockStream.h"
#include "Sequence.h"
#define STL_ITERATE( a, b ) for ( a = b.begin(); a != b.end(); a++ )
#define STL_INSERT( a, b ) a.insert( a.end(), b );
inline CSequence::CSequence( void )
{
m_numCommands = 0;
// m_numChildren = 0;
m_flags = 0;
m_iterations = 1;
m_parent = NULL;
m_return = NULL;
}
CSequence::~CSequence( void )
{
assert(!m_commands.size());
//assert(!m_numChildren);
}
/*
-------------------------
Create
-------------------------
*/
CSequence *CSequence::Create( void )
{
CSequence *seq = new CSequence;
//TODO: Emit warning
assert(seq);
if ( seq == NULL )
return NULL;
seq->SetFlag( SQ_COMMON );
return seq;
}
/*
-------------------------
Delete
-------------------------
*/
void CSequence::Delete( CIcarus* icarus )
{
block_l::iterator bi;
sequence_l::iterator si;
//Notify the parent of the deletion
if ( m_parent )
{
m_parent->RemoveChild( this );
}
//Clear all children
if ( m_children.size() > 0 )
{
/*for ( iterSeq = m_childrenMap.begin(); iterSeq != m_childrenMap.end(); iterSeq++ )
{
(*iterSeq).second->SetParent( NULL );
}*/
for ( si = m_children.begin(); si != m_children.end(); si++ )
{
(*si)->SetParent( NULL );
}
}
m_children.clear();
//m_childrenMap.clear();
//Clear all held commands
for ( bi = m_commands.begin(); bi != m_commands.end(); bi++ )
{
(*bi)->Free(icarus);
delete (*bi); //Free() handled internally -- not any more!!
}
m_commands.clear();
}
/*
-------------------------
AddChild
-------------------------
*/
void CSequence::AddChild( CSequence *child )
{
assert( child );
if ( child == NULL )
return;
m_children.insert( m_children.end(), child );
// m_childrenMap[ m_numChildren ] = child;
// m_numChildren++;
}
/*
-------------------------
RemoveChild
-------------------------
*/
void CSequence::RemoveChild( CSequence *child )
{
assert( child );
if ( child == NULL )
return;
m_children.remove( child );
//Remove the child
/* sequenceID_m::iterator iterSeq = m_childrenMap.find( child->GetID() );
if ( iterSeq != m_childrenMap.end() )
{
m_childrenMap.erase( iterSeq );
}
m_numChildren--;*/
}
/*
-------------------------
HasChild
-------------------------
*/
bool CSequence::HasChild( CSequence *sequence )
{
sequence_l::iterator ci;
for ( ci = m_children.begin(); ci != m_children.end(); ci++ )
{
if ( (*ci) == sequence )
return true;
if ( (*ci)->HasChild( sequence ) )
return true;
}
/* sequenceID_m::iterator iterSeq = NULL;
for ( iterSeq = m_childrenMap.begin(); iterSeq != m_childrenMap.end(); iterSeq++ )
{
if ( ((*iterSeq).second) == sequence )
return true;
if ( (*iterSeq).second->HasChild( sequence ) )
return true;
}*/
return false;
}
/*
-------------------------
SetParent
-------------------------
*/
void CSequence::SetParent( CSequence *parent )
{
m_parent = parent;
if ( parent == NULL )
return;
//Inherit the parent's properties (this avoids messy tree walks later on)
if ( parent->m_flags & SQ_RETAIN )
m_flags |= SQ_RETAIN;
if ( parent->m_flags & SQ_PENDING )
m_flags |= SQ_PENDING;
}
/*
-------------------------
PopCommand
-------------------------
*/
CBlock *CSequence::PopCommand( int type )
{
CBlock *command = NULL;
//Make sure everything is ok
assert( (type == POP_FRONT) || (type == POP_BACK) );
if ( m_commands.empty() )
return NULL;
switch ( type )
{
case POP_FRONT:
command = m_commands.front();
m_commands.pop_front();
m_numCommands--;
return command;
break;
case POP_BACK:
command = m_commands.back();
m_commands.pop_back();
m_numCommands--;
return command;
break;
}
//Invalid flag
return NULL;
}
/*
-------------------------
PushCommand
-------------------------
*/
int CSequence::PushCommand( CBlock *block, int type )
{
//Make sure everything is ok
assert( (type == PUSH_FRONT) || (type == PUSH_BACK) );
assert( block );
switch ( type )
{
case PUSH_FRONT:
m_commands.push_front( block );
m_numCommands++;
return true;
break;
case PUSH_BACK:
m_commands.push_back( block );
m_numCommands++;
return true;
break;
}
//Invalid flag
return false;
}
/*
-------------------------
SetFlag
-------------------------
*/
void CSequence::SetFlag( int flag )
{
m_flags |= flag;
}
/*
-------------------------
RemoveFlag
-------------------------
*/
void CSequence::RemoveFlag( int flag, bool children )
{
m_flags &= ~flag;
if ( children )
{
/* sequenceID_m::iterator iterSeq = NULL;
for ( iterSeq = m_childrenMap.begin(); iterSeq != m_childrenMap.end(); iterSeq++ )
{
(*iterSeq).second->RemoveFlag( flag, true );
}*/
sequence_l::iterator si;
for ( si = m_children.begin(); si != m_children.end(); si++ )
{
(*si)->RemoveFlag( flag, true );
}
}
}
/*
-------------------------
HasFlag
-------------------------
*/
int CSequence::HasFlag( int flag )
{
return (m_flags & flag);
}
/*
-------------------------
SetReturn
-------------------------
*/
void CSequence::SetReturn ( CSequence *sequence )
{
assert( sequence != this );
m_return = sequence;
}
/*
-------------------------
GetChildByID
-------------------------
*/
CSequence *CSequence::GetChildByID( int id )
{
if ( id < 0 )
return NULL;
//NOTENOTE: Done for safety reasons, I don't know what this template will return on underflow ( sigh... )
/* sequenceID_m::iterator mi = m_childrenMap.find( id );
if ( mi == m_childrenMap.end() )
return NULL;
return (*mi).second;*/
sequence_l::iterator iterSeq;
STL_ITERATE( iterSeq, m_children )
{
if ( (*iterSeq)->GetID() == id )
return (*iterSeq);
}
return NULL;
}
/*
-------------------------
GetChildByIndex
-------------------------
*/
CSequence *CSequence::GetChildByIndex( int iIndex )
{
if ( iIndex < 0 || iIndex >= (int)m_children.size() )
return NULL;
sequence_l::iterator iterSeq = m_children.begin();
for ( int i = 0; i < iIndex; i++ )
{
++iterSeq;
}
return (*iterSeq);
}
/*
-------------------------
SaveCommand
-------------------------
*/
int CSequence::SaveCommand( CBlock *block )
{
CIcarus *pIcarus = (CIcarus *)IIcarusInterface::GetIcarus();
unsigned char flags;
int numMembers, bID, size;
CBlockMember *bm;
// Data saved here (IBLK):
// Block ID.
// Block Flags.
// Number of Block Members.
// Block Members:
// - Block Member ID.
// - Block Data Size.
// - Block (Raw) Data.
//Save out the block ID
bID = block->GetBlockID();
pIcarus->BufferWrite( &bID, sizeof ( bID ) );
//Save out the block's flags
flags = block->GetFlags();
pIcarus->BufferWrite( &flags, sizeof ( flags ) );
//Save out the number of members to read
numMembers = block->GetNumMembers();
pIcarus->BufferWrite( &numMembers, sizeof ( numMembers ) );
for ( int i = 0; i < numMembers; i++ )
{
bm = block->GetMember( i );
//Save the block id
bID = bm->GetID();
pIcarus->BufferWrite( &bID, sizeof ( bID ) );
//Save out the data size
size = bm->GetSize();
pIcarus->BufferWrite( &size, sizeof ( size ) );
//Save out the raw data
pIcarus->BufferWrite( bm->GetData(), size );
}
return true;
}
int CSequence::LoadCommand( CBlock *block, CIcarus *icarus )
{
IGameInterface* game = icarus->GetGame();
int bID, bSize;
void *bData;
unsigned char flags;
int id, numMembers;
// Data expected/loaded here (IBLK) (with the size as : 'IBSZ' ).
// Block ID.
// Block Flags.
// Number of Block Members.
// Block Members:
// - Block Member ID.
// - Block Data Size.
// - Block (Raw) Data.
//Get the block ID.
icarus->BufferRead( &id, sizeof( id ) );
block->Create( id );
//Read the block's flags
icarus->BufferRead( &flags, sizeof( flags ) );
block->SetFlags( flags );
//Get the number of block members
icarus->BufferRead( &numMembers, sizeof( numMembers ) );
for ( int j = 0; j < numMembers; j++ )
{
//Get the member ID
icarus->BufferRead( &bID, sizeof( bID ) );
//Get the member size
icarus->BufferRead( &bSize, sizeof( bSize ) );
//Get the member's data
if ( ( bData = game->Malloc( bSize ) ) == NULL )
return false;
//Get the actual raw data
icarus->BufferRead( bData, bSize );
//Write out the correct type
switch ( bID )
{
case CIcarus::TK_INT:
{
assert(0);
int data = *(int *) bData;
block->Write( CIcarus::TK_FLOAT, (float) data, icarus );
}
break;
case CIcarus::TK_FLOAT:
block->Write( CIcarus::TK_FLOAT, *(float *) bData, icarus );
break;
case CIcarus::TK_STRING:
case CIcarus::TK_IDENTIFIER:
case CIcarus::TK_CHAR:
block->Write( CIcarus::TK_STRING, (char *) bData, icarus );
break;
case CIcarus::TK_VECTOR:
case CIcarus::TK_VECTOR_START:
block->Write( CIcarus::TK_VECTOR, *(vec3_t *) bData, icarus );
break;
case CIcarus::ID_TAG:
block->Write( CIcarus::ID_TAG, (float) CIcarus::ID_TAG, icarus );
break;
case CIcarus::ID_GET:
block->Write( CIcarus::ID_GET, (float) CIcarus::ID_GET, icarus );
break;
case CIcarus::ID_RANDOM:
block->Write( CIcarus::ID_RANDOM, *(float *) bData, icarus );//(float) ID_RANDOM );
break;
case CIcarus::TK_EQUALS:
case CIcarus::TK_GREATER_THAN:
case CIcarus::TK_LESS_THAN:
case CIcarus::TK_NOT:
block->Write( bID, 0, icarus );
break;
default:
assert(0);
return false;
break;
}
//Get rid of the temp memory
game->Free( bData );
}
return true;
}
/*
-------------------------
Save
-------------------------
*/
int CSequence::Save()
{
// Data saved here.
// Parent ID.
// Return ID.
// Number of Children.
// Children.
// - Child ID
// Save Flags.
// Save Iterations.
// Number of Commands
// - Commands (raw) data.
CIcarus *pIcarus = (CIcarus *)IIcarusInterface::GetIcarus();
block_l::iterator bi;
int id;
// Save the parent (by GUID).
id = ( m_parent != NULL ) ? m_parent->GetID() : -1;
pIcarus->BufferWrite( &id, sizeof( id ) );
//Save the return (by GUID)
id = ( m_return != NULL ) ? m_return->GetID() : -1;
pIcarus->BufferWrite( &id, sizeof( id ) );
//Save the number of children
int iNumChildren = m_children.size();
pIcarus->BufferWrite( &iNumChildren, sizeof( iNumChildren ) );
//Save out the children (only by GUID)
/*STL_ITERATE( iterSeq, m_childrenMap )
{
id = (*iterSeq).second->GetID();
pIcarus->BufferWrite( &id, sizeof( id ) );
}*/
sequence_l::iterator iterSeq;
STL_ITERATE( iterSeq, m_children )
{
id = (*iterSeq)->GetID();
pIcarus->BufferWrite( &id, sizeof( id ) );
}
//Save flags
pIcarus->BufferWrite( &m_flags, sizeof( m_flags ) );
//Save iterations
pIcarus->BufferWrite( &m_iterations, sizeof( m_iterations ) );
//Save the number of commands
pIcarus->BufferWrite( &m_numCommands, sizeof( m_numCommands ) );
//Save the commands
STL_ITERATE( bi, m_commands )
{
SaveCommand( (*bi) );
}
return true;
}
/*
-------------------------
Load
-------------------------
*/
int CSequence::Load( CIcarus* icarus )
{
CSequence *sequence;
CBlock *block;
int id;
// Data expected/loaded here (ISEQ) (with the size as : 'ISSZ' ).
// Parent ID.
// Return ID.
// Number of Children.
// Children.
// - Child ID
// Save Flags.
// Save Iterations.
// Number of Commands
// - Commands (raw) data.
//Get the parent sequence
icarus->BufferRead( &id, sizeof( id ) );
m_parent = ( id != -1 ) ? icarus->GetSequence( id ) : NULL;
//Get the return sequence
icarus->BufferRead( &id, sizeof( id ) );
m_return = ( id != -1 ) ? icarus->GetSequence( id ) : NULL;
//Get the number of children
int iNumChildren = 0;
icarus->BufferRead( &iNumChildren, sizeof( iNumChildren ) );
//Reload all children
for ( int i = 0; i < iNumChildren; i++ )
{
//Get the child sequence ID
icarus->BufferRead( &id, sizeof( id ) );
//Get the desired sequence
if ( ( sequence = icarus->GetSequence( id ) ) == NULL )
return false;
//Insert this into the list
STL_INSERT( m_children, sequence );
//Restore the connection in the child / ID map
// m_childrenMap[ i ] = sequence;
}
//Get the sequence flags
icarus->BufferRead( &m_flags, sizeof( m_flags ) );
//Get the number of iterations
icarus->BufferRead( &m_iterations, sizeof( m_iterations ) );
int numCommands;
//Get the number of commands
icarus->BufferRead( &numCommands, sizeof( numCommands ) );
//Get all the commands
for ( i = 0; i < numCommands; i++ )
{
block = new CBlock;
LoadCommand( block, icarus );
//Save the block
//STL_INSERT( m_commands, block );
PushCommand( block, PUSH_BACK );
}
return true;
}

2614
code/icarus/Sequencer.cpp Normal file

File diff suppressed because it is too large Load Diff

19
code/icarus/StdAfx.h Normal file
View File

@@ -0,0 +1,19 @@
#ifndef __ICR_STDAFX__
#define __ICR_STDAFX__
#pragma warning( disable : 4786 ) // identifier was truncated
#pragma warning (push, 3)
#include <string>
#include <list>
#include <vector>
#include <map>
#include <algorithm>
#pragma warning (pop)
using namespace std;
#define STL_ITERATE( a, b ) for ( a = b.begin(); a != b.end(); a++ )
#define STL_INSERT( a, b ) a.insert( a.end(), b );
#endif

2036
code/icarus/TaskManager.cpp Normal file

File diff suppressed because it is too large Load Diff

213
code/icarus/blockstream.h Normal file
View File

@@ -0,0 +1,213 @@
// BlockStream.h
#ifndef __INTERPRETED_BLOCK_STREAM__
#define __INTERPRETED_BLOCK_STREAM__
#include <assert.h>
typedef float vec3_t[3];
// Templates
// CBlockMember
class CBlockMember
{
public:
CBlockMember();
protected:
~CBlockMember();
public:
void Free(IGameInterface* game);
int WriteMember ( FILE * ); //Writes the member's data, in block format, to FILE *
int ReadMember( char **, long *, CIcarus* icarus ); //Reads the member's data, in block format, from FILE *
void SetID( int id ) { m_id = id; } //Set the ID member variable
void SetSize( int size ) { m_size = size; } //Set the size member variable
void GetInfo( int *, int *, void **);
//SetData overloads
void SetData( const char * ,CIcarus* icarus);
void SetData( vec3_t , CIcarus* icarus);
void SetData( void *data, int size, CIcarus* icarus);
int GetID( void ) const { return m_id; } //Get ID member variables
void *GetData( void ) const { return m_data; } //Get data member variable
int GetSize( void ) const { return m_size; } //Get size member variable
// Overloaded new operator.
inline void *operator new( size_t size )
{ // Allocate the memory.
return IGameInterface::GetGame()->Malloc( size );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{ // Free the Memory.
IGameInterface::GetGame()->Free( pRawData );
}
CBlockMember *Duplicate( CIcarus* icarus );
template <class T> void WriteData(T &data, CIcarus* icarus)
{
IGameInterface* game = icarus->GetGame();
if ( m_data )
{
game->Free( m_data );
}
m_data = game->Malloc( sizeof(T) );
*((T *) m_data) = data;
m_size = sizeof(T);
}
template <class T> void WriteDataPointer(const T *data, int num, CIcarus* icarus)
{
IGameInterface* game =icarus->GetGame();
if ( m_data )
{
game->Free( m_data );
}
m_data = game->Malloc( num*sizeof(T) );
memcpy( m_data, data, num*sizeof(T) );
m_size = num*sizeof(T);
}
protected:
int m_id; //ID of the value contained in data
int m_size; //Size of the data member variable
void *m_data; //Data for this member
};
//CBlock
class CBlock
{
typedef vector< CBlockMember * > blockMember_v;
public:
CBlock()
{
m_flags = 0;
m_id = 0;
}
~CBlock() { assert(!GetNumMembers()); }
int Init( void );
int Create( int );
int Free(CIcarus* icarus);
//Write Overloads
int Write( int, vec3_t, CIcarus* icaru );
int Write( int, float, CIcarus* icaru );
int Write( int, const char *, CIcarus* icaru );
int Write( int, int, CIcarus* icaru );
int Write( CBlockMember *, CIcarus* icaru );
//Member push / pop functions
int AddMember( CBlockMember * );
CBlockMember *GetMember( int memberNum );
void *GetMemberData( int memberNum );
CBlock *Duplicate( CIcarus* icarus );
int GetBlockID( void ) const { return m_id; } //Get the ID for the block
int GetNumMembers( void ) const { return m_members.size();} //Get the number of member in the block's list
void SetFlags( unsigned char flags ) { m_flags = flags; }
void SetFlag( unsigned char flag ) { m_flags |= flag; }
int HasFlag( unsigned char flag ) const { return ( m_flags & flag ); }
unsigned char GetFlags( void ) const { return m_flags; }
// Overloaded new operator.
inline void *operator new( size_t size )
{ // Allocate the memory.
return IGameInterface::GetGame()->Malloc( size );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{ // Validate data.
if ( pRawData == 0 )
return;
// Free the Memory.
IGameInterface::GetGame()->Free( pRawData );
}
protected:
blockMember_v m_members; //List of all CBlockMembers owned by this list
int m_id; //ID of the block
unsigned char m_flags;
};
// CBlockStream
class CBlockStream
{
public:
CBlockStream()
{
m_stream = NULL;
m_streamPos = 0;
}
~CBlockStream() {};
int Init( void );
int Create( char * );
int Free( void );
// Stream I/O functions
int BlockAvailable( void );
int WriteBlock( CBlock *, CIcarus* icarus ); //Write the block out
int ReadBlock( CBlock *, CIcarus* icarus ); //Read the block in
int Open( char *, long ); //Open a stream for reading / writing
// Overloaded new operator.
static void *operator new( size_t size )
{ // Allocate the memory.
return IGameInterface::GetGame()->Malloc( size );
}
// Overloaded delete operator.
static void operator delete( void *pRawData )
{ // Free the Memory.
IGameInterface::GetGame()->Free( pRawData );
}
protected:
long m_fileSize; //Size of the file
FILE *m_fileHandle; //Global file handle of current I/O source
char m_fileName[CIcarus::MAX_FILENAME_LENGTH]; //Name of the current file
char *m_stream; //Stream of data to be parsed
long m_streamPos;
static char* s_IBI_EXT;
static char* s_IBI_HEADER_ID;
static const float s_IBI_VERSION;
};
#endif //__INTERPRETED_BLOCK_STREAM__

115
code/icarus/sequence.h Normal file
View File

@@ -0,0 +1,115 @@
// Sequence Header File
#ifndef __SEQUENCE__
#define __SEQUENCE__
class CSequence
{
typedef list < CSequence * > sequence_l;
// typedef map < int, CSequence *> sequenceID_m;
typedef list < CBlock * > block_l;
public:
//Constructors / Destructors
CSequence( void );
~CSequence( void );
//Creation and deletion
static CSequence *Create( void );
void Delete( CIcarus* icarus );
//Organization functions
void AddChild( CSequence * );
void RemoveChild( CSequence * );
void SetParent( CSequence * );
CSequence *GetParent( void ) const { return m_parent; }
//Block manipulation
CBlock *PopCommand( int );
int PushCommand( CBlock *, int );
//Flag utilties
void SetFlag( int );
void RemoveFlag( int, bool = false );
int HasFlag( int );
int GetFlags( void ) const { return m_flags; }
void SetFlags( int flags ) { m_flags = flags; }
//Various encapsulation utilities
int GetIterations( void ) const { return m_iterations; }
void SetIterations( int it ) { m_iterations = it; }
int GetID( void ) const { return m_id; }
void SetID( int id ) { m_id = id; }
CSequence *GetReturn( void ) const { return m_return; }
void SetReturn ( CSequence *sequence );
int GetNumCommands( void ) const { return m_numCommands; }
int GetNumChildren( void ) const { return m_children.size(); }
CSequence *GetChildByID( int id );
CSequence *GetChildByIndex( int iIndex );
bool HasChild( CSequence *sequence );
int Save();
int Load( CIcarus* icarus );
// Overloaded new operator.
inline void *operator new( size_t size )
{ // Allocate the memory.
return IGameInterface::GetGame()->Malloc( size );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{ // Free the Memory.
IGameInterface::GetGame()->Free( pRawData );
}
enum
{
SQ_COMMON = 0x00000000, //Common one-pass sequence
SQ_LOOP = 0x00000001, //Looping sequence
SQ_RETAIN = 0x00000002, //Inside a looping sequence list, retain the information
SQ_AFFECT = 0x00000004, //Affect sequence
SQ_RUN = 0x00000008, //A run block
SQ_PENDING = 0x00000010, //Pending use, don't free when flushing the sequences
SQ_CONDITIONAL = 0x00000020, //Conditional statement
SQ_TASK = 0x00000040, //Task block
};
enum
{
POP_FRONT,
POP_BACK,
PUSH_FRONT,
PUSH_BACK
};
protected:
int SaveCommand( CBlock *block );
int LoadCommand( CBlock *block, CIcarus *icarus );
//Organization information
sequence_l m_children;
//sequenceID_m m_childrenMap;
//int m_numChildren;
CSequence *m_parent;
CSequence *m_return;
//Data information
block_l m_commands;
int m_flags;
int m_iterations;
int m_id;
int m_numCommands;
};
#endif //__SEQUENCE__

163
code/icarus/sequencer.h Normal file
View File

@@ -0,0 +1,163 @@
// Sequencer Header File
#ifndef __SEQUENCER__
#define __SEQUENCER__
//Defines
//const int MAX_ERROR_LENGTH = 256;
//Typedefs
typedef struct bstream_s
{
CBlockStream *stream;
bstream_s *last;
} bstream_t;
// Sequencer
/*
==================================================================================================
CSequencer
==================================================================================================
*/
class CSequencer
{
//typedef map < int, CSequence * > sequenceID_m;
typedef list < CSequence * > sequence_l;
typedef map < CTaskGroup *, CSequence * > taskSequence_m;
public:
enum
{
BF_ELSE = 0x00000001, //Block has an else id //FIXME: This was a sloppy fix for a problem that arose from conditionals
};
enum
{
SEQ_OK, //Command was successfully added
SEQ_FAILED, //An error occured while trying to insert the command
};
CSequencer();
protected:
~CSequencer();
public:
int GetID() { return m_id;};
int Init( int ownerID, CTaskManager *taskManager);
static CSequencer *Create ( void );
void Free( CIcarus* icarus );
int Run( char *buffer, long size, CIcarus* icarus);
int Callback( CTaskManager *taskManager, CBlock *block, int returnCode, CIcarus* icarus );
void SetOwnerID( int owner ) { m_ownerID = owner;}
int GetOwnerID( void ) const { return m_ownerID; }
CTaskManager *GetTaskManager( void ) const { return m_taskManager; }
void SetTaskManager( CTaskManager *tm) { if ( tm ) m_taskManager = tm; }
int Save();
int Load( CIcarus* icarus, IGameInterface* game );
// Overloaded new operator.
inline void *operator new( size_t size )
{ // Allocate the memory.
return IGameInterface::GetGame()->Malloc( size );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{ // Free the Memory.
IGameInterface::GetGame()->Free( pRawData );
}
// moved to public on 2/12/2 to allow calling during shutdown
int Recall( CIcarus* icarus );
protected:
int EvaluateConditional( CBlock *block, CIcarus* icarus );
int Route( CSequence *sequence, bstream_t *bstream , CIcarus* icarus);
int Flush( CSequence *owner, CIcarus* icarus );
void Interrupt( void );
bstream_t *AddStream( void );
void DeleteStream( bstream_t *bstream );
int AddAffect( bstream_t *bstream, int retain, int *id, CIcarus* icarus );
CSequence *AddSequence( CIcarus* icarus );
CSequence *AddSequence( CSequence *parent, CSequence *returnSeq, int flags, CIcarus* icarus );
CSequence *GetSequence( int id );
//NOTENOTE: This only removes references to the sequence, IT DOES NOT FREE THE ALLOCATED MEMORY!
int RemoveSequence( CSequence *sequence, CIcarus* icarus);
int DestroySequence( CSequence *sequence, CIcarus* icarus);
int PushCommand( CBlock *command, int flag );
CBlock *PopCommand( int flag );
inline CSequence *ReturnSequence( CSequence *sequence );
void CheckRun( CBlock ** , CIcarus* icarus);
void CheckLoop( CBlock ** , CIcarus* icarus);
void CheckAffect( CBlock ** , CIcarus* icarus);
void CheckIf( CBlock ** , CIcarus* icarus);
void CheckDo( CBlock ** , CIcarus* icarus);
void CheckFlush( CBlock ** , CIcarus* icarus);
void Prep( CBlock ** , CIcarus* icarus);
int Prime( CTaskManager *taskManager, CBlock *command, CIcarus* icarus);
void StripExtension( const char *in, char *out );
int ParseRun( CBlock *block , CIcarus* icarus);
int ParseLoop( CBlock *block, bstream_t *bstream , CIcarus* icarus);
int ParseAffect( CBlock *block, bstream_t *bstream, CIcarus* icarus );
int ParseIf( CBlock *block, bstream_t *bstream, CIcarus* icarus );
int ParseElse( CBlock *block, bstream_t *bstream, CIcarus* icarus );
int ParseTask( CBlock *block, bstream_t *bstream , CIcarus* icarus);
int Affect( int id, int type , CIcarus* icarus);
void AddTaskSequence( CSequence *sequence, CTaskGroup *group );
CSequence *GetTaskSequence( CTaskGroup *group );
//Member variables
int m_ownerID;
CTaskManager *m_taskManager;
int m_numCommands; //Total number of commands for the sequencer (including all child sequences)
//sequenceID_m m_sequenceMap;
sequence_l m_sequences;
taskSequence_m m_taskSequences;
CSequence *m_curSequence;
CTaskGroup *m_curGroup;
bstream_t *m_curStream;
int m_elseValid;
CBlock *m_elseOwner;
vector<bstream_t*> m_streamsCreated;
int m_id;
};
#endif //__SEQUENCER__

227
code/icarus/taskmanager.h Normal file
View File

@@ -0,0 +1,227 @@
// Task Manager header file
#ifndef __TASK_MANAGER__
#define __TASK_MANAGER__
typedef unsigned long DWORD;
#define MAX_TASK_NAME 64
#define TASKFLAG_NORMAL 0x00000000
const int RUNAWAY_LIMIT = 256;
enum
{
TASK_RETURN_COMPLETE,
TASK_RETURN_FAILED,
};
enum
{
TASK_OK,
TASK_FAILED,
TASK_START,
TASK_END,
};
// CTask
class CTask
{
public:
CTask();
~CTask();
static CTask *Create( int GUID, CBlock *block );
void Free( void );
DWORD GetTimeStamp( void ) const { return m_timeStamp; }
CBlock *GetBlock( void ) const { return m_block; }
int GetGUID( void) const { return m_id; }
int GetID( void ) const { return m_block->GetBlockID(); }
void SetTimeStamp( DWORD timeStamp ) { m_timeStamp = timeStamp; }
void SetBlock( CBlock *block ) { m_block = block; }
void SetGUID( int id ) { m_id = id; }
// Overloaded new operator.
inline void *operator new( size_t size )
{ // Allocate the memory.
return IGameInterface::GetGame()->Malloc( size );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{ // Free the Memory.
IGameInterface::GetGame()->Free( pRawData );
}
protected:
int m_id;
DWORD m_timeStamp;
CBlock *m_block;
};
// CTaskGroup
class CTaskGroup
{
public:
typedef map < int, bool > taskCallback_m;
CTaskGroup( void );
~CTaskGroup( void );
void Init( void );
int Add( CTask *task );
void SetGUID( int GUID );
void SetParent( CTaskGroup *group ) { m_parent = group; }
bool Complete(void) const { return ( m_numCompleted == m_completedTasks.size() ); }
bool MarkTaskComplete( int id );
CTaskGroup *GetParent( void ) const { return m_parent; }
int GetGUID( void ) const { return m_GUID; }
// Overloaded new operator.
static void *operator new( size_t size )
{ // Allocate the memory.
return IGameInterface::GetGame()->Malloc( size );
}
// Overloaded delete operator.
static void operator delete( void *pRawData )
{ // Free the Memory.
IGameInterface::GetGame()->Free( pRawData );
}
//protected:
taskCallback_m m_completedTasks;
CTaskGroup *m_parent;
unsigned int m_numCompleted;
int m_GUID;
};
// CTaskManager
class CSequencer;
class CTaskManager
{
typedef map < int, CTask * > taskID_m;
typedef map < string, CTaskGroup * > taskGroupName_m;
typedef map < int, CTaskGroup * > taskGroupID_m;
typedef vector < CTaskGroup * > taskGroup_v;
typedef list < CTask *> tasks_l;
public:
CTaskManager();
~CTaskManager();
int GetID();
static CTaskManager *Create( void );
CBlock *GetCurrentTask( void );
int Init( CSequencer *owner );
int Free( void );
int Flush( void );
int SetCommand( CBlock *block, int type, CIcarus* icarus );
int Completed( int id );
int Update( CIcarus* icarus );
int IsRunning( void ) const { return(!m_tasks.empty()); };
bool IsResident( void ) const { return m_resident;};
CTaskGroup *AddTaskGroup( const char *name , CIcarus* icarus);
CTaskGroup *GetTaskGroup( const char *name, CIcarus* icarus);
CTaskGroup *GetTaskGroup( int id, CIcarus* icarus );
int MarkTask( int id, int operation, CIcarus* icarus );
CBlock *RecallTask( void );
void Save();
void Load( CIcarus* icarus );
// Overloaded new operator.
inline void* operator new( size_t size )
{ // Allocate the memory.
return IGameInterface::GetGame()->Malloc( size );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{ // Free the Memory.
IGameInterface::GetGame()->Free( pRawData );
}
protected:
int Go( CIcarus* icarus ); //Heartbeat function called once per game frame
int CallbackCommand( CTask *task, int returnCode, CIcarus* icarus );
inline bool Check( int targetID, CBlock *block, int memberNum ) const;
int GetVector( int entID, CBlock *block, int &memberNum, vec3_t &value, CIcarus* icarus );
int GetFloat( int entID, CBlock *block, int &memberNum, float &value, CIcarus* icarus );
int Get( int entID, CBlock *block, int &memberNum, char **value, CIcarus* icarus );
int PushTask( CTask *task, int flag );
CTask *PopTask( int flag );
// Task functions
int Rotate( CTask *task, CIcarus* icarus );
int Remove( CTask *task , CIcarus* icarus);
int Camera( CTask *task, CIcarus* icarus );
int Print( CTask *task , CIcarus* icarus);
int Sound( CTask *task, CIcarus* icarus );
int Move( CTask *task , CIcarus* icarus);
int Kill( CTask *task , CIcarus* icarus);
int Set( CTask *task, CIcarus* icarus );
int Use( CTask *task , CIcarus* icarus);
int DeclareVariable( CTask *task , CIcarus* icarus);
int FreeVariable( CTask *task, CIcarus* icarus );
int Signal( CTask *task , CIcarus* icarus);
int Play( CTask *task , CIcarus* icarus);
int Wait( CTask *task, bool &completed, CIcarus* icarus );
int WaitSignal( CTask *task, bool &completed, CIcarus* icarus);
int SaveCommand( CBlock *block );
// Variables
CSequencer *m_owner;
int m_ownerID;
CTaskGroup *m_curGroup;
taskGroup_v m_taskGroups;
tasks_l m_tasks;
int m_GUID;
int m_count;
taskGroupName_m m_taskGroupNameMap;
taskGroupID_m m_taskGroupIDMap;
bool m_resident;
int m_id;
//CTask *m_waitTask; //Global pointer to the current task that is waiting for callback completion
};
#endif //__TASK_MANAGER__