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

View File

@@ -0,0 +1,698 @@
//Anything above this #include will be ignored by the compiler
#include "../qcommon/exe_headers.h"
// Interpreted Block Stream Functions
//
// -- jweier
// this include must remain at the top of every Icarus CPP file
#include "icarus.h"
#pragma warning(disable : 4100) //unref formal parm
#pragma warning(disable : 4710) //member not inlined
#include <string.h>
#include "blockstream.h"
/*
===================================================================================================
CBlockMember
===================================================================================================
*/
CBlockMember::CBlockMember( void )
{
m_id = -1;
m_size = -1;
m_data = NULL;
}
CBlockMember::~CBlockMember( void )
{
Free();
}
/*
-------------------------
Free
-------------------------
*/
void CBlockMember::Free( void )
{
if ( m_data != NULL )
{
ICARUS_Free ( m_data );
m_data = NULL;
m_id = m_size = -1;
}
}
/*
-------------------------
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 )
{
WriteDataPointer( data, strlen(data)+1 );
}
void CBlockMember::SetData( vector_t data )
{
WriteDataPointer( data, 3 );
}
void CBlockMember::SetData( void *data, int size )
{
if ( m_data )
ICARUS_Free( m_data );
m_data = ICARUS_Malloc( size );
memcpy( m_data, data, size );
m_size = size;
}
// Member I/O functions
/*
-------------------------
ReadMember
-------------------------
*/
int CBlockMember::ReadMember( char **stream, long *streamPos )
{
m_id = *(int *) (*stream + *streamPos);
*streamPos += sizeof( int );
if ( m_id == 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 = ICARUS_Malloc( m_size );
float infinite = Q3_INFINITE;
memcpy( m_data, &infinite, m_size );
}
else
{
m_size = *(long *) (*stream + *streamPos);
*streamPos += sizeof( long );
m_data = ICARUS_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( void )
{
CBlockMember *newblock = new CBlockMember;
if ( newblock == NULL )
return NULL;
newblock->SetData( m_data, m_size );
newblock->SetSize( m_size );
newblock->SetID( m_id );
return newblock;
}
/*
===================================================================================================
CBlock
===================================================================================================
*/
CBlock::CBlock( void )
{
m_flags = 0;
m_id = 0;
}
CBlock::~CBlock( void )
{
Free();
}
/*
-------------------------
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( void )
{
int numMembers = GetNumMembers();
CBlockMember *bMember;
while ( numMembers-- )
{
bMember = GetMember( numMembers );
if (!bMember)
return false;
delete bMember;
}
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 )
{
CBlockMember *bMember = new CBlockMember;
bMember->SetID( member_id );
bMember->SetData( member_data );
bMember->SetSize( strlen(member_data) + 1 );
AddMember( bMember );
return true;
}
int CBlock::Write( int member_id, vector_t member_data )
{
CBlockMember *bMember;
bMember = new CBlockMember;
bMember->SetID( member_id );
bMember->SetData( member_data );
bMember->SetSize( sizeof(vector_t) );
AddMember( bMember );
return true;
}
int CBlock::Write( int member_id, float member_data )
{
CBlockMember *bMember = new CBlockMember;
bMember->SetID( member_id );
bMember->WriteData( member_data );
bMember->SetSize( sizeof(member_data) );
AddMember( bMember );
return true;
}
int CBlock::Write( int member_id, int member_data )
{
CBlockMember *bMember = new CBlockMember;
bMember->SetID( member_id );
bMember->WriteData( member_data );
bMember->SetSize( sizeof(member_data) );
AddMember( bMember );
return true;
}
int CBlock::Write( CBlockMember *bMember )
{
// 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( void )
{
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() );
}
return newblock;
}
/*
===================================================================================================
CBlockStream
===================================================================================================
*/
CBlockStream::CBlockStream( void )
{
m_stream = NULL;
m_streamPos = 0;
}
CBlockStream::~CBlockStream( void )
{
}
/*
-------------------------
GetChar
-------------------------
*/
char CBlockStream::GetChar( void )
{
char data;
data = *(char*) (m_stream + m_streamPos);
m_streamPos += sizeof( data );
return data;
}
/*
-------------------------
GetUnsignedInteger
-------------------------
*/
unsigned CBlockStream::GetUnsignedInteger( void )
{
unsigned data;
data = *(unsigned *) (m_stream + m_streamPos);
m_streamPos += sizeof( data );
return data;
}
/*
-------------------------
GetInteger
-------------------------
*/
int CBlockStream::GetInteger( void )
{
int data;
data = *(int *) (m_stream + m_streamPos);
m_streamPos += sizeof( data );
return data;
}
/*
-------------------------
GetLong
-------------------------
*/
long CBlockStream::GetLong( void )
{
long data;
data = *(long *) (m_stream + m_streamPos);
m_streamPos += sizeof( data );
return data;
}
/*
-------------------------
GetFloat
-------------------------
*/
float CBlockStream::GetFloat( void )
{
float data;
data = *(float *) (m_stream + m_streamPos);
m_streamPos += sizeof( data );
return data;
}
// Extension stripping utility
/*
-------------------------
StripExtension
-------------------------
*/
void CBlockStream::StripExtension( const char *in, char *out )
{
int i = strlen(in);
while ( (in[i] != '.') && (i >= 0) )
i--;
if ( i < 0 )
{
strcpy(out, in);
return;
}
strncpy(out, in, i);
}
/*
-------------------------
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 )
{
char newName[MAX_FILENAME_LENGTH], *id_header = IBI_HEADER_ID;
float version = IBI_VERSION;
//Clear the temp string
memset(newName, 0, sizeof(newName));
//Strip the extension and add the BLOCK_EXT extension
strcpy((char *) m_fileName, filename);
StripExtension( (char *) m_fileName, (char *) &newName );
strcat((char *) newName, IBI_EXT);
//Recover that as the active filename
strcpy(m_fileName, newName);
if ( ((m_fileHandle = fopen(m_fileName, "wb")) == NULL) )
{
return false;
}
fwrite( id_header, 1, sizeof(id_header), m_fileHandle );
fwrite( &version, 1, sizeof(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 )
{
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();
return true;
}
/*
-------------------------
BlockAvailable
-------------------------
*/
int CBlockStream::BlockAvailable( void )
{
if ( m_streamPos >= m_fileSize )
return false;
return true;
}
/*
-------------------------
ReadBlock
-------------------------
*/
int CBlockStream::ReadBlock( CBlock *get )
{
CBlockMember *bMember;
int b_id, numMembers;
unsigned char flags;
if (!BlockAvailable())
return false;
b_id = GetInteger();
numMembers = GetInteger();
flags = (unsigned char) GetChar();
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 );
get->AddMember( bMember );
}
#ifdef _XBOX
Z_SetNewDeleteTemporary(false);
#endif
return true;
}
/*
-------------------------
Open
-------------------------
*/
int CBlockStream::Open( char *buffer, long size )
{
char id_header[sizeof(IBI_HEADER_ID)];
float version;
Init();
m_fileSize = size;
m_stream = buffer;
for ( int i = 0; i < sizeof( id_header ); i++ )
{
id_header[i] = GetChar();
}
version = GetFloat();
//Check for valid header
if ( strcmp( id_header, IBI_HEADER_ID ) )
{
Free();
return false;
}
//Check for valid version
if ( version != IBI_VERSION )
{
Free();
return false;
}
return true;
}

198
codemp/icarus/blockstream.h Normal file
View File

