2007-06-28 10:47:08 -07:00
/*
* Event . c
*
* The event management system .
*/
# include <stdio.h>
// event tracing printf's
# define DEBUG_GROUP0
// display tested triggers
//#define DEBUG_GROUP1
2006-06-02 12:34:58 -07:00
# include "lib/framework/frame.h"
2007-06-28 10:47:08 -07:00
# include "interp.h"
# include "script.h"
# include "event.h"
// array to store release functions
static VAL_CREATE_FUNC * asCreateFuncs ;
static VAL_RELEASE_FUNC * asReleaseFuncs ;
static SDWORD numFuncs ;
// Heap for value chunks
static OBJ_HEAP * psValHeap ;
// Heap for active triggers
static OBJ_HEAP * psTrigHeap ;
// Heap for contexts
static OBJ_HEAP * psContHeap ;
// The list of currently active triggers
ACTIVE_TRIGGER * psTrigList ;
// The list of callback triggers
ACTIVE_TRIGGER * psCallbackList ;
// The new triggers added this loop
static ACTIVE_TRIGGER * psAddedTriggers ;
// The trigger which is currently firing
static ACTIVE_TRIGGER * psFiringTrigger ;
static BOOL triggerChanged ;
static UDWORD updateTime ;
// The currently allocated contexts
SCRIPT_CONTEXT * psContList ;
// The current event trace level
static SDWORD eventTraceLevel = 3 ;
// print info on trigger
# ifdef DEBUG
# define DB_TRIGINF(psTrigger, level)\
if ( eventTraceLevel > = ( level ) ) \
eventPrintTriggerInfo ( psTrigger )
# else
# define DB_TRIGINF(psTrigger, level)
# endif
// event tracing printf
# ifdef DEBUG
# define DB_TRACE(x, level) \
if ( eventTraceLevel > = ( level ) ) \
2006-08-22 07:28:49 -07:00
debug ( LOG_NEVER , x )
2007-06-28 10:47:08 -07:00
# else
# define DB_TRACE(x,level)
# endif
// Initialise a trigger
static BOOL eventInitTrigger ( ACTIVE_TRIGGER * * ppsTrigger , SCRIPT_CONTEXT * psContext ,
UDWORD event , SDWORD trigger , UDWORD currTime ) ;
// Add a trigger to the list in order
static void eventAddTrigger ( ACTIVE_TRIGGER * psTrigger ) ;
// Free up a trigger
static void eventFreeTrigger ( ACTIVE_TRIGGER * psTrigger ) ;
//resets the event timer - updateTime
void eventTimeReset ( UDWORD initTime )
{
updateTime = initTime ;
}
/* Initialise the event system */
BOOL eventInitialise ( EVENT_INIT * psInit )
{
// Create the value heap
if ( ! HEAP_CREATE ( & psValHeap , sizeof ( VAL_CHUNK ) , psInit - > valInit , psInit - > valExt ) )
{
2006-08-19 06:26:11 -07:00
debug ( LOG_ERROR , " eventInitialise: HEAP_CREATE failed for values " ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
// Create the trigger heap
if ( ! HEAP_CREATE ( & psTrigHeap , sizeof ( ACTIVE_TRIGGER ) , psInit - > trigInit , psInit - > trigExt ) )
{
2006-08-19 06:26:11 -07:00
debug ( LOG_ERROR , " eventInitialise: HEAP_CREATE failed for triggers " ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
// Create the context heap
if ( ! HEAP_CREATE ( & psContHeap , sizeof ( SCRIPT_CONTEXT ) , psInit - > contInit , psInit - > contExt ) )
{
2006-08-19 06:26:11 -07:00
debug ( LOG_ERROR , " eventInitialise: HEAP_CREATE failed for context " ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
psTrigList = NULL ;
psCallbackList = NULL ;
psContList = NULL ;
eventTraceLevel = 0 ;
asCreateFuncs = NULL ;
asReleaseFuncs = NULL ;
numFuncs = 0 ;
return TRUE ;
}
// reset the event system
void eventReset ( void )
{
ACTIVE_TRIGGER * psCurr ;
# ifdef DEBUG
SDWORD count = 0 ;
# endif
// Free any active triggers and their context's
while ( psTrigList )
{
psCurr = psTrigList ;
psTrigList = psTrigList - > psNext ;
# ifdef DEBUG
if ( ! psCurr - > psContext - > release )
{
count + = 1 ;
}
# endif
eventRemoveContext ( psCurr - > psContext ) ;
HEAP_FREE ( psTrigHeap , psCurr ) ;
}
// Free any active callback triggers and their context's
while ( psCallbackList )
{
psCurr = psCallbackList ;
psCallbackList = psCallbackList - > psNext ;
# ifdef DEBUG
if ( ! psCurr - > psContext - > release )
{
count + = 1 ;
}
# endif
eventRemoveContext ( psCurr - > psContext ) ;
HEAP_FREE ( psTrigHeap , psCurr ) ;
}
// Now free any context's that are left
while ( psContList )
{
# ifdef DEBUG
if ( ! psContList - > release )
{
count + = 1 ;
}
# endif
eventRemoveContext ( psContList ) ;
}
# ifdef DEBUG
if ( count > 0 )
{
2006-08-22 07:28:49 -07:00
debug ( LOG_NEVER , " eventReset: %d contexts still allocated at shutdown \n " , count ) ;
2007-06-28 10:47:08 -07:00
}
# endif
}
// Shutdown the event system
void eventShutDown ( void )
{
eventReset ( ) ;
HEAP_DESTROY ( psValHeap ) ;
HEAP_DESTROY ( psTrigHeap ) ;
HEAP_DESTROY ( psContHeap ) ;
if ( asCreateFuncs )
{
FREE ( asCreateFuncs ) ;
}
if ( asReleaseFuncs )
{
FREE ( asReleaseFuncs ) ;
}
}
// get the trigger id string
STRING * eventGetTriggerID ( SCRIPT_CODE * psCode , SDWORD trigger )
{
STRING * pID , * pTrigType ;
static STRING aIDNum [ 255 ] ;
SDWORD i ;
TRIGGER_TYPE type ;
if ( ( trigger > = 0 ) & & ( trigger < psCode - > numTriggers ) )
{
type = psCode - > psTriggerData [ trigger ] . type ;
}
else
{
return " INACTIVE " ;
}
pTrigType = " UNKNOWN " ;
switch ( type )
{
case TR_INIT :
pTrigType = " INIT " ;
break ;
case TR_CODE :
pTrigType = " CODE " ;
break ;
case TR_WAIT :
pTrigType = " WAIT " ;
break ;
case TR_EVERY :
pTrigType = " EVERY " ;
break ;
case TR_PAUSE :
pTrigType = " PAUSE " ;
break ;
default :
if ( asScrCallbackTab )
{
pTrigType = asScrCallbackTab [ type - TR_CALLBACKSTART ] . pIdent ;
}
break ;
}
if ( psCode - > psDebug = = NULL | | type ! = TR_CODE )
{
sprintf ( aIDNum , " %d (%s) " , trigger , pTrigType ) ;
}
else
{
pID = " NOT FOUND " ;
for ( i = 0 ; i < psCode - > debugEntries ; i + + )
{
if ( psCode - > psDebug [ i ] . offset = = psCode - > pTriggerTab [ trigger ] )
{
pID = psCode - > psDebug [ i ] . pLabel ;
break ;
}
}
sprintf ( aIDNum , " %s (%s) " , pID , pTrigType ) ;
}
return aIDNum ;
}
// get the event id string
STRING * eventGetEventID ( SCRIPT_CODE * psCode , SDWORD event )
{
STRING * pID ;
static STRING aIDNum [ 255 ] ;
SDWORD i ;
if ( ( psCode - > psDebug = = NULL ) | |
( event < 0 ) | | ( event > psCode - > numEvents ) )
{
sprintf ( aIDNum , " %d " , event ) ;
return aIDNum ;
}
pID = " NOT FOUND " ;
for ( i = 0 ; i < psCode - > debugEntries ; i + + )
{
if ( psCode - > psDebug [ i ] . offset = = psCode - > pEventTab [ event ] )
{
pID = psCode - > psDebug [ i ] . pLabel ;
break ;
}
}
return pID ;
}
// Print out all the info available about a trigger
void eventPrintTriggerInfo ( ACTIVE_TRIGGER * psTrigger )
{
SCRIPT_CODE * psCode = psTrigger - > psContext - > psCode ;
// BOOL debugInfo = psCode->psDebug != NULL;
STRING * pTrigLab , * pEventLab ;
// find the debug info for the trigger
pTrigLab = eventGetTriggerID ( psCode , psTrigger - > trigger ) ;
// find the debug info for the event
pEventLab = eventGetEventID ( psCode , psTrigger - > event ) ;
2006-08-22 07:28:49 -07:00
debug ( LOG_NEVER , " trigger %s at %d -> %s " , pTrigLab , psTrigger - > testTime , pEventLab ) ;
2007-06-28 10:47:08 -07:00
if ( psTrigger - > offset ! = 0 )
{
2006-08-22 07:28:49 -07:00
debug ( LOG_NEVER , " %d " , psTrigger - > offset ) ;
2007-06-28 10:47:08 -07:00
}
}
// Initialise the create/release function array - specify the maximum value type
BOOL eventInitValueFuncs ( SDWORD maxType )
{
2006-08-19 06:26:11 -07:00
if ( asReleaseFuncs ! = NULL ) //<NEW> 13.05.05
debug ( LOG_ERROR , " eventInitValueFuncs: array already initialised " ) ;
2006-08-23 05:58:48 -07:00
ASSERT ( asReleaseFuncs = = NULL ,
" eventInitValueFuncs: array already initialised " ) ;
2007-06-28 10:47:08 -07:00
asCreateFuncs = ( VAL_CREATE_FUNC * ) MALLOC ( sizeof ( VAL_CREATE_FUNC ) * maxType ) ;
if ( ! asCreateFuncs )
{
2006-08-19 06:26:11 -07:00
debug ( LOG_ERROR , " eventInitValueFuncs: Out of memory " ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
asReleaseFuncs = ( VAL_RELEASE_FUNC * ) MALLOC ( sizeof ( VAL_RELEASE_FUNC ) * maxType ) ;
if ( ! asReleaseFuncs )
{
2006-08-19 06:26:11 -07:00
debug ( LOG_ERROR , " eventInitValueFuncs: Out of memory " ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
memset ( asCreateFuncs , 0 , sizeof ( VAL_CREATE_FUNC ) * maxType ) ;
memset ( asReleaseFuncs , 0 , sizeof ( VAL_RELEASE_FUNC ) * maxType ) ;
numFuncs = maxType ;
return TRUE ;
}
// Add a new value create function
BOOL eventAddValueCreate ( INTERP_TYPE type , VAL_CREATE_FUNC create )
{
if ( type > = numFuncs )
{
2006-08-22 07:28:49 -07:00
debug ( LOG_ERROR , " eventAddValueCreate: type out of range " ) ;
abort ( ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
asCreateFuncs [ type ] = create ;
return TRUE ;
}
// Add a new value release function
BOOL eventAddValueRelease ( INTERP_TYPE type , VAL_RELEASE_FUNC release )
{
if ( type > = numFuncs )
{
2006-08-22 07:28:49 -07:00
debug ( LOG_ERROR , " eventAddValueRelease: type out of range " ) ;
abort ( ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
asReleaseFuncs [ type ] = release ;
return TRUE ;
}
// Create a new context for a script
BOOL eventNewContext ( SCRIPT_CODE * psCode , CONTEXT_RELEASE release ,
SCRIPT_CONTEXT * * ppsContext )
{
SCRIPT_CONTEXT * psContext ;
2006-08-15 11:38:51 -07:00
SDWORD val , storeIndex , type , arrayNum , i , j , arraySize ;
2007-06-28 10:47:08 -07:00
VAL_CHUNK * psNewChunk , * psNextChunk ;
2006-08-23 05:58:48 -07:00
ASSERT ( PTRVALID ( psCode , sizeof ( SCRIPT_CODE ) ) ,
" eventNewContext: Invalid code pointer " ) ;
2007-06-28 10:47:08 -07:00
// Get a new context
if ( ! HEAP_ALLOC ( psContHeap , ( void * ) & psContext ) )
{
2006-08-15 11:38:51 -07:00
debug ( LOG_ERROR , " eventNewContext: HEAP_ALLOC failed " ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
// Initialise the context
psContext - > psCode = psCode ;
psContext - > triggerCount = 0 ;
psContext - > release = ( SWORD ) ( release = = CR_RELEASE ? TRUE : FALSE ) ;
psContext - > psGlobals = NULL ;
psContext - > id = - 1 ; // only used by the save game
val = psCode - > numGlobals + psCode - > arraySize - 1 ;
arrayNum = psCode - > numArrays - 1 ;
arraySize = 1 ;
if ( psCode - > numArrays > 0 )
{
for ( i = 0 ; i < psCode - > psArrayInfo [ arrayNum ] . dimensions ; i + + )
{
arraySize * = psCode - > psArrayInfo [ arrayNum ] . elements [ i ] ;
}
}
2006-08-15 11:38:51 -07:00
//prepare local variables (initialize, store type)
//-------------------------------
2006-08-22 07:28:49 -07:00
psCode - > ppsLocalVarVal = ( INTERP_VAL * * ) MALLOC ( sizeof ( INTERP_VAL * ) * psCode - > numEvents ) ; //allocate space for array of local var arrays for each event
2006-08-15 11:38:51 -07:00
debug ( LOG_SCRIPT , " allocated space for %d events " , psCode - > numEvents ) ;
for ( i = 0 ; i < psCode - > numEvents ; i + + )
{
if ( psCode - > numLocalVars [ i ] > 0 ) //this event has any local vars declared
{
psCode - > ppsLocalVarVal [ i ] = ( INTERP_VAL * ) MALLOC ( sizeof ( INTERP_VAL ) * psCode - > numLocalVars [ i ] ) ; //allocate space for local vars array (for the current event)
debug ( LOG_SCRIPT , " Event %d has %d local variables " , i , psCode - > numLocalVars [ i ] ) ;
for ( j = 0 ; j < psCode - > numLocalVars [ i ] ; j + + )
{
type = psCode - > ppsLocalVars [ i ] [ j ] ;
psCode - > ppsLocalVarVal [ i ] [ j ] . type = type ; //store (copy) var type (data used during parsing -> data used during interpreting)
//debug(LOG_SCRIPT,"var %d's type: %d", i, type);
//initialize Strings and integers
if ( type = = VAL_STRING )
{
2006-08-19 06:26:11 -07:00
//debug(LOG_ERROR,"eventNewContext: STRING type variables are not implemented");
2006-08-15 11:38:51 -07:00
2006-08-19 06:26:11 -07:00
psCode - > ppsLocalVarVal [ i ] [ j ] . v . sval = ( char * ) MALLOC ( MAXSTRLEN ) ;
2006-08-15 11:38:51 -07:00
strcpy ( psCode - > ppsLocalVarVal [ i ] [ j ] . v . sval , " \0 " ) ;
}
else
{
psCode - > ppsLocalVarVal [ i ] [ j ] . v . ival = 0 ;
}
//Initialize objects
if ( asCreateFuncs ! = NULL & & type < numFuncs & & asCreateFuncs [ type ] )
{
if ( ! asCreateFuncs [ type ] ( & ( psCode - > ppsLocalVarVal [ i ] [ j ] ) ) )
{
debug ( LOG_ERROR , " eventNewContext: asCreateFuncs failed for local var " ) ;
return FALSE ;
}
}
//debug(LOG_SCRIPT, "i=%d, j=%d, value=%d",i,j,psCode->ppsLocalVarVal[i][j].v.ival);
}
2006-08-21 02:34:42 -07:00
//debug(LOG_SCRIPT,"------");
2006-08-22 07:28:49 -07:00
2006-08-15 11:38:51 -07:00
}
else //this event has no local vars
{
psCode - > ppsLocalVarVal [ i ] = NULL ;
}
2006-08-22 07:28:49 -07:00
2006-08-15 11:38:51 -07:00
}
2007-06-28 10:47:08 -07:00
while ( val > = 0 )
{
if ( ! HEAP_ALLOC ( psValHeap , ( void * ) & psNewChunk ) )
{
for ( psNewChunk = psContext - > psGlobals ; psNewChunk ; psNewChunk = psNextChunk )
{
psNextChunk = psNewChunk - > psNext ;
HEAP_FREE ( psValHeap , psNewChunk ) ;
}
HEAP_FREE ( psContHeap , psContext ) ;
return FALSE ;
}
// Set the value types
storeIndex = val % CONTEXT_VALS ;
while ( storeIndex > = 0 )
{
if ( val > = psCode - > numGlobals )
{
type = psCode - > psArrayInfo [ arrayNum ] . type ;
}
else
{
type = psCode - > pGlobals [ val ] ;
}
psNewChunk - > asVals [ storeIndex ] . type = type ;
2006-08-19 06:26:11 -07:00
//initialize Strings
if ( type = = VAL_STRING )
{
psNewChunk - > asVals [ storeIndex ] . v . sval = ( char * ) MALLOC ( MAXSTRLEN ) ;
strcpy ( psNewChunk - > asVals [ storeIndex ] . v . sval , " \0 " ) ;
}
else
{
psNewChunk - > asVals [ storeIndex ] . v . ival = 0 ;
}
2006-08-21 02:34:42 -07:00
//initialize objects
2007-06-28 10:47:08 -07:00
if ( asCreateFuncs ! = NULL & & type < numFuncs & & asCreateFuncs [ type ] )
{
if ( ! asCreateFuncs [ type ] ( psNewChunk - > asVals + storeIndex ) )
{
HEAP_FREE ( psValHeap , psNewChunk ) ;
for ( psNewChunk = psContext - > psGlobals ; psNewChunk ; psNewChunk = psNextChunk )
{
psNextChunk = psNewChunk - > psNext ;
HEAP_FREE ( psValHeap , psNewChunk ) ;
}
HEAP_FREE ( psContHeap , psContext ) ;
return FALSE ;
}
}
storeIndex - = 1 ;
val - = 1 ;
arraySize - = 1 ;
if ( arraySize < = 0 )
{
// finished this array
arrayNum - = 1 ;
if ( arrayNum > = 0 )
{
// calculate the next array size
arraySize = 1 ;
for ( i = 0 ; i < psCode - > psArrayInfo [ arrayNum ] . dimensions ; i + + )
{
arraySize * = psCode - > psArrayInfo [ arrayNum ] . elements [ i ] ;
}
}
}
}
psNewChunk - > psNext = psContext - > psGlobals ;
psContext - > psGlobals = psNewChunk ;
}
psContext - > psNext = psContList ;
psContList = psContext ;
* ppsContext = psContext ;
return TRUE ;
}
// Copy a context, including variable values
BOOL eventCopyContext ( SCRIPT_CONTEXT * psContext , SCRIPT_CONTEXT * * ppsNew )
{
SCRIPT_CONTEXT * psNew ;
SDWORD val ;
VAL_CHUNK * psChunk , * psOChunk ;
2006-08-23 05:58:48 -07:00
ASSERT ( PTRVALID ( psContext , sizeof ( SCRIPT_CONTEXT ) ) ,
" eventCopyContext: Invalid context pointer " ) ;
2007-06-28 10:47:08 -07:00
// Get a new context
if ( ! eventNewContext ( psContext - > psCode , psContext - > release , & psNew ) )
{
return FALSE ;
}
// Now copy the values over
psChunk = psNew - > psGlobals ;
psOChunk = psContext - > psGlobals ;
while ( psChunk )
{
for ( val = 0 ; val < CONTEXT_VALS ; val + + )
{
psChunk - > asVals [ val ] . v . ival = psOChunk - > asVals [ val ] . v . ival ;
}
psChunk = psChunk - > psNext ;
psOChunk = psOChunk - > psNext ;
}
* ppsNew = psNew ;
return TRUE ;
}
// Add a new object to the trigger system
// Time is the application time at which all the triggers are to be started
BOOL eventRunContext ( SCRIPT_CONTEXT * psContext , UDWORD time )
{
SDWORD event ;
ACTIVE_TRIGGER * psTrigger ;
TRIGGER_DATA * psData ;
SCRIPT_CODE * psCode ;
2006-08-23 05:58:48 -07:00
ASSERT ( PTRVALID ( psContext , sizeof ( SCRIPT_CONTEXT ) ) ,
" eventNewObject: Invalid context pointer " ) ;
2007-06-28 10:47:08 -07:00
// Now setup all the triggers
psContext - > triggerCount = 0 ;
psCode = psContext - > psCode ;
for ( event = 0 ; event < psCode - > numEvents ; event + + )
{
if ( psCode - > pEventLinks [ event ] > = 0 )
{
// See if this is an init event
psData = psCode - > psTriggerData + psCode - > pEventLinks [ event ] ;
if ( psData - > type = = TR_INIT )
{
if ( ! interpRunScript ( psContext , IRT_EVENT , event , 0 ) )
{
return FALSE ;
}
}
else
{
if ( ! eventInitTrigger ( & psTrigger , psContext , event ,
psCode - > pEventLinks [ event ] , time ) )
{
return FALSE ;
}
eventAddTrigger ( psTrigger ) ;
DB_TRACE ( ( " added " ) , 2 ) ;
DB_TRIGINF ( psTrigger , 2 ) ;
DB_TRACE ( ( " \n " ) , 2 ) ;
}
}
}
return TRUE ;
}
// Remove an object from the event system
void eventRemoveContext ( SCRIPT_CONTEXT * psContext )
{
ACTIVE_TRIGGER * psCurr , * psPrev = NULL , * psNext ;
VAL_CHUNK * psCChunk , * psNChunk ;
SCRIPT_CONTEXT * psCCont , * psPCont = NULL ;
SDWORD i , chunkStart ;
INTERP_VAL * psVal ;
// Get rid of all it's triggers
while ( psTrigList & & psTrigList - > psContext = = psContext )
{
psNext = psTrigList - > psNext ;
eventFreeTrigger ( psTrigList ) ;
psTrigList = psNext ;
}
for ( psCurr = psTrigList ; psCurr ; psCurr = psNext )
{
psNext = psCurr - > psNext ;
if ( psCurr - > psContext = = psContext )
{
eventFreeTrigger ( psCurr ) ;
psPrev - > psNext = psNext ;
}
else
{
psPrev = psCurr ;
}
}
// Get rid of all it's callback triggers
while ( psCallbackList & & psCallbackList - > psContext = = psContext )
{
psNext = psCallbackList - > psNext ;
eventFreeTrigger ( psCallbackList ) ;
psCallbackList = psNext ;
}
for ( psCurr = psCallbackList ; psCurr ; psCurr = psNext )
{
psNext = psCurr - > psNext ;
if ( psCurr - > psContext = = psContext )
{
eventFreeTrigger ( psCurr ) ;
psPrev - > psNext = psNext ;
}
else
{
psPrev = psCurr ;
}
}
// Call the release function for all the values
if ( asReleaseFuncs ! = NULL )
{
psCChunk = psContext - > psGlobals ;
chunkStart = 0 ;
for ( i = 0 ; i < psContext - > psCode - > numGlobals ; i + + )
{
if ( i - chunkStart > = CONTEXT_VALS )
{
chunkStart + = CONTEXT_VALS ;
psCChunk = psCChunk - > psNext ;
2006-08-23 05:58:48 -07:00
ASSERT ( psCChunk ! = NULL ,
" eventRemoveContext: not enough value chunks " ) ;
2007-06-28 10:47:08 -07:00
}
psVal = psCChunk - > asVals + ( i - chunkStart ) ;
if ( psVal - > type < numFuncs & & asReleaseFuncs [ psVal - > type ] ! = NULL )
{
asReleaseFuncs [ psVal - > type ] ( psVal ) ;
}
}
}
// Free it's variables
for ( psCChunk = psContext - > psGlobals ; psCChunk ; psCChunk = psNChunk )
{
psNChunk = psCChunk - > psNext ;
HEAP_FREE ( psValHeap , psCChunk ) ;
}
// Remove it from the context list
if ( psContext = = psContList )
{
psCCont = psContList ;
psContList = psContList - > psNext ;
HEAP_FREE ( psContHeap , psCCont ) ;
}
else
{
for ( psCCont = psContList ; psCCont & & psCCont ! = psContext ;
psCCont = psCCont - > psNext )
{
psPCont = psCCont ;
}
if ( psCCont )
{
psPCont - > psNext = psCCont - > psNext ;
HEAP_FREE ( psContHeap , psContext ) ;
}
else
{
2006-08-23 05:58:48 -07:00
ASSERT ( FALSE , " eventRemoveContext: context not found " ) ;
2007-06-28 10:47:08 -07:00
}
}
}
// Get the value pointer for a variable index
BOOL eventGetContextVal ( SCRIPT_CONTEXT * psContext , UDWORD index , INTERP_VAL * * ppsVal )
{
VAL_CHUNK * psChunk ;
// Find the chunk for the variable
psChunk = psContext - > psGlobals ;
while ( psChunk & & index > = CONTEXT_VALS )
{
index - = CONTEXT_VALS ;
psChunk = psChunk - > psNext ;
}
if ( ! psChunk )
{
2006-08-23 05:58:48 -07:00
ASSERT ( FALSE , " eventGetContextVal: Variable not found " ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
* ppsVal = psChunk - > asVals + index ;
return TRUE ;
}
// Set a global variable value for a context
BOOL eventSetContextVar ( SCRIPT_CONTEXT * psContext , UDWORD index ,
INTERP_TYPE type , UDWORD data )
{
INTERP_VAL * psVal ;
if ( ! eventGetContextVal ( psContext , index , & psVal ) )
{
return FALSE ;
}
if ( psVal - > type ! = type )
{
2006-08-23 05:58:48 -07:00
ASSERT ( FALSE , " eventSetContextVar: Variable type mismatch " ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
// Store the data
psVal - > v . ival = ( SDWORD ) data ;
return TRUE ;
}
// Add a trigger to the list in order
static void eventAddTrigger ( ACTIVE_TRIGGER * psTrigger )
{
ACTIVE_TRIGGER * psCurr , * psPrev = NULL ;
UDWORD testTime = psTrigger - > testTime ;
if ( psTrigger - > type > = TR_CALLBACKSTART )
{
// Add this to the callback trigger list
if ( psCallbackList = = NULL )
{
psTrigger - > psNext = NULL ;
psCallbackList = psTrigger ;
}
else if ( psTrigger - > type < = psCallbackList - > type )
{
psTrigger - > psNext = psCallbackList ;
psCallbackList = psTrigger ;
}
else
{
for ( psCurr = psCallbackList ; psCurr & & psCurr - > type < psTrigger - > type ;
psCurr = psCurr - > psNext )
{
psPrev = psCurr ;
}
psTrigger - > psNext = psPrev - > psNext ;
psPrev - > psNext = psTrigger ;
}
}
else if ( psTrigList = = NULL )
{
psTrigger - > psNext = NULL ;
psTrigList = psTrigger ;
}
else if ( testTime < = psTrigList - > testTime )
{
psTrigger - > psNext = psTrigList ;
psTrigList = psTrigger ;
}
else
{
for ( psCurr = psTrigList ; psCurr & & psCurr - > testTime < testTime ;
psCurr = psCurr - > psNext )
{
psPrev = psCurr ;
}
psTrigger - > psNext = psPrev - > psNext ;
psPrev - > psNext = psTrigger ;
}
}
2006-06-02 12:34:58 -07:00
2007-06-28 10:47:08 -07:00
// Initialise a trigger
static BOOL eventInitTrigger ( ACTIVE_TRIGGER * * ppsTrigger , SCRIPT_CONTEXT * psContext ,
UDWORD event , SDWORD trigger , UDWORD currTime )
{
ACTIVE_TRIGGER * psNewTrig ;
TRIGGER_DATA * psTrigData ;
UDWORD testTime ;
2006-08-23 05:58:48 -07:00
ASSERT ( event < psContext - > psCode - > numEvents ,
" eventAddTrigger: Event out of range " ) ;
ASSERT ( trigger < psContext - > psCode - > numTriggers ,
" eventAddTrigger: Trigger out of range " ) ;
2007-06-28 10:47:08 -07:00
if ( trigger = = - 1 )
{
return FALSE ;
}
// Get a trigger object
if ( ! HEAP_ALLOC ( psTrigHeap , ( void * ) & psNewTrig ) )
{
return FALSE ;
}
// Initialise the trigger
psNewTrig - > psContext = psContext ;
psContext - > triggerCount + = 1 ;
psTrigData = psContext - > psCode - > psTriggerData + trigger ;
testTime = currTime + psTrigData - > time ;
psNewTrig - > testTime = testTime ;
psNewTrig - > trigger = ( SWORD ) trigger ;
psNewTrig - > type = ( SWORD ) psTrigData - > type ;
psNewTrig - > event = ( UWORD ) event ;
psNewTrig - > offset = 0 ;
* ppsTrigger = psNewTrig ;
return TRUE ;
}
// Load a trigger into the system from a save game
BOOL eventLoadTrigger ( UDWORD time , SCRIPT_CONTEXT * psContext ,
SDWORD type , SDWORD trigger , UDWORD event , UDWORD offset )
{
ACTIVE_TRIGGER * psNewTrig ;
TRIGGER_DATA * psTrigData ;
2006-08-23 05:58:48 -07:00
ASSERT ( event < psContext - > psCode - > numEvents ,
" eventLoadTrigger: Event out of range " ) ;
ASSERT ( trigger < psContext - > psCode - > numTriggers ,
" eventLoadTrigger: Trigger out of range " ) ;
2007-06-28 10:47:08 -07:00
// Get a trigger object
if ( ! HEAP_ALLOC ( psTrigHeap , ( void * ) & psNewTrig ) )
{
2006-08-22 07:28:49 -07:00
debug ( LOG_ERROR , " eventLoadTrigger: out of memory " ) ;
abort ( ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
// Initialise the trigger
psNewTrig - > psContext = psContext ;
psContext - > triggerCount + = 1 ;
psTrigData = psContext - > psCode - > psTriggerData + trigger ;
psNewTrig - > testTime = time ;
psNewTrig - > trigger = ( SWORD ) trigger ;
psNewTrig - > type = ( SWORD ) type ;
psNewTrig - > event = ( UWORD ) event ;
psNewTrig - > offset = ( UWORD ) offset ;
eventAddTrigger ( psNewTrig ) ;
return TRUE ;
}
// add a TR_PAUSE trigger to the event system.
BOOL eventAddPauseTrigger ( SCRIPT_CONTEXT * psContext , UDWORD event , UDWORD offset ,
UDWORD time )
{
ACTIVE_TRIGGER * psNewTrig ;
SDWORD trigger ;
2006-08-23 05:58:48 -07:00
ASSERT ( event < psContext - > psCode - > numEvents ,
" eventAddTrigger: Event out of range " ) ;
2007-06-28 10:47:08 -07:00
// Get a trigger object
if ( ! HEAP_ALLOC ( psTrigHeap , ( void * ) & psNewTrig ) )
{
return FALSE ;
}
// figure out what type of trigger will go into the system when the pause
// finishes
switch ( psFiringTrigger - > type )
{
case TR_WAIT :
// fired by a wait trigger, no trigger to replace it
trigger = - 1 ;
break ;
case TR_PAUSE :
// fired by a pause trigger, use the trigger stored with it
trigger = psFiringTrigger - > trigger ;
break ;
default :
// just store the trigger that fired
trigger = psFiringTrigger - > trigger ;
break ;
}
// Initialise the trigger
psNewTrig - > psContext = psContext ;
psContext - > triggerCount + = 1 ;
psNewTrig - > testTime = updateTime + time ;
psNewTrig - > trigger = ( SWORD ) trigger ;
psNewTrig - > type = TR_PAUSE ;
psNewTrig - > event = ( UWORD ) event ;
psNewTrig - > offset = ( UWORD ) offset ;
// store the new trigger
psNewTrig - > psNext = psAddedTriggers ;
psAddedTriggers = psNewTrig ;
// tell the event system the trigger has been changed
triggerChanged = TRUE ;
return TRUE ;
}
// Free up a trigger
static void eventFreeTrigger ( ACTIVE_TRIGGER * psTrigger )
{
if ( psTrigger - > psContext - > release & & psTrigger - > psContext - > triggerCount < = 1 )
{
// Free the context as well
eventRemoveContext ( psTrigger - > psContext ) ;
}
HEAP_FREE ( psTrigHeap , psTrigger ) ;
}
// Activate a callback trigger
void eventFireCallbackTrigger ( TRIGGER_TYPE callback )
{
ACTIVE_TRIGGER * psPrev , * psCurr , * psNext ;
TRIGGER_DATA * psTrigDat ;
BOOL fired ;
2006-09-06 10:19:20 -07:00
// FIXME temporary check
// FIXME This needs to be removed as soon as we are sure the transport comes and we don't have any more problems with the VIDEO_QUIT callback !!
2006-09-06 09:58:20 -07:00
if ( callback = = 15 )
debug ( LOG_SCRIPT , " eventFireCallbackTrigger: processing CALL_VIDEO_QUIT " ) ;
2007-06-28 10:47:08 -07:00
if ( interpProcessorActive ( ) )
{
2006-08-23 05:58:48 -07:00
ASSERT ( FALSE ,
" eventFireCallbackTrigger: script interpreter is already running " ) ;
2007-06-28 10:47:08 -07:00
return ;
}
//this can be called from eventProcessTriggers and so will wipe out all the current added ones
//psAddedTriggers = NULL;
psPrev = NULL ;
for ( psCurr = psCallbackList ; psCurr & & psCurr - > type < = callback ;
psCurr = psNext )
{
psNext = psCurr - > psNext ;
if ( psCurr - > type = = callback )
{
// see if the callback should be fired
fired = FALSE ;
if ( psCurr - > type ! = TR_PAUSE )
{
2006-08-23 05:58:48 -07:00
ASSERT ( psCurr - > trigger > = 0 & &
2007-06-28 10:47:08 -07:00
psCurr - > trigger < psCurr - > psContext - > psCode - > numTriggers ,
2006-08-23 05:58:48 -07:00
" eventFireCallbackTrigger: invalid trigger number " ) ;
2007-06-28 10:47:08 -07:00
psTrigDat = psCurr - > psContext - > psCode - > psTriggerData + psCurr - > trigger ;
}
else
{
psTrigDat = NULL ;
}
if ( psTrigDat & & psTrigDat - > code )
{
if ( ! interpRunScript ( psCurr - > psContext , IRT_TRIGGER ,
psCurr - > trigger , 0 ) )
{
2006-08-23 05:58:48 -07:00
ASSERT ( FALSE , " eventFireCallbackTrigger: trigger %s: code failed " ,
eventGetTriggerID ( psCurr - > psContext - > psCode , psCurr - > trigger ) ) ;
2007-06-28 10:47:08 -07:00
psPrev = psCurr ;
continue ;
}
if ( ! stackPopParams ( 1 , VAL_BOOL , & fired ) )
{
2006-08-23 05:58:48 -07:00
ASSERT ( FALSE , " eventFireCallbackTrigger: trigger %s: code failed " ,
eventGetTriggerID ( psCurr - > psContext - > psCode , psCurr - > trigger ) ) ;
2007-06-28 10:47:08 -07:00
psPrev = psCurr ;
continue ;
}
}
else
{
fired = TRUE ;
}
// run the event
if ( fired )
{
DB_TRIGINF ( psCurr , 1 ) ;
DB_TRACE ( ( " fired \n " ) , 1 ) ;
// remove the trigger from the list
if ( psPrev = = NULL )
{
psCallbackList = psCallbackList - > psNext ;
}
else
{
psPrev - > psNext = psNext ;
}
triggerChanged = FALSE ;
psFiringTrigger = psCurr ;
if ( ! interpRunScript ( psCurr - > psContext ,
IRT_EVENT , psCurr - > event , psCurr - > offset ) ) // this could set triggerChanged
{
2006-08-23 05:58:48 -07:00
ASSERT ( FALSE , " eventFireCallbackTrigger: event %s: code failed " ,
eventGetEventID ( psCurr - > psContext - > psCode , psCurr - > event ) ) ;
2007-06-28 10:47:08 -07:00
}
if ( triggerChanged )
{
// don't need to add the trigger again - just free it
eventFreeTrigger ( psCurr ) ;
}
else
{
// make sure the trigger goes back into the system
psFiringTrigger - > psNext = psAddedTriggers ;
psAddedTriggers = psFiringTrigger ;
}
}
else
{
psPrev = psCurr ;
}
}
else
{
psPrev = psCurr ;
}
}
// Now add all the new triggers
for ( psCurr = psAddedTriggers ; psCurr ; psCurr = psNext )
{
psNext = psCurr - > psNext ;
eventAddTrigger ( psCurr ) ;
}
//clear out after added them all
psAddedTriggers = NULL ;
}
// Run a trigger
static BOOL eventFireTrigger ( ACTIVE_TRIGGER * psTrigger )
{
// TRIGGER_DATA *psTrigData;
BOOL fired ;
INTERP_VAL sResult ;
fired = FALSE ;
// If this is a code trigger see if it fires
if ( psTrigger - > type = = TR_CODE )
{
// Run the trigger
if ( ! interpRunScript ( psTrigger - > psContext ,
IRT_TRIGGER , psTrigger - > trigger , 0 ) )
{
2006-08-23 05:58:48 -07:00
ASSERT ( FALSE , " eventFireTrigger: trigger %s: code failed " ,
eventGetTriggerID ( psTrigger - > psContext - > psCode , psTrigger - > trigger ) ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
// Get the result
sResult . type = VAL_BOOL ;
if ( ! stackPopType ( & sResult ) )
{
return FALSE ;
}
fired = sResult . v . bval ;
}
else
{
fired = TRUE ;
}
// If it fired run the event
if ( fired )
{
DB_TRIGINF ( psTrigger , 1 ) ;
DB_TRACE ( ( " fired \n " ) , 1 ) ;
if ( ! interpRunScript ( psTrigger - > psContext ,
IRT_EVENT , psTrigger - > event , psTrigger - > offset ) )
{
DB_TRACE ( ( " \n \n ******** script failed ********* \n " ) , 0 ) ;
DB_TRIGINF ( psTrigger , 0 ) ;
DB_TRACE ( ( " \n " ) , 0 ) ;
2006-08-23 05:58:48 -07:00
ASSERT ( FALSE , " eventFireTrigger: event %s: code failed " ,
eventGetEventID ( psTrigger - > psContext - > psCode , psTrigger - > event ) ) ;
2007-06-28 10:47:08 -07:00
return FALSE ;
}
}
# ifdef DEBUG
else
{
DB_TRIGINF ( psTrigger , 3 ) ;
DB_TRACE ( ( " \n " ) , 3 ) ;
}
# endif
return TRUE ;
}
// Process all the currently active triggers
void eventProcessTriggers ( UDWORD currTime )
{
ACTIVE_TRIGGER * psCurr , * psNext , * psNew ;
TRIGGER_DATA * psData ;
// Process all the current triggers
psAddedTriggers = NULL ;
updateTime = currTime ;
while ( psTrigList & & psTrigList - > testTime < = currTime )
{
psCurr = psTrigList ;
psTrigList = psTrigList - > psNext ;
// Store the trigger so that I can tell if the event changes
// the trigger assigned to it
psFiringTrigger = psCurr ;
triggerChanged = FALSE ;
// Run the trigger
if ( eventFireTrigger ( psCurr ) ) // This might set triggerChanged
{
if ( triggerChanged | | psCurr - > type = = TR_WAIT )
{
// remove the trigger
eventFreeTrigger ( psCurr ) ;
}
else if ( psCurr - > type = = TR_PAUSE )
{
// restarted a paused event - replace the old trigger
if ( psCurr - > trigger ! = - 1 )
{
if ( eventInitTrigger ( & psNew , psCurr - > psContext ,
psCurr - > event , psCurr - > trigger , updateTime ) )
{
psNew - > psNext = psAddedTriggers ;
psAddedTriggers = psNew ;
}
}
// remove the TR_PAUSE trigger
eventFreeTrigger ( psCurr ) ;
}
else
{
// Add the trigger again
psData = psCurr - > psContext - > psCode - > psTriggerData +
psCurr - > trigger ;
psCurr - > testTime = currTime + psData - > time ;
psCurr - > psNext = psAddedTriggers ;
psAddedTriggers = psCurr ;
}
}
}
// Now add all the new triggers
for ( psCurr = psAddedTriggers ; psCurr ; psCurr = psNext )
{
psNext = psCurr - > psNext ;
eventAddTrigger ( psCurr ) ;
}
//clear out after added them all
psAddedTriggers = NULL ;
}
// remove a trigger from a list
void eventRemoveTriggerFromList ( ACTIVE_TRIGGER * * ppsList ,
SCRIPT_CONTEXT * psContext ,
SDWORD event , SDWORD * pTrigger )
{
ACTIVE_TRIGGER * psCurr , * psPrev = NULL ;
if ( ( ( * ppsList ) ! = NULL ) & &
( * ppsList ) - > event = = event & &
( * ppsList ) - > psContext = = psContext )
{
if ( ( * ppsList ) - > type = = TR_PAUSE )
{
// pause trigger, don't remove it,
// just note the type for when the pause finishes
( * ppsList ) - > trigger = ( SWORD ) * pTrigger ;
* pTrigger = - 1 ;
}
else
{
psCurr = * ppsList ;
* ppsList = ( * ppsList ) - > psNext ;
HEAP_FREE ( psTrigHeap , psCurr ) ;
}
}
else
{
for ( psCurr = * ppsList ; psCurr ; psCurr = psCurr - > psNext )
{
if ( psCurr - > event = = event & &
psCurr - > psContext = = psContext )
{
break ;
}
psPrev = psCurr ;
}
if ( psCurr & & psCurr - > type = = TR_PAUSE )
{
// pause trigger, don't remove it,
// just note the type for when the pause finishes
psCurr - > trigger = ( SWORD ) * pTrigger ;
* pTrigger = - 1 ;
}
else if ( psCurr )
{
psPrev - > psNext = psCurr - > psNext ;
HEAP_FREE ( psTrigHeap , psCurr ) ;
}
}
}
// Change the trigger assigned to an event - to be called from script functions
BOOL eventSetTrigger ( void )
{
ACTIVE_TRIGGER * psTrigger ;
UDWORD event ;
SDWORD trigger ;
SCRIPT_CONTEXT * psContext ;
if ( ! stackPopParams ( 2 , VAL_EVENT , & event , VAL_TRIGGER , & trigger ) )
{
return FALSE ;
}
DB_TRACE ( ( " eventSetTrigger %s %s \n " ,
eventGetEventID ( psFiringTrigger - > psContext - > psCode , event ) ,
eventGetTriggerID ( psFiringTrigger - > psContext - > psCode , trigger ) ) , 2 ) ;
// See if this is the event that is running
psContext = psFiringTrigger - > psContext ;
if ( psFiringTrigger - > event = = event )
{
triggerChanged = TRUE ;
}
else
{
// Remove any old trigger from the list
eventRemoveTriggerFromList ( & psTrigList , psContext , event , & trigger ) ;
eventRemoveTriggerFromList ( & psCallbackList , psContext , event , & trigger ) ;
eventRemoveTriggerFromList ( & psAddedTriggers , psContext , event , & trigger ) ;
/* if (psTrigList &&
psTrigList - > event = = event & &
psTrigList - > psContext = = psContext )
{
if ( psTrigList - > type = = TR_PAUSE )
{
// pause trigger, don't remove it,
// just note the type for when the pause finishes
psTrigList - > trigger = ( SWORD ) trigger ;
trigger = - 1 ;
}
else
{
psCurr = psTrigList ;
psTrigList = psTrigList - > psNext ;
HEAP_FREE ( psTrigHeap , psCurr ) ;
}
}
else
{
for ( psCurr = psTrigList ; psCurr ; psCurr = psCurr - > psNext )
{
if ( psCurr - > event = = event & &
psTrigList - > psContext = = psContext )
{
break ;
}
psPrev = psCurr ;
}
if ( psCurr & & psCurr - > type = = TR_PAUSE )
{
// pause trigger, don't remove it,
// just note the type for when the pause finishes
psCurr - > trigger = ( SWORD ) trigger ;
trigger = - 1 ;
}
else if ( psCurr )
{
psPrev - > psNext = psCurr - > psNext ;
HEAP_FREE ( psTrigHeap , psCurr ) ;
}
}
// Remove any old callback trigger from the list
if ( psCallbackList & & psCallbackList - > event = = event & &
psCallbackList - > psContext = = psContext )
{
psCurr = psCallbackList ;
psCallbackList = psCallbackList - > psNext ;
HEAP_FREE ( psTrigHeap , psCurr ) ;
}
else
{
for ( psCurr = psCallbackList ; psCurr ; psCurr = psCurr - > psNext )
{
if ( psCurr - > psContext = = psContext & &
psCurr - > event = = event )
{
break ;
}
psPrev = psCurr ;
}
if ( psCurr )
{
psPrev - > psNext = psCurr - > psNext ;
HEAP_FREE ( psTrigHeap , psCurr ) ;
}
} */
}
// Create a new trigger if necessary
if ( trigger > = 0 )
{
if ( ! eventInitTrigger ( & psTrigger , psFiringTrigger - > psContext ,
event , trigger , updateTime ) )
{
return FALSE ;
}
psTrigger - > psNext = psAddedTriggers ;
psAddedTriggers = psTrigger ;
}
return TRUE ;
}
// set the event tracing level - to be called from script functions
BOOL eventSetTraceLevel ( void )
{
SDWORD level ;
if ( ! stackPopParams ( 1 , VAL_INT , & level ) )
{
return FALSE ;
}
if ( level < 0 )
{
level = 0 ;
}
if ( level > 3 )
{
level = 3 ;
}
eventTraceLevel = level ;
return TRUE ;
}
2006-08-19 06:26:11 -07:00
//reset local vars
BOOL resetLocalVars ( SCRIPT_CODE * psCode , UDWORD EventIndex )
{
2006-08-22 07:28:49 -07:00
2006-08-19 06:26:11 -07:00
SDWORD i ;
2006-08-22 07:28:49 -07:00
if ( EventIndex > = psCode - > numEvents )
2006-08-19 06:26:11 -07:00
{
2006-08-21 14:20:17 -07:00
if ( psCode - > psDebug ! = NULL )
debug ( LOG_ERROR , " resetLocalVars: wrong event index: %d (Event name: %s, total events count = %d, stack depth = %d) " , EventIndex , eventGetEventID ( psCode , EventIndex ) , psCode - > numEvents , GetCallDepth ( ) ) ;
else
debug ( LOG_ERROR , " resetLocalVars: wrong event index: %d (total events count = %d, stack depth = %d) " , EventIndex , psCode - > numEvents , GetCallDepth ( ) ) ;
2006-08-19 06:26:11 -07:00
return FALSE ;
}
for ( i = 0 ; i < psCode - > numLocalVars [ EventIndex ] ; i + + )
{
//Initialize main value
if ( psCode - > ppsLocalVarVal [ EventIndex ] [ i ] . type = = VAL_STRING )
{
//debug(LOG_ERROR , "resetLocalVars: String type is not implemented");
psCode - > ppsLocalVarVal [ EventIndex ] [ i ] . v . sval = ( char * ) MALLOC ( MAXSTRLEN ) ;
strcpy ( psCode - > ppsLocalVarVal [ EventIndex ] [ i ] . v . sval , " \0 " ) ;
}
else
{
psCode - > ppsLocalVarVal [ EventIndex ] [ i ] . v . ival = 0 ;
}
/* only group (!) must be re-created each time */
if ( psCode - > ppsLocalVarVal [ EventIndex ] [ i ] . type = = ST_GROUP )
{
debug ( LOG_SCRIPT , " resetLocalVars - created " ) ;
2006-08-22 07:28:49 -07:00
2006-08-19 06:26:11 -07:00
if ( ! asCreateFuncs [ psCode - > ppsLocalVarVal [ EventIndex ] [ i ] . type ] ( & ( psCode - > ppsLocalVarVal [ EventIndex ] [ i ] ) ) )
{
debug ( LOG_ERROR , " asCreateFuncs failed for local var (re-init) " ) ;
return FALSE ;
}
}
}
//debug(LOG_SCRIPT, "Reset local vars for event %d", EventIndex);
return TRUE ;
2006-08-23 05:58:48 -07:00
}