@@ -0,0 +1,198 @@
// BlockStream.h
#ifndef __INTERPRETED_BLOCK_STREAM__
#define __INTERPRETED_BLOCK_STREAM__
#pragma warning(disable : 4786) //identifier was truncated
#pragma warning(disable : 4514) //unreffed inline func removed
#include "../qcommon/qcommon.h"
#include <stdio.h>
#pragma warning (push, 3) //go back down to 3 for the stl include
#include <list>
#include <vector>
#pragma warning (pop)
using namespace std;
#define IBI_EXT ".IBI" //(I)nterpreted (B)lock (I)nstructions
#define IBI_HEADER_ID "IBI"
const float IBI_VERSION = 1.57f;
const int MAX_FILENAME_LENGTH = 1024;
typedef float vector_t[3];
enum
{
POP_FRONT,
POP_BACK,
PUSH_FRONT,
PUSH_BACK
};
// Templates
// CBlockMember
class CBlockMember
{
public:
CBlockMember();
~CBlockMember();
void Free( void );
int WriteMember ( FILE * ); //Writes the member's data, in block format, to FILE *
int ReadMember( char **, long * ); //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 * );
void SetData( vector_t );
void SetData( void *data, int size );
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
inline void *operator new( size_t size )
{ // Allocate the memory.
return Z_Malloc( size, TAG_ICARUS4, qtrue );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{ // Free the Memory.
Z_Free( pRawData );
}
CBlockMember *Duplicate( void );
template <class T> void WriteData(T &data)
{
if ( m_data )
{
ICARUS_Free( m_data );
}
m_data = ICARUS_Malloc( sizeof(T) );
*((T *) m_data) = data;
m_size = sizeof(T);
}
template <class T> void WriteDataPointer(const T *data, int num)
{
if ( m_data )
{
ICARUS_Free( m_data );
}
m_data = ICARUS_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();
~CBlock();
int Init( void );
int Create( int );
int Free();
//Write Overloads
int Write( int, vector_t );
int Write( int, float );
int Write( int, const char * );
int Write( int, int );
int Write( CBlockMember * );
//Member push / pop functions
int AddMember( CBlockMember * );
CBlockMember *GetMember( int memberNum );
void *GetMemberData( int memberNum );
CBlock *Duplicate( void );
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; }
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();
~CBlockStream();
int Init( void );
int Create( char * );
int Free( void );
// Stream I/O functions
int BlockAvailable( void );
int WriteBlock( CBlock * ); //Write the block out
int ReadBlock( CBlock * ); //Read the block in
int Open( char *, long ); //Open a stream for reading / writing
protected:
unsigned GetUnsignedInteger( void );
int GetInteger( void );
char GetChar( void );
long GetLong( void );
float GetFloat( void );
void StripExtension( const char *, char * ); //Utility function to strip away file extensions
long m_fileSize; //Size of the file
FILE *m_fileHandle; //Global file handle of current I/O source
char m_fileName[MAX_FILENAME_LENGTH]; //Name of the current file
char *m_stream; //Stream of data to be parsed
long m_streamPos;
};
#endif //__INTERPRETED_BLOCK_STREAM__

View File

@@ -0,0 +1,733 @@
//Anything above this #include will be ignored by the compiler
#include "../qcommon/exe_headers.h"
// ICARUS Utility functions
//rww - mangled to work in server exe setting.
//#include "Q3_Interface.h"
//#include "g_roff.h"
#include "../game/g_public.h"
#include "../server/server.h"
#include "interface.h"
#include "GameInterface.h"
#include "../qcommon/RoffSystem.h"
#include "Q3_Interface.h"
ICARUS_Instance *iICARUS;
bufferlist_t ICARUS_BufferList;
entlist_t ICARUS_EntList;
extern unsigned Com_BlockChecksum (const void *buffer, int length);
extern void Q3_DebugPrint( int level, const char *format, ... );
int ICARUS_entFilter = -1;
/*
=============
ICARUS_GetScript
gets the named script from the cache or disk if not already loaded
=============
*/
int ICARUS_GetScript( const char *name, char **buf )
{
bufferlist_t::iterator ei;
//Make sure the caller is valid
//Attempt to retrieve a precached script
ei = ICARUS_BufferList.find( (char *) name );
//Not found, check the disk
if ( ei == ICARUS_BufferList.end() )
{
if ( ICARUS_RegisterScript( name ) == false )
return 0;
//Script is now inserted, retrieve it and pass through
ei = ICARUS_BufferList.find( (char *) name );
if ( ei == ICARUS_BufferList.end() )
{
//NOTENOTE: This is an internal error in STL if this happens...
assert(0);
return 0;
}
}
*buf = (*ei).second->buffer;
return (*ei).second->length;
}
/*
=============
ICARUS_RunScript
Runs the script by the given name
=============
*/
int ICARUS_RunScript( sharedEntity_t *ent, const char *name )
{
char *buf;
int len;
//Make sure the caller is valid
if ( gSequencers[ent->s.number] == NULL )
{
//Com_Printf( "%s : entity is not a valid script user\n", ent->classname );
return false;
}
#ifdef _HACK_FOR_TESTING_ONLY_1
char namex[1024];
char *blah = strstr(name, "stu/");
int r = blah - name;
if (blah)
{
int i = 0;
while (i < r)
{
namex[i] = name[i];
i++;
}
namex[i] = 0;
strcat(namex, "ignorethisfolder/");
i = strlen(namex);
while (name[r] != '/')
{
r++;
}
r++;
while (name[r])
{
namex[i] = name[r];
r++;
i++;
}
namex[i] = 0;
}
else
{
strcpy(namex, name);
}
len = ICARUS_GetScript (namex, &buf);
#else
len = ICARUS_GetScript (name, &buf);
#endif
if (len == 0)
{
return false;
}
//Attempt to run the script
if S_FAILED(gSequencers[ent->s.number]->Run( buf, len ))
return false;
if ( ( ICARUS_entFilter == -1 ) || ( ICARUS_entFilter == ent->s.number ) )
{
Q3_DebugPrint( WL_VERBOSE, "%d Script %s executed by %s %s\n", svs.time, (char *) name, ent->classname, ent->targetname );
}
return true;
}
/*
=================
ICARUS_Init
Allocates a new ICARUS instance
=================
*/
void ICARUS_Init( void )
{
//Link all interface functions
Interface_Init( &interface_export );
//Create the ICARUS instance for this session
iICARUS = ICARUS_Instance::Create( &interface_export );
if ( iICARUS == NULL )
{
Com_Error( ERR_DROP, "Unable to initialize ICARUS instance\n" );
return;
}
}
/*
=================
ICARUS_Shutdown
Frees up ICARUS resources from all entities
=================
*/
void ICARUS_Shutdown( void )
{
bufferlist_t::iterator ei;
sharedEntity_t *ent = SV_GentityNum(0);
//Release all ICARUS resources from the entities
for ( int i = 0; i < /*globals.num_entities*/MAX_GENTITIES; i++ )
{
ent = SV_GentityNum(i);
if (gSequencers[i])
{
if (ent->s.number >= MAX_GENTITIES ||
ent->s.number < 0)
{
ent->s.number = i;
assert(0);
}
ICARUS_FreeEnt( ent );
}
}
//Clear out all precached scripts
for ( ei = ICARUS_BufferList.begin(); ei != ICARUS_BufferList.end(); ei++ )
{
//gi.Free( (*ei).second->buffer );
ICARUS_Free((*ei).second->buffer);
delete (*ei).second;
}
ICARUS_BufferList.clear();
//Clear the name map
ICARUS_EntList.clear();
//Free this instance
if ( iICARUS )
{
iICARUS->Delete();
iICARUS = NULL;
}
}
/*
==============
ICARUS_FreeEnt
Frees all ICARUS resources on an entity
WARNING!!! DO NOT DO THIS WHILE RUNNING A SCRIPT, ICARUS WILL CRASH!!!
FIXME: shouldn't ICARUS handle this internally?
==============
*/
void ICARUS_FreeEnt( sharedEntity_t *ent )
{
assert( iICARUS );
if (ent->s.number >= MAX_GENTITIES ||
ent->s.number < 0)
{
assert(0);
return;
}
//Make sure the ent is valid
if ( gSequencers[ent->s.number] == NULL )
return;
//Remove them from the ICARUSE_EntList list so that when their g_entity index is reused, ICARUS doesn't try to affect the new (incorrect) ent.
if VALIDSTRING( ent->script_targetname )
{
char temp[1024];
strncpy( (char *) temp, ent->script_targetname, 1023 );
temp[ 1023 ] = 0;
entlist_t::iterator it = ICARUS_EntList.find( Q_strupr(temp) );
if (it != ICARUS_EntList.end())
{
ICARUS_EntList.erase(it);
}
}
//Delete the sequencer and the task manager
iICARUS->DeleteSequencer( gSequencers[ent->s.number] );
//Clean up the pointers
gSequencers[ent->s.number] = NULL;
gTaskManagers[ent->s.number] = NULL;
}
/*
==============
ICARUS_ValidEnt
Determines whether or not an entity needs ICARUS information
==============
*/
bool ICARUS_ValidEnt( sharedEntity_t *ent )
{
int i;
//Targeted by a script
if VALIDSTRING( ent->script_targetname )
return true;
//Potentially able to call a script
for ( i = 0; i < NUM_BSETS; i++ )
{
if VALIDSTRING( ent->behaviorSet[i] )
{
//Com_Printf( "WARNING: Entity %d (%s) has behaviorSet but no script_targetname -- using targetname\n", ent->s.number, ent->targetname );
//ent->script_targetname = ent->targetname;
//rww - You CANNOT do things like this now. We're switching memory around to be able to read this memory from vm land,
//and while this allows us to read it on our "fake" entity here, we can't modify pointers like this. We can however do
//something completely hackish such as the following.
assert(ent->s.number >= 0 && ent->s.number < MAX_GENTITIES);
sharedEntity_t *trueEntity = SV_GentityNum(ent->s.number);
//This works because we're modifying the actual shared game vm data and turning one pointer into another.
//While these pointers both look like garbage to us in here, they are not.
trueEntity->script_targetname = trueEntity->targetname;
return true;
}
}
return false;
}
/*
==============
ICARUS_AssociateEnt
Associate the entity's id and name so that it can be referenced later
==============
*/
void ICARUS_AssociateEnt( sharedEntity_t *ent )
{
char temp[1024];
if ( VALIDSTRING( ent->script_targetname ) == false )
return;
strncpy( (char *) temp, ent->script_targetname, 1023 );
temp[ 1023 ] = 0;
ICARUS_EntList[ Q_strupr( (char *) temp ) ] = ent->s.number;
}
/*
==============
ICARUS_RegisterScript
Loads and caches a script
==============
*/
bool ICARUS_RegisterScript( const char *name, qboolean bCalledDuringInterrogate /* = false */ )
{
bufferlist_t::iterator ei;
pscript_t *pscript;
char newname[MAX_FILENAME_LENGTH];
char *buffer = NULL; // lose compiler warning about uninitialised vars
long length;
//Make sure this isn't already cached
ei = ICARUS_BufferList.find( (char *) name );
// note special return condition here, if doing interrogate and we already have this file then we MUST return
// false (which stops the interrogator proceeding), this not only saves some time, but stops a potential
// script recursion bug which could lock the program in an infinite loop... Return TRUE for normal though!
//
if ( ei != ICARUS_BufferList.end() )
return (bCalledDuringInterrogate)?false:true;
sprintf((char *) newname, "%s%s", name, IBI_EXT );
// small update here, if called during interrogate, don't let gi.FS_ReadFile() complain because it can't
// find stuff like BS_RUN_AND_SHOOT as scriptname... During FINALBUILD the message won't appear anyway, hence
// the ifndef, this just cuts down on internal error reports while testing release mode...
//
qboolean qbIgnoreFileRead = qfalse;
//
// NOTENOTE: For the moment I've taken this back out, to avoid doubling the number of fopen()'s per file.
#if 0//#ifndef FINAL_BUILD
if (bCalledDuringInterrogate)
{
fileHandle_t file;
gi.FS_FOpenFile( newname, &file, FS_READ );
if ( file == NULL )
{
qbIgnoreFileRead = qtrue; // warn disk code further down not to try FS_ReadFile()
}
else
{
gi.FS_FCloseFile( file );
}
}
#endif
length = qbIgnoreFileRead ? -1 : FS_ReadFile( newname, (void **) &buffer );
if ( length <= 0 )
{
// File not found, but keep quiet during interrogate stage, because of stuff like BS_RUN_AND_SHOOT as scriptname
//
if (!bCalledDuringInterrogate)
{
Com_Printf(S_COLOR_RED"Could not open file '%s'\n", newname );
}
return false;
}
pscript = new pscript_t;
pscript->buffer = (char *) ICARUS_Malloc(length);//gi.Malloc(length, TAG_ICARUS, qfalse);
memcpy (pscript->buffer, buffer, length);
pscript->length = length;
FS_FreeFile( buffer );
ICARUS_BufferList[ name ] = pscript;
return true;
}
void ICARUS_SoundPrecache(const char *filename)
{
T_G_ICARUS_SOUNDINDEX *sharedMem = (T_G_ICARUS_SOUNDINDEX *)sv.mSharedMemory;
strcpy(sharedMem->filename, filename);
VM_Call(gvm, GAME_ICARUS_SOUNDINDEX);
}
int ICARUS_GetIDForString( const char *string )
{
T_G_ICARUS_GETSETIDFORSTRING *sharedMem = (T_G_ICARUS_GETSETIDFORSTRING *)sv.mSharedMemory;
strcpy(sharedMem->string, string);
return VM_Call(gvm, GAME_ICARUS_GETSETIDFORSTRING);
}
/*
-------------------------
ICARUS_InterrogateScript
-------------------------
*/
// at this point the filename should have had the "scripts" (Q3_SCRIPT_DIR) added to it (but not the IBI extension)
//
void ICARUS_InterrogateScript( const char *filename )
{
CBlockStream stream;
CBlockMember *blockMember;
CBlock block;
if (!Q_stricmp(filename,"NULL") || !Q_stricmp(filename,"default"))
return;
//////////////////////////////////
//
// ensure "scripts" (Q3_SCRIPT_DIR), which will be missing if this was called recursively...
//
char sFilename[MAX_FILENAME_LENGTH]; // should really be MAX_QPATH (and 64 bytes instead of 1024), but this fits the rest of the code
if (!Q_stricmpn(filename,Q3_SCRIPT_DIR,strlen(Q3_SCRIPT_DIR)))
{
Q_strncpyz(sFilename,filename,sizeof(sFilename));
}
else
{
Q_strncpyz(sFilename,va("%s/%s",Q3_SCRIPT_DIR,filename),sizeof(sFilename));
}
//
//////////////////////////////////
//Attempt to register this script
if ( ICARUS_RegisterScript( sFilename, qtrue ) == false ) // true = bCalledDuringInterrogate
return;
char *buf;
long len;
//Attempt to retrieve the new script data
if ( ( len = ICARUS_GetScript ( sFilename, &buf ) ) == 0 )
return;
//Open the stream
if ( stream.Open( buf, len ) == qfalse )
return;
const char *sVal1, *sVal2;
char temp[1024];
int setID;
//Now iterate through all blocks of the script, searching for keywords
while ( stream.BlockAvailable() )
{
//Get a block
if ( stream.ReadBlock( &block ) == qfalse )
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 );
//we can do this I guess since the roff is loaded on the server.
theROFFSystem.Cache((char *)sVal1, qfalse);
}
}
break;
case ID_PLAY: // to cache ROFF files
sVal1 = (const char *) block.GetMemberData( 0 );
if (!Q_stricmp(sVal1,"PLAY_ROFF"))
{
sVal1 = (const char *) block.GetMemberData( 1 );
//we can do this I guess since the roff is loaded on the server.
theROFFSystem.Cache((char *)sVal1, qfalse);
}
break;
//Run commands
case ID_RUN:
sVal1 = (const char *) block.GetMemberData( 0 );
COM_StripExtension( sVal1, (char *) temp );
ICARUS_InterrogateScript( (const char *) &temp );
break;
case ID_SOUND:
//We can't just call over to S_RegisterSound or whatever because this is on the server.
sVal1 = (const char *) block.GetMemberData( 1 ); //0 is channel, 1 is filename
ICARUS_SoundPrecache(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 );
//Get the id for this set identifier
setID = ICARUS_GetIDForString( sVal1 );
//Check against valid types
switch ( setID )
{
case SET_SPAWNSCRIPT:
case SET_USESCRIPT:
case SET_AWAKESCRIPT:
case SET_ANGERSCRIPT:
case SET_ATTACKSCRIPT:
case SET_VICTORYSCRIPT:
case SET_LOSTENEMYSCRIPT:
case SET_PAINSCRIPT:
case SET_FLEESCRIPT:
case SET_DEATHSCRIPT:
case SET_DELAYEDSCRIPT:
case SET_BLOCKEDSCRIPT:
case SET_FFIRESCRIPT:
case SET_FFDEATHSCRIPT:
case SET_MINDTRICKSCRIPT:
case SET_CINEMATIC_SKIPSCRIPT:
//Recursively obtain all embedded scripts
ICARUS_InterrogateScript( sVal2 );
break;
case SET_LOOPSOUND: //like ID_SOUND, but set's looping
ICARUS_SoundPrecache(sVal2);
break;
case SET_VIDEO_PLAY: //in game cinematic
//do nothing for MP.
break;
case SET_ADDRHANDBOLT_MODEL:
case SET_ADDLHANDBOLT_MODEL:
//do nothing for MP
break;
default:
break;
}
}
break;
default:
break;
}
//Clean out the block for the next pass
block.Free();
}
//All done
stream.Free();
}
#ifdef _XBOX // We borrow the one in NPC_stats.c
extern stringID_table_t BSTable[];
#else
stringID_table_t BSTable[] =
{
ENUM2STRING(BS_DEFAULT),//# default behavior for that NPC
ENUM2STRING(BS_ADVANCE_FIGHT),//# Advance to captureGoal and shoot enemies if you can
ENUM2STRING(BS_SLEEP),//# Play awake script when startled by sound
ENUM2STRING(BS_FOLLOW_LEADER),//# Follow your leader and shoot any enemies you come across
ENUM2STRING(BS_JUMP),//# Face navgoal and jump to it.
ENUM2STRING(BS_SEARCH),//# Using current waypoint as a base), search the immediate branches of waypoints for enemies
ENUM2STRING(BS_WANDER),//# Wander down random waypoint paths
ENUM2STRING(BS_NOCLIP),//# Moves through walls), etc.
ENUM2STRING(BS_REMOVE),//# Waits for player to leave PVS then removes itself
ENUM2STRING(BS_CINEMATIC),//# Does nothing but face it's angles and move to a goal if it has one
//the rest are internal only
"", -1,
};
#endif
/*
==============
ICARUS_PrecacheEnt
Precache all scripts being used by the entity
==============
*/
void ICARUS_PrecacheEnt( sharedEntity_t *ent )
{
char newname[MAX_FILENAME_LENGTH];
int i;
for ( i = 0; i < NUM_BSETS; i++ )
{
if ( ent->behaviorSet[i] == NULL )
continue;
if ( GetIDForString( BSTable, ent->behaviorSet[i] ) == -1 )
{//not a behavior set
sprintf((char *) newname, "%s/%s", Q3_SCRIPT_DIR, ent->behaviorSet[i] );
//Precache this, and all internally referenced scripts
ICARUS_InterrogateScript( newname );
}
}
}
/*
==============
ICARUS_InitEnt
Allocates a sequencer and task manager only if an entity is a potential script user
==============
*/
void Q3_TaskIDClear( int *taskID );
void ICARUS_InitEnt( sharedEntity_t *ent )
{
//Make sure this is a fresh ent
assert( iICARUS );
assert( gTaskManagers[ent->s.number] == NULL );
assert( gSequencers[ent->s.number] == NULL );
if ( gSequencers[ent->s.number] != NULL )
return;
if ( gTaskManagers[ent->s.number] != NULL )
return;
//Create the sequencer and setup the task manager
gSequencers[ent->s.number] = iICARUS->GetSequencer( ent->s.number );
gTaskManagers[ent->s.number] = gSequencers[ent->s.number]->GetTaskManager();
//Initialize all taskIDs to -1
memset( &ent->taskID, -1, sizeof( ent->taskID ) );
//Add this entity to a map of valid associated ents for quick retrieval later
ICARUS_AssociateEnt( ent );
//Precache all the entity's scripts
ICARUS_PrecacheEnt( ent );
}
/*
-------------------------
ICARUS_LinkEntity
-------------------------
*/
int ICARUS_LinkEntity( int entID, CSequencer *sequencer, CTaskManager *taskManager )
{
sharedEntity_t *ent = SV_GentityNum(entID);
if ( ent == NULL )
return false;
gSequencers[ent->s.number] = sequencer;
gTaskManagers[ent->s.number] = taskManager;
ICARUS_AssociateEnt( ent );
return true;
}
/*
-------------------------
Svcmd_ICARUS_f
-------------------------
*/
void Svcmd_ICARUS_f( void )
{
//rwwFIXMEFIXME: Do something with this for debugging purposes at some point.
/*
char *cmd = Cmd_Argv( 1 );
if ( Q_stricmp( cmd, "log" ) == 0 )
{
//g_ICARUSDebug->integer = WL_DEBUG;
if ( VALIDSTRING( Cmd_Argv( 2 ) ) )
{
sharedEntity_t *ent = G_Find( NULL, FOFS( script_targetname ), gi.argv(2) );
if ( ent == NULL )
{
Com_Printf( "Entity \"%s\" not found!\n", gi.argv(2) );
return;
}
//Start logging
Com_Printf("Logging ICARUS info for entity %s\n", gi.argv(2) );
ICARUS_entFilter = ( ent->s.number == ICARUS_entFilter ) ? -1 : ent->s.number;
return;
}
Com_Printf("Logging ICARUS info for all entities\n");
return;
}
*/
return;
}

View File

@@ -0,0 +1,36 @@
#ifndef __G_ICARUS_H__
#define __G_ICARUS_H__
typedef struct pscript_s
{
char *buffer;
long length;
} pscript_t;
typedef map < string, int, less<string>, allocator<int> > entlist_t;
typedef map < string, pscript_t*, less<string>, allocator<pscript_t*> > bufferlist_t;
//ICARUS includes
extern interface_export_t interface_export;
extern void Interface_Init( interface_export_t *pe );
extern int ICARUS_RunScript( sharedEntity_t *ent, const char *name );
extern bool ICARUS_RegisterScript( const char *name, qboolean bCalledDuringInterrogate = qfalse);
extern ICARUS_Instance *iICARUS;
extern bufferlist_t ICARUS_BufferList;
extern entlist_t ICARUS_EntList;
//
// g_ICARUS.cpp
//
void ICARUS_Init( void );
bool ICARUS_ValidEnt( sharedEntity_t *ent );
void ICARUS_InitEnt( sharedEntity_t *ent );
void ICARUS_FreeEnt( sharedEntity_t *ent );
void ICARUS_AssociateEnt( sharedEntity_t *ent );
void ICARUS_Shutdown( void );
void Svcmd_ICARUS_f( void );
extern int ICARUS_entFilter;
#endif//#ifndef __G_ICARUS_H__

32
codemp/icarus/icarus.h Normal file
View File

@@ -0,0 +1,32 @@
// ICARUS Public Header File
#pragma warning ( disable : 4786 ) //NOTENOTE: STL Debug name length warning
#ifndef __ICARUS__
#define __ICARUS__
#include "../game/g_public.h"
#pragma warning( disable : 4786 ) // identifier was truncated
#pragma warning( disable : 4514 ) // unreferenced inline was removed
#pragma warning( disable : 4710 ) // not inlined
#pragma warning( push, 3 ) //save current state and change to 3
#define STL_ITERATE( a, b ) for ( a = b.begin(); a != b.end(); a++ )
#define STL_INSERT( a, b ) a.insert( a.end(), b );
#include "tokenizer.h"
#include "blockstream.h"
#include "interpreter.h"
#include "sequencer.h"
#include "taskmanager.h"
#include "instance.h"
#pragma warning( pop ) //restore
extern void *ICARUS_Malloc(int iSize);
extern void ICARUS_Free(void *pMem);
#endif //__ICARUS__

655
codemp/icarus/instance.cpp Normal file
View File

@@ -0,0 +1,655 @@
//Anything above this #include will be ignored by the compiler
#include "../qcommon/exe_headers.h"
// ICARUS Instance
//
// -- jweier
// this include must remain at the top of every Icarus CPP file
#include "icarus.h"
#include <assert.h>
class CSequencer;
class CTaskManager;
//We can't put these on entity fields since all that stuff is in C
//which can't be changed due to VMs. So we'll use a global array
//and access by the entity index given.
CSequencer *gSequencers[MAX_GENTITIES];
CTaskManager *gTaskManagers[MAX_GENTITIES];
// Instance
ICARUS_Instance::ICARUS_Instance( void )
{
m_GUID = 0;
//to be safe
memset(gSequencers,0, sizeof(gSequencers));
memset(gTaskManagers,0, sizeof(gTaskManagers));
#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
}
ICARUS_Instance::~ICARUS_Instance( void )
{
}
/*
-------------------------
Create
-------------------------
*/
ICARUS_Instance *ICARUS_Instance::Create( interface_export_t *ie )
{
ICARUS_Instance *instance = new ICARUS_Instance;
instance->m_interface = ie;
#ifndef __linux__
Com_Printf( "ICARUS Instance successfully created\n" );
#endif
return instance;
}
/*
-------------------------
Free
-------------------------
*/
int ICARUS_Instance::Free( void )
{
sequencer_l::iterator sri;
//Delete any residual sequencers
STL_ITERATE( sri, m_sequencers )
{
delete (*sri);
#ifdef _DEBUG
m_DEBUG_NumSequencerResidual++;
#endif
}
m_sequencers.clear();
//all these are deleted now so clear the global map.
memset(gSequencers,0, sizeof(gSequencers));
memset(gTaskManagers,0, sizeof(gTaskManagers));
m_signals.clear();
sequence_l::iterator si;
//Delete any residual sequences
STL_ITERATE( si, m_sequences )
{
delete (*si);
#ifdef _DEBUG
m_DEBUG_NumSequenceResidual++;
#endif
}
m_sequences.clear();
return true;
}
/*
-------------------------
Delete
-------------------------
*/
int ICARUS_Instance::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
delete this;
return true;
}
/*
-------------------------
GetSequencer
-------------------------
*/
CSequencer *ICARUS_Instance::GetSequencer( int ownerID )
{
CSequencer *sequencer = CSequencer::Create();
CTaskManager *taskManager = CTaskManager::Create();
sequencer->Init( ownerID, m_interface, taskManager, this );
taskManager->Init( sequencer );
STL_INSERT( m_sequencers, sequencer );
#ifdef _DEBUG
m_DEBUG_NumSequencerAlloc++;
#endif
return sequencer;
}
/*
-------------------------
DeleteSequencer
-------------------------
*/
void ICARUS_Instance::DeleteSequencer( CSequencer *sequencer )
{
// added 2/12/2 to properly delete blocks that were passed to the task manager
sequencer->Recall();
CTaskManager *taskManager = sequencer->GetTaskManager();
if ( taskManager )
{
taskManager->Free();
delete taskManager;
}
m_sequencers.remove( sequencer );
sequencer->Free();
delete sequencer;
#ifdef _DEBUG
m_DEBUG_NumSequencerFreed++;
#endif
}
/*
-------------------------
GetSequence
-------------------------
*/
CSequence *ICARUS_Instance::GetSequence( void )
{
CSequence *sequence = CSequence::Create();
//Assign the GUID
sequence->SetID( m_GUID++ );
sequence->SetOwner( this );
STL_INSERT( m_sequences, sequence );
#ifdef _DEBUG
m_DEBUG_NumSequenceAlloc++;
#endif
return sequence;
}
/*
-------------------------
GetSequence
-------------------------
*/
CSequence *ICARUS_Instance::GetSequence( int id )
{
sequence_l::iterator si;
STL_ITERATE( si, m_sequences )
{
if ( (*si)->GetID() == id )
return (*si);
}
return NULL;
}
/*
-------------------------
DeleteSequence
-------------------------
*/
void ICARUS_Instance::DeleteSequence( CSequence *sequence )
{
m_sequences.remove( sequence );
delete sequence;
#ifdef _DEBUG
m_DEBUG_NumSequenceFreed++;
#endif
}
/*
-------------------------
AllocateSequences
-------------------------
*/
int ICARUS_Instance::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;
}
/*
-------------------------
SaveSequenceIDTable
-------------------------
*/
int ICARUS_Instance::SaveSequenceIDTable( void )
{
//Save out the number of sequences to follow
int numSequences = m_sequences.size();
m_interface->I_WriteSaveData( '#SEQ', &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();
}
m_interface->I_WriteSaveData( 'SQTB', idTable, sizeof( int ) * numSequences );
delete[] idTable;
return true;
}
/*
-------------------------
SaveSequences
-------------------------
*/
int ICARUS_Instance::SaveSequences( void )
{
//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;
}
/*
-------------------------
SaveSequencers
-------------------------
*/
int ICARUS_Instance::SaveSequencers( void )
{
//Save out the number of sequences to follow
int numSequencers = m_sequencers.size();
m_interface->I_WriteSaveData( '#SQR', &numSequencers, sizeof( numSequencers ) );
//The sequencers are then saved
sequencer_l::iterator si;
STL_ITERATE( si, m_sequencers )
{
(*si)->Save();
}
return true;
}
/*
-------------------------
SaveSignals
-------------------------
*/
int ICARUS_Instance::SaveSignals( void )
{
int numSignals = m_signals.size();
m_interface->I_WriteSaveData( 'ISIG', &numSignals, sizeof( numSignals ) );
signal_m::iterator si;
STL_ITERATE( si, m_signals )
{
//m_interface->I_WriteSaveData( 'ISIG', &numSignals, sizeof( numSignals ) );
const char *name = ((*si).first).c_str();
//Make sure this is a valid string
assert( ( name != NULL ) && ( name[0] != NULL ) );
int length = strlen( name ) + 1;
//Save out the string size
m_interface->I_WriteSaveData( 'SIG#', &length, sizeof ( length ) );
//Write out the string
m_interface->I_WriteSaveData( 'SIGN', (void *) name, length );
}
return true;
}
/*
-------------------------
Save
-------------------------
*/
int ICARUS_Instance::Save( void )
{
//Save out a ICARUS save block header with the ICARUS version
double version = ICARUS_VERSION;
m_interface->I_WriteSaveData( 'ICAR', &version, sizeof( version ) );
//Save out the signals
if ( SaveSignals() == false )
return false;
//Save out the sequences
if ( SaveSequences() == false )
return false;
//Save out the sequencers
if ( SaveSequencers() == false )
return false;
m_interface->I_WriteSaveData( 'IEND', &version, sizeof( version ) );
return true;
}
/*
-------------------------
LoadSignals
-------------------------
*/
int ICARUS_Instance::LoadSignals( void )
{
int numSignals;
m_interface->I_ReadSaveData( 'ISIG', &numSignals, sizeof( numSignals ) );
for ( int i = 0; i < numSignals; i++ )
{
char buffer[1024];
int length;
//Get the size of the string
m_interface->I_ReadSaveData( 'SIG#', &length, sizeof( length ) );
assert( length < sizeof( buffer ) );
//Get the string
m_interface->I_ReadSaveData( 'SIGN', &buffer, length );
//Turn it on and add it to the system
Signal( (const char *) &buffer );
}
return true;
}
/*
-------------------------
LoadSequence
-------------------------
*/
int ICARUS_Instance::LoadSequence( void )
{
CSequence *sequence = GetSequence();
//Load the sequence back in
sequence->Load();
//If this sequence had a higher GUID than the current, save it
if ( sequence->GetID() > m_GUID )
m_GUID = sequence->GetID();
return true;
}
/*
-------------------------
LoadSequence
-------------------------
*/
int ICARUS_Instance::LoadSequences( void )
{
CSequence *sequence;
int numSequences;
//Get the number of sequences to read in
m_interface->I_ReadSaveData( '#SEQ', &numSequences, sizeof( numSequences ) );
int *idTable = new int[ numSequences ];
if ( idTable == NULL )
return false;
//Load the sequencer ID table
m_interface->I_ReadSaveData( 'SQTB', 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() ) == false )
return false;
}
//Free the idTable
delete[] idTable;
return true;
}
/*
-------------------------
LoadSequencers
-------------------------
*/
int ICARUS_Instance::LoadSequencers( void )
{
CSequencer *sequencer;
int numSequencers;
//Get the number of sequencers to load
m_interface->I_ReadSaveData( '#SQR', &numSequencers, sizeof( &numSequencers ) );
//Load all sequencers
for ( int i = 0; i < numSequencers; i++ )
{
//NOTENOTE: The ownerID will be replaced in the loading process
if ( ( sequencer = GetSequencer( -1 ) ) == NULL )
return false;
if ( sequencer->Load() == false )
return false;
}
return true;
}
/*
-------------------------
Load
-------------------------
*/
int ICARUS_Instance::Load( void )
{
//Clear out any old information
Free();
//Check to make sure we're at the ICARUS save block
double version;
m_interface->I_ReadSaveData( 'ICAR', &version, sizeof( version ) );
//Versions must match!
if ( version != ICARUS_VERSION )
{
m_interface->I_DPrintf( WL_ERROR, "save game data contains outdated ICARUS version information!\n");
return false;
}
//Load all signals
if ( LoadSignals() == false )
{
m_interface->I_DPrintf( WL_ERROR, "failed to load signals from save game!\n");
return false;
}
//Load in all sequences
if ( LoadSequences() == false )
{
m_interface->I_DPrintf( WL_ERROR, "failed to load sequences from save game!\n");
return false;
}
//Load in all sequencers
if ( LoadSequencers() == false )
{
m_interface->I_DPrintf( WL_ERROR, "failed to load sequencers from save game!\n");
return false;
}
m_interface->I_ReadSaveData( 'IEND', &version, sizeof( version ) );
return true;
}
/*
-------------------------
Signal
-------------------------
*/
void ICARUS_Instance::Signal( const char *identifier )
{
m_signals[ identifier ] = 1;
}
/*
-------------------------
CheckSignal
-------------------------
*/
bool ICARUS_Instance::CheckSignal( const char *identifier )
{
signal_m::iterator smi;
smi = m_signals.find( identifier );
if ( smi == m_signals.end() )
return false;
return true;
}
/*
-------------------------
ClearSignal
-------------------------
*/
void ICARUS_Instance::ClearSignal( const char *identifier )
{
m_signals.erase( identifier );
}

81
codemp/icarus/instance.h Normal file
View File

@@ -0,0 +1,81 @@
// ICARUS Intance header
#ifndef __INSTANCE__
#define __INSTANCE__
#include "blockstream.h"
#include "interface.h"
#include "taskmanager.h"
#include "sequence.h"
#include "sequencer.h"
class ICARUS_Instance
{
public:
typedef list< CSequence * > sequence_l;
typedef list< CSequencer * > sequencer_l;
typedef map < string, unsigned char > signal_m;
ICARUS_Instance( void );
~ICARUS_Instance( void );
static ICARUS_Instance *Create( interface_export_t * );
int Delete( void );
CSequencer *GetSequencer( int );
void DeleteSequencer( CSequencer * );
CSequence *GetSequence( void );
CSequence *GetSequence( int id );
void DeleteSequence( CSequence * );
interface_export_t *GetInterface( void ) const { return m_interface; }
//These are overriddable for "worst-case" save / loads
virtual int Save( void /*FIXME*/ );
virtual int Load( void /*FIXME*/ );
void Signal( const char *identifier );
bool CheckSignal( const char *identifier );
void ClearSignal( const char *identifier );
protected:
virtual int SaveSignals( void );
virtual int SaveSequences( void );
virtual int SaveSequenceIDTable( void );
virtual int SaveSequencers( void );
int AllocateSequences( int numSequences, int *idTable );
virtual int LoadSignals( void );
virtual int LoadSequencers( void );
virtual int LoadSequences( void );
virtual int LoadSequence( void );
int Free( void );
interface_export_t *m_interface;
int m_GUID;
sequence_l m_sequences;
sequencer_l m_sequencers;
signal_m m_signals;
#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
};
#endif //__INSTANCE__

View File

@@ -0,0 +1,24 @@
//Anything above this #include will be ignored by the compiler
#include "../qcommon/exe_headers.h"
// ICARUS Engine Interface File
//
// This file is the only section of the ICARUS systems that
// is not directly portable from engine to engine.
//
// -- jweier
#include "../game/g_public.h"
#include "interface.h"
/*
void Interface_Init( interface_export_t *pe )
{
//TODO: This is where you link up all your functions to the engine
//Example:
//
// pe->I_GetEntityByName = ENGINE_GetEntityByName;
}
*/

72
codemp/icarus/interface.h Normal file
View File

@@ -0,0 +1,72 @@
// ICARUS Interface header file
#ifndef __INTERFACE__
#define __INTERFACE__
//#include "../server/server.h"
//#include "../game/g_public.h"
typedef unsigned long DWORD;
typedef float vec_t;
typedef vec_t vec3_t[3];
class CSequencer;
class CTaskManager;
typedef struct interface_export_s
{
//General
int (*I_LoadFile)( const char *name, void **buf );
void (*I_CenterPrint)( const char *format, ... );
void (*I_DPrintf)( int, const char *, ... );
sharedEntity_t *(*I_GetEntityByName)( const char *name ); //Polls the engine for the sequencer of the entity matching the name passed
DWORD (*I_GetTime)( void ); //Gets the current time
DWORD (*I_GetTimeScale)(void );
int (*I_PlaySound)( int taskID, int entID, const char *name, const char *channel );
void (*I_Lerp2Pos)( int taskID, int entID, vec3_t origin, vec3_t angles, float duration );
void (*I_Lerp2Origin)( int taskID, int entID, vec3_t origin, float duration );
void (*I_Lerp2Angles)( int taskID, int entID, vec3_t angles, float duration );
int (*I_GetTag)( int entID, const char *name, int lookup, vec3_t info );
void (*I_Lerp2Start)( int taskID, int entID, float duration );
void (*I_Lerp2End)( int taskID, int entID, float duration );
void (*I_Set)( int taskID, int entID, const char *type_name, const char *data );
void (*I_Use)( int entID, const char *name );
void (*I_Kill)( int entID, const char *name );
void (*I_Remove)( int entID, const char *name );
float (*I_Random)( float min, float max );
void (*I_Play)( int taskID, int entID, const char *type, const char *name );
//Camera functions
void (*I_CameraPan)( vec3_t angles, vec3_t dir, float duration );
void (*I_CameraMove)( vec3_t origin, float duration );
void (*I_CameraZoom)( float fov, float duration );
void (*I_CameraRoll)( float angle, float duration );
void (*I_CameraFollow)( const char *name, float speed, float initLerp );
void (*I_CameraTrack)( const char *name, float speed, float initLerp );
void (*I_CameraDistance)( float dist, float initLerp );
void (*I_CameraFade)( float sr, float sg, float sb, float sa, float dr, float dg, float db, float da, float duration );
void (*I_CameraPath)( const char *name );
void (*I_CameraEnable)( void );
void (*I_CameraDisable)( void );
void (*I_CameraShake)( float intensity, int duration );
int (*I_GetFloat)( int entID, int type, const char *name, float *value );
int (*I_GetVector)( int entID, int type, const char *name, vec3_t value );
int (*I_GetString)( int entID, int type, const char *name, char **value );
int (*I_Evaluate)( int p1Type, const char *p1, int p2Type, const char *p2, int operatorType );
void (*I_DeclareVariable)( int type, const char *name );
void (*I_FreeVariable)( const char *name );
//Save / Load functions
int (*I_WriteSaveData)( unsigned long chid, void *data, int length );
// Below changed by BTO (VV). Visual C++ 7.1 compiler no longer allows default args on function pointers. Ack.
int (*I_ReadSaveData)( unsigned long chid, void *address, int length /* , void **addressptr = NULL */ );
int (*I_LinkEntity)( int entID, CSequencer *sequencer, CTaskManager *taskManager );
} interface_export_t;
#endif //__INTERFACE__

File diff suppressed because it is too large Load Diff

224
codemp/icarus/interpreter.h Normal file
View File

@@ -0,0 +1,224 @@
// Interpreter.h
#ifndef __INTERPRETER__
#define __INTERPRETER__
#define ICARUS_VERSION 1.33
#define MAX_STRING_SIZE 256
#define MAX_VAR_NAME 64
typedef float vector_t[3];
//If you modify this, you MUST modify in g_ICARUScb.c as well.
//Token defines
enum
{
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
};
enum
{
MSG_COMPLETED,
MSG_EOF,
NUM_MESSAGES,
};
#ifdef __cplusplus
typedef struct variable_s
{
char name[MAX_VAR_NAME];
int type;
void *data;
} variable_t;
typedef map< string, variable_t * > variable_m;
typedef vector < variable_t * > variable_v;
//CInterpreter
class CInterpreter
{
public:
CInterpreter();
~CInterpreter();
int Interpret( CTokenizer *, CBlockStream *, char *filename=NULL ); //Main interpretation function
int Match( int ); //Looks ahead to the next token to try and match it to the passed token, consumes token on success
int LookAhead( int ); //Looks ahead without consuming on success
int FindSymbol( const char *, keywordArray_t * ); //Searches the symbol table for the given name. Returns the ID if found
int GetAffect( void ); //Handles the affect() function
int GetWait( void ); //Handles the wait() function
int GetSet( void ); //Handles the set() function
int GetBroadcast( void ); //Handles the broadcast() function
int GetLoop( void ); //Handles the loop() function
int GetPrint( void ); //Handles the print() function
int GetUse( void ); //Handles the use() function
int GetFlush( void ); //Handles the flush() function
int GetRun( void ); //Handles the run() function
int GetKill( void ); //Handles the kill() function
int GetRemove( void ); //Handles the remove() function
int GetCamera( void ); //Handles the camera() function
int GetIf( void ); //Handles the if() conditional statement
int GetSound( void ); //Handles the sound() function
int GetMove( void ); //Handles the move() function
int GetRotate( void ); //Handles the rotate() function
int GetRem( void ); //Handles the rem() function
int GetTask( void );
int GetDo( void );
int GetElse( void );
int GetDeclare( void );
int GetFree( void );
int GetDoWait( void );
int GetSignal( void );
int GetWaitSignal( void );
int GetPlay( void );
int GetRandom( CBlock *block );
int GetGet( CBlock *block ); //Heh
int GetTag( CBlock *block ); //Handles the tag() identifier
int GetVector( CBlock *block );
int GetNextType( void );
int GetType( char *get );
int GetAny( CBlock *block );
int GetEvaluator( CBlock *block );
int GetString( CBlock *); //Attempts to match and retrieve the value of a string token
int GetIdentifier( CBlock *get ); //Attempts to match and retrieve the value of an identifier token
int GetInteger( CBlock * ); //Attempts to match and retrieve the value of a int token
int GetFloat( CBlock * ); //Attempts to match and retrieve the value of a float token
int GetVariable( int type );
int GetID ( char * ); //Attempts to match and interpret an identifier
keywordArray_t *GetSymbols( void ) { return (keywordArray_t *) &m_symbolKeywords; } //Returns the interpreter's symbol table
keywordArray_t *GetIDs( void ) { return (keywordArray_t *) &m_IDKeywords; } //Returns the interpreter's ID table
keywordArray_t *GetTypes( void ) { return (keywordArray_t *) &m_typeKeywords; } //Returns the interpreter's type table
protected:
void InitVars( void );
void FreeVars( void );
variable_t *AddVar( const char *name, int type );
variable_t *FindVar( const char *name );
const char *GetTokenName( int ); //Returns the name of a token
int Error( char *, ... ); //Prints an error message
int MatchTag( void ); //Attempts to match to a tag identifier
int MatchGet( void ); //Attempts to match to a get identifier
int MatchRandom( void ); //Attempts to match to a random identifier
CTokenizer *m_tokenizer; //Pointer to the tokenizer
CBlockStream *m_blockStream; //Pointer to the block stream
variable_v m_vars;
variable_m m_varMap;
string m_sCurrentLine; // used in IBIze error reporting for more clarity
string m_sCurrentFile; // full-pathed name of .TXT file (needed because of above, which affects parsestreams)
int m_iCurrentLine; // also needed now because of 'm_sCurrentLine'
int m_iBadCBlockNumber; // used for final app return code (NZ = err)
static keywordArray_t m_symbolKeywords[]; //Symbols
static keywordArray_t m_IDKeywords[]; //Identifiers
static keywordArray_t m_typeKeywords[]; //Types
static keywordArray_t m_conditionalKeywords[]; //Conditional
};
#endif __cplusplus
#endif //__INTERPRETER__

20
codemp/icarus/memory.cpp Normal file
View File

@@ -0,0 +1,20 @@
//Anything above this #include will be ignored by the compiler
#include "../qcommon/exe_headers.h"
#include "icarus.h"
// leave these two as standard mallocs for the moment, there's something weird happening in ICARUS...
//
void *ICARUS_Malloc(int iSize)
{
//return gi.Malloc(iSize, TAG_ICARUS);
//return malloc(iSize);
return Z_Malloc(iSize, TAG_ICARUS5, qfalse);
}
void ICARUS_Free(void *pMem)
{
//gi.Free(pMem);
//free(pMem);
Z_Free(pMem);
}

1
codemp/icarus/module.h Normal file
View File

@@ -0,0 +1 @@
//This needs to be present to make the tokenizer happy...

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,297 @@
#ifndef __Q3_INTERFACE__
#define __Q3_INTERFACE__
//NOTENOTE: The enums and tables in this file will obviously bitch if they are included multiple times, don't do that
typedef enum //# setType_e
{
//# #sep Parm strings
SET_PARM1 = 0,//## %s="" # Set entity parm1
SET_PARM2,//## %s="" # Set entity parm2
SET_PARM3,//## %s="" # Set entity parm3
SET_PARM4,//## %s="" # Set entity parm4
SET_PARM5,//## %s="" # Set entity parm5
SET_PARM6,//## %s="" # Set entity parm6
SET_PARM7,//## %s="" # Set entity parm7
SET_PARM8,//## %s="" # Set entity parm8
SET_PARM9,//## %s="" # Set entity parm9
SET_PARM10,//## %s="" # Set entity parm10
SET_PARM11,//## %s="" # Set entity parm11
SET_PARM12,//## %s="" # Set entity parm12
SET_PARM13,//## %s="" # Set entity parm13
SET_PARM14,//## %s="" # Set entity parm14
SET_PARM15,//## %s="" # Set entity parm15
SET_PARM16,//## %s="" # Set entity parm16
// NOTE!!! If you add any other SET_xxxxxxSCRIPT types, make sure you update the 'case' statements in
// ICARUS_InterrogateScript() (game/g_ICARUS.cpp), or the script-precacher won't find them.
//# #sep Scripts and other file paths
SET_SPAWNSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when spawned //0 - do not change these, these are equal to BSET_SPAWN, etc
SET_USESCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when used
SET_AWAKESCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when startled
SET_ANGERSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script run when find an enemy for the first time
SET_ATTACKSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when you shoot
SET_VICTORYSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when killed someone
SET_LOSTENEMYSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when you can't find your enemy
SET_PAINSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when hit
SET_FLEESCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when hit and low health
SET_DEATHSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when killed
SET_DELAYEDSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run after a delay
SET_BLOCKEDSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when blocked by teammate
SET_FFIRESCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when player has shot own team repeatedly
SET_FFDEATHSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when player kills a teammate
SET_MINDTRICKSCRIPT,//## %s="NULL" !!"W:\game\base\scripts\!!#*.txt" # Script to run when player kills a teammate
SET_VIDEO_PLAY,//## %s="filename" !!"W:\game\base\video\!!#*.roq" # Play a video (inGame)
SET_CINEMATIC_SKIPSCRIPT, //## %s="filename" !!"W:\game\base\scripts\!!#*.txt" # Script to run when skipping the running cinematic
//# #sep Standard strings
SET_ENEMY,//## %s="NULL" # Set enemy by targetname
SET_LEADER,//## %s="NULL" # Set for BS_FOLLOW_LEADER
SET_NAVGOAL,//## %s="NULL" # *Move to this navgoal then continue script
SET_CAPTURE,//## %s="NULL" # Set captureGoal by targetname
SET_VIEWTARGET,//## %s="NULL" # Set angles toward ent by targetname
SET_WATCHTARGET,//## %s="NULL" # Set angles toward ent by targetname, will *continue* to face them... only in BS_CINEMATIC
SET_TARGETNAME,//## %s="NULL" # Set/change your targetname
SET_PAINTARGET,//## %s="NULL" # Set/change what to use when hit
SET_CAMERA_GROUP,//## %s="NULL" # all ents with this cameraGroup will be focused on
SET_CAMERA_GROUP_TAG,//## %s="NULL" # What tag on all clients to try to track
SET_LOOK_TARGET,//## %s="NULL" # object for NPC to look at
SET_ADDRHANDBOLT_MODEL, //## %s="NULL" # object to place on NPC right hand bolt
SET_REMOVERHANDBOLT_MODEL, //## %s="NULL" # object to remove from NPC right hand bolt
SET_ADDLHANDBOLT_MODEL, //## %s="NULL" # object to place on NPC left hand bolt
SET_REMOVELHANDBOLT_MODEL, //## %s="NULL" # object to remove from NPC left hand bolt
SET_CAPTIONTEXTCOLOR, //## %s="" # Color of text RED,WHITE,BLUE, YELLOW
SET_CENTERTEXTCOLOR, //## %s="" # Color of text RED,WHITE,BLUE, YELLOW
SET_SCROLLTEXTCOLOR, //## %s="" # Color of text RED,WHITE,BLUE, YELLOW
SET_COPY_ORIGIN,//## %s="targetname" # Copy the origin of the ent with targetname to your origin
SET_DEFEND_TARGET,//## %s="targetname" # This NPC will attack the target NPC's enemies
SET_TARGET,//## %s="NULL" # Set/change your target
SET_TARGET2,//## %s="NULL" # Set/change your target2, on NPC's, this fires when they're knocked out by the red hypo
SET_LOCATION,//## %s="INVALID" # What trigger_location you're in - Can only be gotten, not set!
SET_REMOVE_TARGET,//## %s="NULL" # Target that is fired when someone completes the BS_REMOVE behaviorState
SET_LOADGAME,//## %s="exitholodeck" # Load the savegame that was auto-saved when you started the holodeck
SET_LOCKYAW,//## %s="off" # Lock legs to a certain yaw angle (or "off" or "auto" uses current)
SET_FULLNAME,//## %s="NULL" # This name will appear when ent is scanned by tricorder
SET_VIEWENTITY,//## %s="NULL" # Make the player look through this ent's eyes - also shunts player movement control to this ent
SET_LOOPSOUND,//## %s="FILENAME" !!"W:\game\base\!!#sound\*.*" # Looping sound to play on entity
SET_ICARUS_FREEZE,//## %s="NULL" # Specify name of entity to freeze - !!!NOTE!!! since the ent is frozen, it cannot unfreeze itself, you must have some other entity unfreeze a frozen ent!!!
SET_ICARUS_UNFREEZE,//## %s="NULL" # Specify name of entity to unfreeze - !!!NOTE!!! since the ent is frozen, it cannot unfreeze itself, you must have some other entity unfreeze a frozen ent!!!
SET_SCROLLTEXT, //## %s="" # key of text string to print
SET_LCARSTEXT, //## %s="" # key of text string to print in LCARS frame
//# #sep vectors
SET_ORIGIN,//## %v="0.0 0.0 0.0" # Set origin explicitly or with TAG
SET_ANGLES,//## %v="0.0 0.0 0.0" # Set angles explicitly or with TAG
SET_TELEPORT_DEST,//## %v="0.0 0.0 0.0" # Set origin here as soon as the area is clear
//# #sep floats
SET_XVELOCITY,//## %f="0.0" # Velocity along X axis
SET_YVELOCITY,//## %f="0.0" # Velocity along Y axis
SET_ZVELOCITY,//## %f="0.0" # Velocity along Z axis
SET_Z_OFFSET,//## %f="0.0" # Vertical offset from original origin... offset/ent's speed * 1000ms is duration
SET_DPITCH,//## %f="0.0" # Pitch for NPC to turn to
SET_DYAW,//## %f="0.0" # Yaw for NPC to turn to
SET_TIMESCALE,//## %f="0.0" # Speed-up slow down game (0 - 1.0)
SET_CAMERA_GROUP_Z_OFS,//## %s="NULL" # when following an ent with the camera, apply this z ofs
SET_VISRANGE,//## %f="0.0" # How far away NPC can see
SET_EARSHOT,//## %f="0.0" # How far an NPC can hear
SET_VIGILANCE,//## %f="0.0" # How often to look for enemies (0 - 1.0)
SET_GRAVITY,//## %f="0.0" # Change this ent's gravity - 800 default
SET_FACEAUX, //## %f="0.0" # Set face to Aux expression for number of seconds
SET_FACEBLINK, //## %f="0.0" # Set face to Blink expression for number of seconds
SET_FACEBLINKFROWN, //## %f="0.0" # Set face to Blinkfrown expression for number of seconds
SET_FACEFROWN, //## %f="0.0" # Set face to Frown expression for number of seconds
SET_FACENORMAL, //## %f="0.0" # Set face to Normal expression for number of seconds
SET_FACEEYESCLOSED, //## %f="0.0" # Set face to Eyes closed
SET_FACEEYESOPENED, //## %f="0.0" # Set face to Eyes open
SET_WAIT, //## %f="0.0" # Change an entity's wait field
SET_FOLLOWDIST, //## %f="0.0" # How far away to stay from leader in BS_FOLLOW_LEADER
SET_SCALE, //## %f="0.0" # Scale the entity model
//# #sep ints
SET_ANIM_HOLDTIME_LOWER,//## %d="0" # Hold lower anim for number of milliseconds
SET_ANIM_HOLDTIME_UPPER,//## %d="0" # Hold upper anim for number of milliseconds
SET_ANIM_HOLDTIME_BOTH,//## %d="0" # Hold lower and upper anims for number of milliseconds
SET_HEALTH,//## %d="0" # Change health
SET_ARMOR,//## %d="0" # Change armor
SET_WALKSPEED,//## %d="0" # Change walkSpeed
SET_RUNSPEED,//## %d="0" # Change runSpeed
SET_YAWSPEED,//## %d="0" # Change yawSpeed
SET_AGGRESSION,//## %d="0" # Change aggression 1-5
SET_AIM,//## %d="0" # Change aim 1-5
SET_FRICTION,//## %d="0" # Change ent's friction - 6 default
SET_SHOOTDIST,//## %d="0" # How far the ent can shoot - 0 uses weapon
SET_HFOV,//## %d="0" # Horizontal field of view
SET_VFOV,//## %d="0" # Vertical field of view
SET_DELAYSCRIPTTIME,//## %d="0" # How many milliseconds to wait before running delayscript
SET_FORWARDMOVE,//## %d="0" # NPC move forward -127(back) to 127
SET_RIGHTMOVE,//## %d="0" # NPC move right -127(left) to 127
SET_STARTFRAME, //## %d="0" # frame to start animation sequence on
SET_ENDFRAME, //## %d="0" # frame to end animation sequence on
SET_ANIMFRAME, //## %d="0" # frame to set animation sequence to
SET_COUNT, //## %d="0" # Change an entity's count field
SET_SHOT_SPACING,//## %d="1000" # Time between shots for an NPC - reset to defaults when changes weapon
SET_MISSIONSTATUSTIME,//## %d="0" # Amount of time until Mission Status should be shown after death
SET_WIDTH,//## %d="0.0" # Width of NPC bounding box.
//# #sep booleans
SET_IGNOREPAIN,//## %t="BOOL_TYPES" # Do not react to pain
SET_IGNOREENEMIES,//## %t="BOOL_TYPES" # Do not acquire enemies
SET_IGNOREALERTS,//## %t="BOOL_TYPES" # Do not get enemy set by allies in area(ambush)
SET_DONTSHOOT,//## %t="BOOL_TYPES" # Others won't shoot you
SET_NOTARGET,//## %t="BOOL_TYPES" # Others won't pick you as enemy
SET_DONTFIRE,//## %t="BOOL_TYPES" # Don't fire your weapon
SET_LOCKED_ENEMY,//## %t="BOOL_TYPES" # Keep current enemy until dead
SET_CROUCHED,//## %t="BOOL_TYPES" # Force NPC to crouch
SET_WALKING,//## %t="BOOL_TYPES" # Force NPC to move at walkSpeed
SET_RUNNING,//## %t="BOOL_TYPES" # Force NPC to move at runSpeed
SET_CHASE_ENEMIES,//## %t="BOOL_TYPES" # NPC will chase after enemies
SET_LOOK_FOR_ENEMIES,//## %t="BOOL_TYPES" # NPC will be on the lookout for enemies
SET_FACE_MOVE_DIR,//## %t="BOOL_TYPES" # NPC will face in the direction it's moving
SET_DONT_FLEE,//## %t="BOOL_TYPES" # NPC will not run from danger
SET_FORCED_MARCH,//## %t="BOOL_TYPES" # NPC will not move unless you aim at him
SET_UNDYING,//## %t="BOOL_TYPES" # Can take damage down to 1 but not die
SET_NOAVOID,//## %t="BOOL_TYPES" # Will not avoid other NPCs or architecture
SET_SOLID,//## %t="BOOL_TYPES" # Make yourself notsolid or solid
SET_PLAYER_USABLE,//## %t="BOOL_TYPES" # Can be activateby the player's "use" button
SET_LOOP_ANIM,//## %t="BOOL_TYPES" # For non-NPCs, loop your animation sequence
SET_INTERFACE,//## %t="BOOL_TYPES" # Player interface on/off
SET_SHIELDS,//## %t="BOOL_TYPES" # NPC has no shields (Borg do not adapt)
SET_INVISIBLE,//## %t="BOOL_TYPES" # Makes an NPC not solid and not visible
SET_VAMPIRE,//## %t="BOOL_TYPES" # Draws only in mirrors/portals
SET_FORCE_INVINCIBLE,//## %t="BOOL_TYPES" # Force Invincibility effect, also godmode
SET_GREET_ALLIES,//## %t="BOOL_TYPES" # Makes an NPC greet teammates
SET_VIDEO_FADE_IN,//## %t="BOOL_TYPES" # Makes video playback fade in
SET_VIDEO_FADE_OUT,//## %t="BOOL_TYPES" # Makes video playback fade out
SET_PLAYER_LOCKED,//## %t="BOOL_TYPES" # Makes it so player cannot move
SET_LOCK_PLAYER_WEAPONS,//## %t="BOOL_TYPES" # Makes it so player cannot switch weapons
SET_NO_IMPACT_DAMAGE,//## %t="BOOL_TYPES" # Stops this ent from taking impact damage
SET_NO_KNOCKBACK,//## %t="BOOL_TYPES" # Stops this ent from taking knockback from weapons
SET_ALT_FIRE,//## %t="BOOL_TYPES" # Force NPC to use altfire when shooting
SET_NO_RESPONSE,//## %t="BOOL_TYPES" # NPCs will do generic responses when this is on (usescripts override generic responses as well)
SET_INVINCIBLE,//## %t="BOOL_TYPES" # Completely unkillable
SET_MISSIONSTATUSACTIVE, //# Turns on Mission Status Screen
SET_NO_COMBAT_TALK,//## %t="BOOL_TYPES" # NPCs will not do their combat talking noises when this is on
SET_NO_ALERT_TALK,//## %t="BOOL_TYPES" # NPCs will not do their combat talking noises when this is on
SET_TREASONED,//## %t="BOOL_TYPES" # Player has turned on his own- scripts will stop, NPCs will turn on him and level changes load the brig
SET_DISABLE_SHADER_ANIM,//## %t="BOOL_TYPES" # Allows turning off an animating shader in a script
SET_SHADER_ANIM,//## %t="BOOL_TYPES" # Sets a shader with an image map to be under frame control
SET_SABERACTIVE,//## %t="BOOL_TYPES" # Turns saber on/off
SET_ADJUST_AREA_PORTALS,//## %t="BOOL_TYPES" # Only set this on things you move with script commands that you *want* to open/close area portals. Default is off.
SET_DMG_BY_HEAVY_WEAP_ONLY,//## %t="BOOL_TYPES" # When true, only a heavy weapon class missile/laser can damage this ent.
SET_SHIELDED,//## %t="BOOL_TYPES" # When true, ion_cannon is shielded from any kind of damage.
SET_NO_GROUPS,//## %t="BOOL_TYPES" # This NPC cannot alert groups or be part of a group
SET_FIRE_WEAPON,//## %t="BOOL_TYPES" # Makes NPC will hold down the fire button, until this is set to false
SET_NO_MINDTRICK,//## %t="BOOL_TYPES" # Makes NPC immune to jedi mind-trick
SET_INACTIVE,//## %t="BOOL_TYPES" # in lieu of using a target_activate or target_deactivate
SET_FUNC_USABLE_VISIBLE,//## %t="BOOL_TYPES" # provides an alternate way of changing func_usable to be visible or not, DOES NOT AFFECT SOLID
SET_SECRET_AREA_FOUND,//## %t="BOOL_TYPES" # Increment secret areas found counter
SET_MISSION_STATUS_SCREEN,//## %t="BOOL_TYPES" # Display Mission Status screen before advancing to next level
SET_END_SCREENDISSOLVE,//## %t="BOOL_TYPES" # End of game dissolve into star background and credits
SET_USE_CP_NEAREST,//## %t="BOOL_TYPES" # NPCs will use their closest combat points, not try and find ones next to the player, or flank player
SET_MORELIGHT,//## %t="BOOL_TYPES" # NPC will have a minlight of 96
SET_NO_FORCE,//## %t="BOOL_TYPES" # NPC will not be affected by force powers
SET_NO_FALLTODEATH,//## %t="BOOL_TYPES" # NPC will not scream and tumble and fall to hit death over large drops
SET_DISMEMBERABLE,//## %t="BOOL_TYPES" # NPC will not be dismemberable if you set this to false (default is true)
SET_NO_ACROBATICS,//## %t="BOOL_TYPES" # Jedi won't jump, roll or cartwheel
SET_USE_SUBTITLES,//## %t="BOOL_TYPES" # When true NPC will always display subtitle regardless of subtitle setting
SET_CLEAN_DAMAGING_ENTS,//## %t="BOOL_TYPES" # Removes entities that could muck up cinematics, explosives, turrets, seekers.
SET_HUD,//## %t="BOOL_TYPES" # Turns on/off HUD
//# #sep calls
SET_SKILL,//## %r%d="0" # Cannot set this, only get it - valid values are 0 through 3
//# #sep Special tables
SET_ANIM_UPPER,//## %t="ANIM_NAMES" # Torso and head anim
SET_ANIM_LOWER,//## %t="ANIM_NAMES" # Legs anim
SET_ANIM_BOTH,//## %t="ANIM_NAMES" # Set same anim on torso and legs
SET_PLAYER_TEAM,//## %t="TEAM_NAMES" # Your team
SET_ENEMY_TEAM,//## %t="TEAM_NAMES" # Team in which to look for enemies
SET_BEHAVIOR_STATE,//## %t="BSTATE_STRINGS" # Change current bState
SET_DEFAULT_BSTATE,//## %t="BSTATE_STRINGS" # Change fallback bState
SET_TEMP_BSTATE,//## %t="BSTATE_STRINGS" # Set/Chang a temp bState
SET_EVENT,//## %t="EVENT_NAMES" # Events you can initiate
SET_WEAPON,//## %t="WEAPON_NAMES" # Change/Stow/Drop weapon
SET_ITEM,//## %t="ITEM_NAMES" # Give items
SET_MUSIC_STATE,//## %t="MUSIC_STATES" # Set the state of the dynamic music
SET_FORCE_HEAL_LEVEL,//## %t="FORCE_LEVELS" # Change force power level
SET_FORCE_JUMP_LEVEL,//## %t="FORCE_LEVELS" # Change force power level
SET_FORCE_SPEED_LEVEL,//## %t="FORCE_LEVELS" # Change force power level
SET_FORCE_PUSH_LEVEL,//## %t="FORCE_LEVELS" # Change force power level
SET_FORCE_PULL_LEVEL,//## %t="FORCE_LEVELS" # Change force power level
SET_FORCE_MINDTRICK_LEVEL,//## %t="FORCE_LEVELS" # Change force power level
SET_FORCE_GRIP_LEVEL,//## %t="FORCE_LEVELS" # Change force power level
SET_FORCE_LIGHTNING_LEVEL,//## %t="FORCE_LEVELS" # Change force power level
SET_SABER_THROW,//## %t="FORCE_LEVELS" # Change force power level
SET_SABER_DEFENSE,//## %t="FORCE_LEVELS" # Change force power level
SET_SABER_OFFENSE,//## %t="FORCE_LEVELS" # Change force power level
SET_OBJECTIVE_SHOW, //## %t="OBJECTIVES" # Show objective on mission screen
SET_OBJECTIVE_HIDE, //## %t="OBJECTIVES" # Hide objective from mission screen
SET_OBJECTIVE_SUCCEEDED,//## %t="OBJECTIVES" # Mark objective as completed
SET_OBJECTIVE_FAILED, //## %t="OBJECTIVES" # Mark objective as failed
SET_MISSIONFAILED, //## %t="MISSIONFAILED" # Mission failed screen activates
SET_TACTICAL_SHOW, //## %t="TACTICAL" # Show tactical info on mission objectives screen
SET_TACTICAL_HIDE, //## %t="TACTICAL" # Hide tactical info on mission objectives screen
SET_OBJECTIVE_CLEARALL, //## # Force all objectives to be hidden
/*
SET_OBJECTIVEFOSTER,
*/
SET_MISSIONSTATUSTEXT, //## %t="STATUSTEXT" # Text to appear in mission status screen
SET_MENU_SCREEN,//## %t="MENUSCREENS" # Brings up specified menu screen
SET_CLOSINGCREDITS, //## # Show closing credits
//in-bhc tables
SET_LEAN,//## %t="LEAN_TYPES" # Lean left, right or stop leaning
//# #eol
SET_
} setType_t;
#ifdef __cplusplus
// this enum isn't used directly by the game, it's mainly for BehavEd to scan for...
//
typedef enum //# playType_e
{
//# #sep Types of file to play
PLAY_ROFF = 0,//## %s="filename" !!"W:\game\base\scripts\!!#*.rof" # Play a ROFF file
//# #eol
PLAY_NUMBEROF
} playType_t;
const int Q3_TIME_SCALE = 1; //MILLISECONDS
extern char cinematicSkipScript[1024];
//General
extern void Q3_TaskIDClear( int *taskID );
extern qboolean Q3_TaskIDPending( sharedEntity_t *ent, taskID_t taskType );
extern void Q3_TaskIDComplete( sharedEntity_t *ent, taskID_t taskType );
extern void Q3_DPrintf( const char *, ... );
extern void Q3_CameraRoll( float angle, float duration );
extern void Q3_CameraFollow( const char *name, float speed, float initLerp );
extern void Q3_CameraTrack( const char *name, float speed, float initLerp );
extern void Q3_CameraDistance( float distance, float initLerp );
//Not referenced directly as script function - all are called through Q3_Set
extern void Q3_SetAnimBoth( int entID, const char *anim_name );
extern void Q3_SetVelocity( int entID, vec3_t angles );
extern void Q3_DeclareVariable ( int type, const char *name );
extern void Q3_FreeVariable( const char *name );
extern void Q3_DebugPrint( int level, const char *format, ... );
#endif //__cplusplus
#endif //__Q3_INTERFACE__

View File

@@ -0,0 +1,429 @@
//Anything above this #include will be ignored by the compiler
#include "../qcommon/exe_headers.h"
#include "../game/g_public.h"
#include "Q3_Registers.h"
extern void Q3_DebugPrint( int level, const char *format, ... );
varString_m varStrings;
varFloat_m varFloats;
varString_m varVectors; //Work around for vector types
int numVariables = 0;
/*
-------------------------
Q3_VariableDeclared
-------------------------
*/
int Q3_VariableDeclared( const char *name )
{
//Check the strings
varString_m::iterator vsi = varStrings.find( name );
if ( vsi != varStrings.end() )
return VTYPE_STRING;
//Check the floats
varFloat_m::iterator vfi = varFloats.find( name );
if ( vfi != varFloats.end() )
return VTYPE_FLOAT;
//Check the vectors
varString_m::iterator vvi = varVectors.find( name );
if ( vvi != varVectors.end() )
return VTYPE_VECTOR;
return VTYPE_NONE;
}
/*
-------------------------
Q3_DeclareVariable
-------------------------
*/
void Q3_DeclareVariable( int type, const char *name )
{
//Cannot declare the same variable twice
if ( Q3_VariableDeclared( name ) != VTYPE_NONE )
return;
if ( numVariables > MAX_VARIABLES )
{
Q3_DebugPrint( WL_ERROR, "too many variables already declared, maximum is %d\n", MAX_VARIABLES );
return;
}
switch( type )
{
case TK_FLOAT:
varFloats[ name ] = 0.0f;
break;
case TK_STRING:
varStrings[ name ] = "NULL";
break;
case TK_VECTOR:
varVectors[ name ] = "0.0 0.0 0.0";
break;
default:
Q3_DebugPrint( WL_ERROR, "unknown 'type' for declare() function!\n" );
return;
break;
}
numVariables++;
}
/*
-------------------------
Q3_FreeVariable
-------------------------
*/
void Q3_FreeVariable( const char *name )
{
//Check the strings
varString_m::iterator vsi = varStrings.find( name );
if ( vsi != varStrings.end() )
{
varStrings.erase( vsi );
numVariables--;
return;
}
//Check the floats
varFloat_m::iterator vfi = varFloats.find( name );
if ( vfi != varFloats.end() )
{
varFloats.erase( vfi );
numVariables--;
return;
}
//Check the strings
varString_m::iterator vvi = varVectors.find( name );
if ( vvi != varVectors.end() )
{
varVectors.erase( vvi );
numVariables--;
return;
}
}
/*
-------------------------
Q3_GetFloatVariable
-------------------------
*/
int Q3_GetFloatVariable( const char *name, float *value )
{
//Check the floats
varFloat_m::iterator vfi = varFloats.find( name );
if ( vfi != varFloats.end() )
{
*value = (*vfi).second;
return true;
}
return false;
}
/*
-------------------------
Q3_GetStringVariable
-------------------------
*/
int Q3_GetStringVariable( const char *name, const char **value )
{
//Check the strings
varString_m::iterator vsi = varStrings.find( name );
if ( vsi != varStrings.end() )
{
*value = (const char *) ((*vsi).second).c_str();
return true;
}
return false;
}
/*
-------------------------
Q3_GetVectorVariable
-------------------------
*/
int Q3_GetVectorVariable( const char *name, vec3_t value )
{
//Check the strings
varString_m::iterator vvi = varVectors.find( name );
if ( vvi != varVectors.end() )
{
const char *str = ((*vvi).second).c_str();
sscanf( str, "%f %f %f", &value[0], &value[1], &value[2] );
return true;
}
return false;
}
/*
-------------------------
Q3_InitVariables
-------------------------
*/
void Q3_InitVariables( void )
{
varStrings.clear();
varFloats.clear();
varVectors.clear();
if ( numVariables > 0 )
Q3_DebugPrint( WL_WARNING, "%d residual variables found!\n", numVariables );
numVariables = 0;
}
/*
-------------------------
Q3_SetVariable_Float
-------------------------
*/
int Q3_SetFloatVariable( const char *name, float value )
{
//Check the floats
varFloat_m::iterator vfi = varFloats.find( name );
if ( vfi == varFloats.end() )
return VTYPE_FLOAT;
(*vfi).second = value;
return true;
}
/*
-------------------------
Q3_SetVariable_String
-------------------------
*/
int Q3_SetStringVariable( const char *name, const char *value )
{
//Check the strings
varString_m::iterator vsi = varStrings.find( name );
if ( vsi == varStrings.end() )
return false;
(*vsi).second = value;
return true;
}
/*
-------------------------
Q3_SetVariable_Vector
-------------------------
*/
int Q3_SetVectorVariable( const char *name, const char *value )
{
//Check the strings
varString_m::iterator vvi = varVectors.find( name );
if ( vvi == varVectors.end() )
return false;
(*vvi).second = value;
return true;
}
/*
-------------------------
Q3_VariableSaveFloats
-------------------------
*/
void Q3_VariableSaveFloats( varFloat_m &fmap )
{
return;
/*
int numFloats = fmap.size();
gi.AppendToSaveGame( 'FVAR', &numFloats, sizeof( numFloats ) );
varFloat_m::iterator vfi;
STL_ITERATE( vfi, fmap )
{
//Save out the map id
int idSize = strlen( ((*vfi).first).c_str() );
//Save out the real data
gi.AppendToSaveGame( 'FIDL', &idSize, sizeof( idSize ) );
gi.AppendToSaveGame( 'FIDS', (void *) ((*vfi).first).c_str(), idSize );
//Save out the float value
gi.AppendToSaveGame( 'FVAL', &((*vfi).second), sizeof( float ) );
}
*/
}
/*
-------------------------
Q3_VariableSaveStrings
-------------------------
*/
void Q3_VariableSaveStrings( varString_m &smap )
{
return;
/*
int numStrings = smap.size();
gi.AppendToSaveGame( 'SVAR', &numStrings, sizeof( numStrings ) );
varString_m::iterator vsi;
STL_ITERATE( vsi, smap )
{
//Save out the map id
int idSize = strlen( ((*vsi).first).c_str() );
//Save out the real data
gi.AppendToSaveGame( 'SIDL', &idSize, sizeof( idSize ) );
gi.AppendToSaveGame( 'SIDS', (void *) ((*vsi).first).c_str(), idSize );
//Save out the string value
idSize = strlen( ((*vsi).second).c_str() );
gi.AppendToSaveGame( 'SVSZ', &idSize, sizeof( idSize ) );
gi.AppendToSaveGame( 'SVAL', (void *) ((*vsi).second).c_str(), idSize );
}
*/
}
/*
-------------------------
Q3_VariableSave
-------------------------
*/
int Q3_VariableSave( void )
{
Q3_VariableSaveFloats( varFloats );
Q3_VariableSaveStrings( varStrings );
Q3_VariableSaveStrings( varVectors);
return qtrue;
}
/*
-------------------------
Q3_VariableLoadFloats
-------------------------
*/
void Q3_VariableLoadFloats( varFloat_m &fmap )
{
return;
/*
int numFloats;
char tempBuffer[1024];
gi.ReadFromSaveGame( 'FVAR', &numFloats, sizeof( numFloats ) );
for ( int i = 0; i < numFloats; i++ )
{
int idSize;
gi.ReadFromSaveGame( 'FIDL', &idSize, sizeof( idSize ) );
gi.ReadFromSaveGame( 'FIDS', &tempBuffer, idSize );
tempBuffer[ idSize ] = 0;
float val;
gi.ReadFromSaveGame( 'FVAL', &val, sizeof( float ) );
Q3_DeclareVariable( TK_FLOAT, (const char *) &tempBuffer );
Q3_SetFloatVariable( (const char *) &tempBuffer, val );
}
*/
}
/*
-------------------------
Q3_VariableLoadStrings
-------------------------
*/
void Q3_VariableLoadStrings( int type, varString_m &fmap )
{
return;
/*
int numFloats;
char tempBuffer[1024];
char tempBuffer2[1024];
gi.ReadFromSaveGame( 'SVAR', &numFloats, sizeof( numFloats ) );
for ( int i = 0; i < numFloats; i++ )
{
int idSize;
gi.ReadFromSaveGame( 'SIDL', &idSize, sizeof( idSize ) );
gi.ReadFromSaveGame( 'SIDS', &tempBuffer, idSize );
tempBuffer[ idSize ] = 0;
gi.ReadFromSaveGame( 'SVSZ', &idSize, sizeof( idSize ) );
gi.ReadFromSaveGame( 'SVAL', &tempBuffer2, idSize );
tempBuffer2[ idSize ] = 0;
switch ( type )
{
case TK_STRING:
Q3_DeclareVariable( TK_STRING, (const char *) &tempBuffer );
Q3_SetStringVariable( (const char *) &tempBuffer, (const char *) &tempBuffer2 );
break;
case TK_VECTOR:
Q3_DeclareVariable( TK_VECTOR, (const char *) &tempBuffer );
Q3_SetVectorVariable( (const char *) &tempBuffer, (const char *) &tempBuffer2 );
break;
}
}
*/
}
/*
-------------------------
Q3_VariableLoad
-------------------------
*/
int Q3_VariableLoad( void )
{
Q3_InitVariables();
Q3_VariableLoadFloats( varFloats );
Q3_VariableLoadStrings( TK_STRING, varStrings );
Q3_VariableLoadStrings( TK_VECTOR, varVectors);
return qfalse;
}

View File

@@ -0,0 +1,36 @@
#ifndef __Q3_REGISTERS__
#define __Q3_REGISTERS__
enum
{
VTYPE_NONE = 0,
VTYPE_FLOAT,
VTYPE_STRING,
VTYPE_VECTOR,
};
#ifdef __cplusplus
#define MAX_VARIABLES 32
typedef map < string, string > varString_m;
typedef map < string, float > varFloat_m;
extern varString_m varStrings;
extern varFloat_m varFloats;
extern varString_m varVectors;
extern void Q3_InitVariables( void );
extern void Q3_DeclareVariable( int type, const char *name );
extern void Q3_FreeVariable( const char *name );
extern int Q3_GetStringVariable( const char *name, const char **value );
extern int Q3_GetFloatVariable( const char *name, float *value );
extern int Q3_GetVectorVariable( const char *name, vec3_t value );
extern int Q3_VariableDeclared( const char *name );
extern int Q3_SetFloatVariable( const char *name, float value );
extern int Q3_SetStringVariable( const char *name, const char *value );
extern int Q3_SetVectorVariable( const char *name, const char *value );
#endif //__cplusplus
#endif //__Q3_REGISTERS__

559
codemp/icarus/sequence.cpp Normal file
View File

@@ -0,0 +1,559 @@
//Anything above this #include will be ignored by the compiler
#include "../qcommon/exe_headers.h"
// Script Command Sequences
//
// -- jweier
// this include must remain at the top of every Icarus CPP file
#include "icarus.h"
#include <assert.h>
CSequence::CSequence( void )
{
m_numCommands = 0;
m_flags = 0;
m_iterations = 1;
m_parent = NULL;
m_return = NULL;
}
CSequence::~CSequence( void )
{
Delete();
}
/*
-------------------------
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( void )
{
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();
//Clear all held commands
for ( bi = m_commands.begin(); bi != m_commands.end(); bi++ )
{
delete (*bi); //Free() handled internally
}
m_commands.clear();
}
/*
-------------------------
AddChild
-------------------------
*/
void CSequence::AddChild( CSequence *child )
{
assert( child );
if ( child == NULL )
return;
m_children.insert( m_children.end(), child );
}
/*
-------------------------
RemoveChild
-------------------------
*/
void CSequence::RemoveChild( CSequence *child )
{
assert( child );
if ( child == NULL )
return;
//Remove the child
m_children.remove( child );
}
/*
-------------------------
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;
}
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 )
{
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;
}
/*
-------------------------
GetChild
-------------------------
*/
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 )
{
unsigned char flags;
int numMembers, bID, size;
CBlockMember *bm;
//Save out the block ID
bID = block->GetBlockID();
(m_owner->GetInterface())->I_WriteSaveData( 'BLID', &bID, sizeof ( bID ) );
//Save out the block's flags
flags = block->GetFlags();
(m_owner->GetInterface())->I_WriteSaveData( 'BFLG', &flags, sizeof ( flags ) );
//Save out the number of members to read
numMembers = block->GetNumMembers();
(m_owner->GetInterface())->I_WriteSaveData( 'BNUM', &numMembers, sizeof ( numMembers ) );
for ( int i = 0; i < numMembers; i++ )
{
bm = block->GetMember( i );
//Save the block id
bID = bm->GetID();
(m_owner->GetInterface())->I_WriteSaveData( 'BMID', &bID, sizeof ( bID ) );
//Save out the data size
size = bm->GetSize();
(m_owner->GetInterface())->I_WriteSaveData( 'BSIZ', &size, sizeof( size ) );
//Save out the raw data
(m_owner->GetInterface())->I_WriteSaveData( 'BMEM', bm->GetData(), size );
}
return true;
}
/*
-------------------------
Save
-------------------------
*/
int CSequence::Save( void )
{
#if 0 //piss off, stupid function
sequence_l::iterator ci;
block_l::iterator bi;
int id;
//Save the parent (by GUID)
id = ( m_parent != NULL ) ? m_parent->GetID() : -1;
(m_owner->GetInterface())->I_WriteSaveData( 'SPID', &id, sizeof( id ) );
//Save the return (by GUID)
id = ( m_return != NULL ) ? m_return->GetID() : -1;
(m_owner->GetInterface())->I_WriteSaveData( 'SRID', &id, sizeof( id ) );
//Save the number of children
// (m_owner->GetInterface())->I_WriteSaveData( 'SNCH', &m_numChildren, sizeof( m_numChildren ) );
//Save out the children (only by GUID)
STL_ITERATE( ci, m_children )
{
id = (*ci)->GetID();
(m_owner->GetInterface())->I_WriteSaveData( 'SCHD', &id, sizeof( id ) );
}
//Save flags
(m_owner->GetInterface())->I_WriteSaveData( 'SFLG', &m_flags, sizeof( m_flags ) );
//Save iterations
(m_owner->GetInterface())->I_WriteSaveData( 'SITR', &m_iterations, sizeof( m_iterations ) );
//Save the number of commands
(m_owner->GetInterface())->I_WriteSaveData( 'SNMC', &m_numCommands, sizeof( m_numCommands ) );
//Save the commands
STL_ITERATE( bi, m_commands )
{
SaveCommand( (*bi) );
}
return true;
#endif
return false;
}
/*
-------------------------
Load
-------------------------
*/
int CSequence::Load( void )
{
#if 0 //piss off, stupid function
unsigned char flags;
CSequence *sequence;
CBlock *block;
int id, numMembers;
int bID, bSize;
void *bData;
//Get the parent sequence
(m_owner->GetInterface())->I_ReadSaveData( 'SPID', &id, sizeof( id ) );
m_parent = ( id != -1 ) ? m_owner->GetSequence( id ) : NULL;
//Get the return sequence
(m_owner->GetInterface())->I_ReadSaveData( 'SRID', &id, sizeof( id ) );
m_return = ( id != -1 ) ? m_owner->GetSequence( id ) : NULL;
//Get the number of children
// (m_owner->GetInterface())->I_ReadSaveData( 'SNCH', &m_numChildren, sizeof( m_numChildren ) );
//Reload all children
for ( int i = 0; i < m_numChildren; i++ )
{
//Get the child sequence ID
(m_owner->GetInterface())->I_ReadSaveData( 'SCHD', &id, sizeof( id ) );
//Get the desired sequence
if ( ( sequence = m_owner->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
(m_owner->GetInterface())->I_ReadSaveData( 'SFLG', &m_flags, sizeof( m_flags ) );
//Get the number of iterations
(m_owner->GetInterface())->I_ReadSaveData( 'SITR', &m_iterations, sizeof( m_iterations ) );
int numCommands;
//Get the number of commands
(m_owner->GetInterface())->I_ReadSaveData( 'SNMC', &numCommands, sizeof( m_numCommands ) );
//Get all the commands
for ( i = 0; i < numCommands; i++ )
{
//Get the block ID and create a new container
(m_owner->GetInterface())->I_ReadSaveData( 'BLID', &id, sizeof( id ) );
block = new CBlock;
block->Create( id );
//Read the block's flags
(m_owner->GetInterface())->I_ReadSaveData( 'BFLG', &flags, sizeof( flags ) );
block->SetFlags( flags );
//Get the number of block members
(m_owner->GetInterface())->I_ReadSaveData( 'BNUM', &numMembers, sizeof( numMembers ) );
for ( int j = 0; j < numMembers; j++ )
{
//Get the member ID
(m_owner->GetInterface())->I_ReadSaveData( 'BMID', &bID, sizeof( bID ) );
//Get the member size
(m_owner->GetInterface())->I_ReadSaveData( 'BSIZ', &bSize, sizeof( bSize ) );
//Get the member's data
if ( ( bData = ICARUS_Malloc( bSize ) ) == NULL )
return false;
//Get the actual raw data
(m_owner->GetInterface())->I_ReadSaveData( 'BMEM', bData, bSize );
//Write out the correct type
switch ( bID )
{
case TK_INT:
{
assert(0);
int data = *(int *) bData;
block->Write( TK_FLOAT, (float) data );
}
break;
case TK_FLOAT:
block->Write( TK_FLOAT, *(float *) bData );
break;
case TK_STRING:
case TK_IDENTIFIER:
case TK_CHAR:
block->Write( TK_STRING, (char *) bData );
break;
case TK_VECTOR:
case TK_VECTOR_START:
block->Write( TK_VECTOR, *(vec3_t *) bData );
break;
case ID_TAG:
block->Write( ID_TAG, (float) ID_TAG );
break;
case ID_GET:
block->Write( ID_GET, (float) ID_GET );
break;
case ID_RANDOM:
block->Write( ID_RANDOM, *(float *) bData );//(float) ID_RANDOM );
break;
case TK_EQUALS:
case TK_GREATER_THAN:
case TK_LESS_THAN:
case TK_NOT:
block->Write( bID, 0 );
break;
default:
assert(0);
return false;
break;
}
//Get rid of the temp memory
ICARUS_Free( bData );
}
//Save the block
//STL_INSERT( m_commands, block );
PushCommand( block, PUSH_BACK );
}
return true;
#endif
return false;
}

98
codemp/icarus/sequence.h Normal file
View File

@@ -0,0 +1,98 @@
// Sequence Header File
#ifndef __SEQUENCE__
#define __SEQUENCE__
#include "blockstream.h"
#include "interface.h"
#include "taskmanager.h"
class ICARUS_Instance;
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( void );
//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 *GetChildByIndex( int id );
bool HasChild( CSequence *sequence );
void SetOwner( ICARUS_Instance *owner ) { m_owner = owner; }
int Save( void );
int Load( void );
inline void *operator new( size_t size )
{ // Allocate the memory.
return Z_Malloc( size, TAG_ICARUS3, qtrue );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{ // Free the Memory.
Z_Free( pRawData );
}
protected:
int SaveCommand( CBlock *block );
ICARUS_Instance *m_owner;
//Organization information
sequence_l m_children;
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__

2483
codemp/icarus/sequencer.cpp Normal file

File diff suppressed because it is too large Load Diff

189
codemp/icarus/sequencer.h Normal file
View File

@@ -0,0 +1,189 @@
// Sequencer Header File
#ifndef __SEQUENCER__
#define __SEQUENCER__
#include "blockstream.h"
#include "interface.h"
#include "taskmanager.h"
#include "sequence.h"
#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 <list>
#include <vector>
#include <map>
#include <algorithm>
#pragma warning (pop)
#pragma warning (disable:4503) // decorated name length xceeded, name was truncated
using namespace std;
//Defines
#define SQ_COMMON 0x00000000 //Common one-pass sequence
#define SQ_LOOP 0x00000001 //Looping sequence
#define SQ_RETAIN 0x00000002 //Inside a looping sequence list, retain the information
#define SQ_AFFECT 0x00000004 //Affect sequence
#define SQ_RUN 0x00000008 //A run block
#define SQ_PENDING 0x00000010 //Pending use, don't free when flushing the sequences
#define SQ_CONDITIONAL 0x00000020 //Conditional statement
#define SQ_TASK 0x00000040 //Task block
#define BF_ELSE 0x00000001 //Block has an else id //FIXME: This was a sloppy fix for a problem that arose from conditionals
#define S_FAILED(a) (a!=SEQ_OK)
//const int MAX_ERROR_LENGTH = 256;
//Typedefs
typedef struct bstream_s
{
CBlockStream *stream;
bstream_s *last;
} bstream_t;
//Enumerations
enum
{
SEQ_OK, //Command was successfully added
SEQ_FAILED, //An error occured while trying to insert the command
};
// Sequencer
class ICARUS_Instance;
/*
==================================================================================================
CSequencer
==================================================================================================
*/
class CSequencer
{
// typedef map < int, CSequence * > sequenceID_m;
typedef list < CSequence * > sequence_l;
typedef map < CTaskGroup *, CSequence * > taskSequence_m;
public:
CSequencer();
~CSequencer();
int Init( int ownerID, interface_export_t *ie, CTaskManager *taskManager, ICARUS_Instance *iCARUS );
static CSequencer *Create ( void );
int Free( void );
int Run( char *buffer, long size );
int Callback( CTaskManager *taskManager, CBlock *block, int returnCode );
ICARUS_Instance *GetOwner( void ) { return m_owner; }
void SetOwnerID( int owner ) { m_ownerID = owner;}
int GetOwnerID( void ) const { return m_ownerID; }
interface_export_t *GetInterface( void ) const { return m_ie; }
CTaskManager *GetTaskManager( void ) const { return m_taskManager; }
void SetTaskManager( CTaskManager *tm) { if ( tm ) m_taskManager = tm; }
int Save( void );
int Load( void );
// Overloaded new operator.
inline void *operator new( size_t size )
{ // Allocate the memory.
return Z_Malloc( size, TAG_ICARUS2, qtrue );
}
// Overloaded delete operator.
inline void operator delete( void *pRawData )
{ // Free the Memory.
Z_Free( pRawData );
}
// moved to public on 2/12/2 to allow calling during shutdown
int Recall( void );
protected:
int EvaluateConditional( CBlock *block );
int Route( CSequence *sequence, bstream_t *bstream );
int Flush( CSequence *owner );
void Interrupt( void );
bstream_t *AddStream( void );
void DeleteStream( bstream_t *bstream );
int AddAffect( bstream_t *bstream, int retain, int *id );
CSequence *AddSequence( void );
CSequence *AddSequence( CSequence *parent, CSequence *returnSeq, int flags );
CSequence *GetSequence( int id );
//NOTENOTE: This only removes references to the sequence, IT DOES NOT FREE THE ALLOCATED MEMORY!
int RemoveSequence( CSequence *sequence);
int DestroySequence( CSequence *sequence);
int PushCommand( CBlock *command, int flag );
CBlock *PopCommand( int flag );
inline CSequence *ReturnSequence( CSequence *sequence );
void CheckRun( CBlock ** );
void CheckLoop( CBlock ** );
void CheckAffect( CBlock ** );
void CheckIf( CBlock ** );
void CheckDo( CBlock ** );
void CheckFlush( CBlock ** );
void Prep( CBlock ** );
int Prime( CTaskManager *taskManager, CBlock *command );
void StripExtension( const char *in, char *out );
int ParseRun( CBlock *block );
int ParseLoop( CBlock *block, bstream_t *bstream );
int ParseAffect( CBlock *block, bstream_t *bstream );
int ParseIf( CBlock *block, bstream_t *bstream );
int ParseElse( CBlock *block, bstream_t *bstream );
int ParseTask( CBlock *block, bstream_t *bstream );
int Affect( int id, int type );
void AddTaskSequence( CSequence *sequence, CTaskGroup *group );
CSequence *GetTaskSequence( CTaskGroup *group );
//Member variables
ICARUS_Instance *m_owner;
int m_ownerID;
CTaskManager *m_taskManager;
interface_export_t *m_ie; //This is unique to the sequencer so that client side and server side sequencers could both
//operate under different interfaces (for client side scripting)
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;
};
#endif //__SEQUENCER__

File diff suppressed because it is too large Load Diff

191
codemp/icarus/taskmanager.h Normal file
View File

@@ -0,0 +1,191 @@
// Task Manager header file
#ifndef __TASK_MANAGER__
#define __TASK_MANAGER__
#include <map>
#include "sequencer.h"
class CSequencer;
#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; }
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; }
//protected:
taskCallback_m m_completedTasks;
CTaskGroup *m_parent;
int m_numCompleted;
int m_GUID;
};
// CTaskManager
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();
static CTaskManager *Create( void );
CBlock *GetCurrentTask( void );
int Init( CSequencer *owner );
int Free( void );
int Flush( void );
int SetCommand( CBlock *block, int type );
int Completed( int id );
int Update( void );
qboolean IsRunning( void );
CTaskGroup *AddTaskGroup( const char *name );
CTaskGroup *GetTaskGroup( const char *name );
CTaskGroup *GetTaskGroup( int id );
int MarkTask( int id, int operation );
CBlock *RecallTask( void );
void Save( void );
void Load( void );
protected:
int Go( void ); //Heartbeat function called once per game frame
int CallbackCommand( CTask *task, int returnCode );
inline bool Check( int targetID, CBlock *block, int memberNum );
int GetVector( int entID, CBlock *block, int &memberNum, vector_t &value );
int GetFloat( int entID, CBlock *block, int &memberNum, float &value );
int Get( int entID, CBlock *block, int &memberNum, char **value );
int PushTask( CTask *task, int flag );
CTask *PopTask( int flag );
// Task functions
int Rotate( CTask *task );
int Remove( CTask *task );
int Camera( CTask *task );
int Print( CTask *task );
int Sound( CTask *task );
int Move( CTask *task );
int Kill( CTask *task );
int Set( CTask *task );
int Use( CTask *task );
int DeclareVariable( CTask *task );
int FreeVariable( CTask *task );
int Signal( CTask *task );
int Play( CTask *task );
int Wait( CTask *task, bool &completed );
int WaitSignal( CTask *task, bool &completed );
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;
//CTask *m_waitTask; //Global pointer to the current task that is waiting for callback completion
};
#endif //__TASK_MANAGER__

2837
codemp/icarus/tokenizer.cpp Normal file

File diff suppressed because it is too large Load Diff

601
codemp/icarus/tokenizer.h Normal file
View File

@@ -0,0 +1,601 @@
// Tokenizer.h
//
#ifndef __TOKENIZER_H
#define __TOKENIZER_H
#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>
#pragma warning (pop)
#pragma warning (disable:4503) // decorated name length xceeded, name was truncated
using namespace std;
//#include <windows.h>
#include "../qcommon/platform.h"
typedef unsigned char byte;
typedef unsigned short word;
#define MAX_STRING_LENGTH 256
#define MAX_IDENTIFIER_LENGTH 128
#define TKF_IGNOREDIRECTIVES 0x00000001 // skip over lines starting with #
#define TKF_USES_EOL 0x00000002 // generate end of line tokens
#define TKF_NODIRECTIVES 0x00000004 // don't treat # in any special way
#define TKF_WANTUNDEFINED 0x00000008 // if token not found in symbols create undefined token
#define TKF_WIDEUNDEFINEDSYMBOLS 0x00000010 // when undefined token encountered, accumulate until space
#define TKF_RAWSYMBOLSONLY 0x00000020
#define TKF_NUMERICIDENTIFIERSTART 0x00000040
#define TKF_IGNOREKEYWORDS 0x00000080
#define TKF_NOCASEKEYWORDS 0x00000100
#define TKF_NOUNDERSCOREINIDENTIFIER 0x00000200
#define TKF_NODASHINIDENTIFIER 0x00000400
#define TKF_COMMENTTOKENS 0x00000800
enum
{
TKERR_NONE,
TKERR_UNKNOWN,
TKERR_BUFFERCREATE,
TKERR_UNRECOGNIZEDSYMBOL,
TKERR_DUPLICATESYMBOL,
TKERR_STRINGLENGTHEXCEEDED,
TKERR_IDENTIFIERLENGTHEXCEEDED,
TKERR_EXPECTED_INTEGER,
TKERR_EXPECTED_IDENTIFIER,
TKERR_EXPECTED_STRING,
TKERR_EXPECTED_CHAR,
TKERR_EXPECTED_FLOAT,
TKERR_UNEXPECTED_TOKEN,
TKERR_INVALID_DIRECTIVE,
TKERR_INCLUDE_FILE_NOTFOUND,
TKERR_UNMATCHED_DIRECTIVE,
TKERR_USERERROR,
};
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,
};
typedef struct
{
char* m_keyword;
int m_tokenvalue;
} keywordArray_t;
class lessstr
{
public:
bool operator()(LPCTSTR str1, LPCTSTR str2) const {return (strcmp(str1, str2) < 0);};
};
class CParseStream
{
public:
CParseStream();
~CParseStream();
static CParseStream* Create();
virtual void Delete();
virtual bool NextChar(byte& theByte);
virtual int GetCurLine();
virtual void GetCurFilename(char** theBuff);
virtual long GetRemainingSize();
CParseStream* GetNext();
void SetNext(CParseStream* next);
virtual bool IsThisDefinition(void* theDefinition);
protected:
virtual bool Init();
CParseStream* m_next;
};
class CToken
{
public:
CToken();
~CToken();
static CToken* Create();
virtual void Delete();
virtual int GetType();
CToken* GetNext();
void SetNext(CToken* theToken);
virtual int GetIntValue();
virtual LPCTSTR GetStringValue();
virtual float GetFloatValue();
protected:
virtual void Init();
char* m_string;
CToken* m_next;
};
class CCharToken : public CToken
{
public:
CCharToken();
~CCharToken();
static CCharToken* Create(byte theByte);
virtual void Delete();
virtual int GetType();
protected:
virtual void Init(byte theByte);
};
class CStringToken : public CToken
{
public:
CStringToken();
~CStringToken();
static CStringToken* Create(LPCTSTR theString);
virtual void Delete();
virtual int GetType();
protected:
virtual void Init(LPCTSTR theString);
};
class CIntToken : public CToken
{
public:
CIntToken();
~CIntToken();
static CIntToken* Create(long value);
virtual void Delete();
virtual int GetType();
virtual float GetFloatValue();
virtual int GetIntValue();
virtual LPCTSTR GetStringValue();
protected:
virtual void Init(long value);
long m_value;
};
class CFloatToken : public CToken
{
public:
CFloatToken();
~CFloatToken();
static CFloatToken* Create(float value);
virtual void Delete();
virtual int GetType();
virtual float GetFloatValue();
virtual LPCTSTR GetStringValue();
protected:
virtual void Init(float value);
float m_value;
};
class CIdentifierToken : public CToken
{
public:
CIdentifierToken();
~CIdentifierToken();
static CIdentifierToken* Create(LPCTSTR name);
virtual void Delete();
virtual int GetType();
protected:
virtual void Init(LPCTSTR name);
};
class CCommentToken : public CToken
{
public:
CCommentToken();
~CCommentToken();
static CCommentToken* Create(LPCTSTR name);
virtual void Delete();
virtual int GetType();
protected:
virtual void Init(LPCTSTR name);
};
class CUserToken : public CToken
{
public:
CUserToken();
~CUserToken();
static CUserToken* Create(int value, LPCTSTR string);
virtual void Delete();
virtual int GetType();
protected:
virtual void Init(int value, LPCTSTR string);
int m_value;
};
class CUndefinedToken : public CToken
{
public:
CUndefinedToken();
~CUndefinedToken();
static CUndefinedToken* Create(LPCTSTR string);
virtual void Delete();
virtual int GetType();
protected:
virtual void Init(LPCTSTR string);
};
class CSymbol
{
public:
CSymbol();
virtual ~CSymbol();
static CSymbol* Create(LPCTSTR symbolName);
virtual void Delete();
LPCTSTR GetName();
protected:
virtual void Init(LPCTSTR symbolName);
char* m_symbolName;
};
typedef map<LPCTSTR, CSymbol*, lessstr> symbolmap_t;
class CDirectiveSymbol : public CSymbol
{
public:
CDirectiveSymbol();
~CDirectiveSymbol();
static CDirectiveSymbol* Create(LPCTSTR symbolName);
virtual void Delete();
void SetValue(LPCTSTR value);
LPCTSTR GetValue();
protected:
virtual void Init(LPCTSTR symbolName);
char* m_value;
};
class CIntSymbol : public CSymbol
{
public:
CIntSymbol();
static CIntSymbol* Create(LPCTSTR symbolName, int value);
virtual void Delete();
int GetValue();
protected:
virtual void Init(LPCTSTR symbolName, int value);
int m_value;
};
class CSymbolTable
{
public:
CSymbolTable();
~CSymbolTable();
static CSymbolTable* Create();
void Delete();
bool AddSymbol(CSymbol* theSymbol);
CSymbol* FindSymbol(LPCTSTR symbolName);
CSymbol* ExtractSymbol(LPCTSTR symbolName);
void RemoveSymbol(LPCTSTR symbolName);
void DiscardSymbols();
protected:
void Init();
symbolmap_t m_symbols;
};
class CSymbolLookup
{
public:
CSymbolLookup();
~CSymbolLookup();
static CSymbolLookup* Create(byte theByte);
virtual void Delete();
CSymbolLookup* GetNext();
void SetNext(CSymbolLookup* next);
void SetParent(CSymbolLookup* parent);
CSymbolLookup* GetParent();
void SetValue(int value);
int GetValue();
byte GetByte();
protected:
void Init(byte theByte);
CSymbolLookup* m_child;
CSymbolLookup* m_sibling;
CSymbolLookup* m_parent;
int m_value;
byte m_byte;
};
class CTokenizerState
{
public:
CTokenizerState();
~CTokenizerState();
static CTokenizerState* Create(bool skip);
virtual void Delete();
CTokenizerState* GetNext();
void SetNext(CTokenizerState* next);
virtual bool ProcessElse();
bool Skipping();
protected:
void Init(bool skip);
bool m_skip;
bool m_elseHit;
CTokenizerState* m_next;
};
class CTokenizerHolderState : public CTokenizerState
{
public:
CTokenizerHolderState();
~CTokenizerHolderState();
static CTokenizerHolderState* Create();
virtual void Delete();
virtual bool ProcessElse();
protected:
void Init();
};
typedef void (*LPTokenizerErrorProc)(LPCTSTR errString);
#ifdef USES_MODULES
class CTokenizer : public CModule
#else
class CTokenizer
#endif
{
public:
CTokenizer();
~CTokenizer();
static CTokenizer* Create(UINT dwFlags = 0);
virtual void Delete();
virtual void Error(int theError);
virtual void Error(int theError, LPCTSTR errString);
virtual void Error(LPCTSTR errString, int theError = TKERR_UNKNOWN);
CToken* GetToken(UINT onFlags = 0, UINT offFlags = 0);
CToken* GetToken(keywordArray_t* keywords, UINT onFlags, UINT offFlags);
void PutBackToken(CToken* theToken, bool commented = false, LPCTSTR addedChars = NULL, bool bIgnoreThisTokenType = false);
bool RequireToken(int tokenType);
void ScanUntilToken(int tokenType);
void SkipToLineEnd();
CToken* GetToEndOfLine(int tokenType = TK_IDENTIFIER);
keywordArray_t* SetKeywords(keywordArray_t* theKeywords);
void SetSymbols(keywordArray_t* theSymbols);
void SetAdditionalErrors(keywordArray_t* theErrors);
void SetErrorProc(LPTokenizerErrorProc errorProc);
void AddParseStream(byte* data, long datasize);
bool AddParseFile(LPCTSTR filename);
COLORREF ParseRGB();
long GetRemainingSize();
UINT GetFlags();
void SetFlags(UINT flags);
void GetCurFilename(char** filename);
int GetCurLine();
LPCTSTR LookupToken(int tokenID, keywordArray_t* theTable = NULL);
protected:
void SetError(int theError, LPCTSTR errString);
virtual void Init(UINT dwFlags = 0);
CToken* FetchToken();
bool AddDefineSymbol(CDirectiveSymbol* definesymbol);
bool NextChar(byte& theByte);
byte Escapement();
void InsertSymbol(LPCTSTR theSymbol, int theValue);
void PutBackChar(byte theByte, int curLine = 0, LPCTSTR filename = NULL);
CToken* TokenFromName(LPCTSTR name);
CToken* HandleDirective();
CToken* HandleSlash();
CToken* HandleString();
CToken* HandleQuote();
CToken* HandleIdentifier(byte theByte);
CToken* HandleNumeric(byte theByte);
CToken* HandleFloat(bool thesign = false, long value = 0);
CToken* HandleDecimal(bool thesign = false);
CToken* HandleSymbol(byte theByte);
CToken* HandleHex(bool thesize);
CToken* HandleOctal(bool thesize);
int DirectiveFromName(LPCTSTR name);
CParseStream* m_curParseStream;
keywordArray_t* m_keywords;
keywordArray_t* m_symbols;
keywordArray_t* m_errors;
CSymbolLookup* m_symbolLookup;
CToken* m_nextToken;
CSymbolTable m_defines;
CTokenizerState* m_state;
UINT m_flags;
LPTokenizerErrorProc m_errorProc;
static keywordArray_t errorMessages[];
static keywordArray_t directiveKeywords[];
};
class CKeywordTable
{
public:
CKeywordTable(CTokenizer* tokenizer, keywordArray_t* keywords);
~CKeywordTable();
protected:
CTokenizer* m_tokenizer;
keywordArray_t* m_holdKeywords;
};
class CParsePutBack : public CParseStream
{
public:
CParsePutBack();
~CParsePutBack();
static CParsePutBack* Create(byte theByte, int curLine, LPCTSTR filename);
virtual void Delete();
virtual bool NextChar(byte& theByte);
virtual int GetCurLine();
virtual void GetCurFilename(char** theBuff);
virtual long GetRemainingSize();
protected:
virtual void Init(byte theByte, int curLine, LPCTSTR filename);
byte m_byte;
bool m_consumed;
int m_curLine;
char* m_curFile;
};
class CParseMemory : public CParseStream
{
public:
CParseMemory();
~CParseMemory();
static CParseMemory* Create(byte* data, long datasize);
virtual void Delete();
virtual bool NextChar(byte& theByte);
virtual int GetCurLine();
virtual void GetCurFilename(char** theBuff);
virtual long GetRemainingSize();
protected:
virtual void Init(byte* data, long datasize);
byte* m_data;
int m_curLine;
long m_curPos;
long m_datasize;
long m_offset;
};
class CParseBlock : public CParseMemory
{
public:
CParseBlock();
~CParseBlock();
static CParseBlock* Create(byte* data, long datasize);
virtual void Delete();
protected:
virtual void Init(byte* data, long datasize);
};
class CParseToken : public CParseStream
{
public:
CParseToken();
~CParseToken();
static CParseToken* Create(CToken* token);
virtual void Delete();
virtual bool NextChar(byte& theByte);
virtual int GetCurLine();
virtual void GetCurFilename(char** theBuff);
virtual long GetRemainingSize();
protected:
virtual void Init(CToken* token);
byte* m_data;
int m_curLine;
long m_curPos;
long m_datasize;
long m_offset;
};
class CParseDefine : public CParseMemory
{
public:
CParseDefine();
~CParseDefine();
static CParseDefine* Create(CDirectiveSymbol* definesymbol);
virtual void Delete();
virtual bool IsThisDefinition(void* theDefinition);
protected:
virtual void Init(CDirectiveSymbol* definesymbol);
CDirectiveSymbol* m_defineSymbol;
};
class CParseFile : public CParseStream
{
public:
CParseFile();
~CParseFile();
static CParseFile* Create();
static CParseFile* Create(LPCTSTR filename, CTokenizer* tokenizer);
// static CParseFile* Create(CFile* file, CTokenizer* tokenizer);
virtual void Delete();
virtual int GetCurLine();
virtual void GetCurFilename(char** theBuff);
virtual long GetRemainingSize();
virtual bool NextChar(byte& theByte);
protected:
virtual bool Init();
virtual bool Init(LPCTSTR filename, CTokenizer* tokenizer);
// virtual void Init(CFile* file, CTokenizer* tokenizer);
DWORD GetFileSize();
void Read(void* buff, UINT buffsize);
// CFile* m_file;
HANDLE m_fileHandle;
char* m_fileName;
int m_curLine;
int m_curPos;
byte* m_buff;
DWORD m_curByte;
DWORD m_filesize;
bool m_ownsFile;
};
#endif//__TOKENIZER_H