// 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; // Run the trigger if (eventFireTrigger(psCurr)) // This might mark the trigger for deletion { if (psCurr->deactivated || 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; } } } // Delete marked triggers now eventPruneLists(); // 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; }
// Activate a callback trigger void eventFireCallbackTrigger(TRIGGER_TYPE callback) { ACTIVE_TRIGGER *psPrev = NULL, *psCurr, *psNext; TRIGGER_DATA *psTrigDat; BOOL fired; if (interpProcessorActive()) { ASSERT(false, "eventFireCallbackTrigger: script interpreter is already running"); return; } //this can be called from eventProcessTriggers and so will wipe out all the current added ones //psAddedTriggers = NULL; for (psCurr = psCallbackList; psCurr && psCurr->type <= (int)callback; psCurr = psNext) { psNext = psCurr->psNext; if (psCurr->type == (int)callback) { // see if the callback should be fired fired = false; if (psCurr->type != TR_PAUSE) { ASSERT(psCurr->trigger >= 0 && psCurr->trigger < psCurr->psContext->psCode->numTriggers, "eventFireCallbackTrigger: invalid trigger number"); psTrigDat = psCurr->psContext->psCode->psTriggerData + psCurr->trigger; } else { psTrigDat = NULL; } if (psTrigDat && psTrigDat->code) { if (!interpRunScript(psCurr->psContext, IRT_TRIGGER, psCurr->trigger, 0)) { ASSERT(false, "eventFireCallbackTrigger: trigger %s: code failed", eventGetTriggerID(psCurr->psContext->psCode, psCurr->trigger)); psPrev = psCurr; continue; } if (!stackPopParams(1, VAL_BOOL, &fired)) { ASSERT(false, "eventFireCallbackTrigger: trigger %s: code failed", eventGetTriggerID(psCurr->psContext->psCode, psCurr->trigger)); psPrev = psCurr; continue; } } else { fired = true; } // run the event if (fired) { DB_TRIGINF(psCurr,1); DB_TRACE(" fired",1); // remove the trigger from the list if (psPrev == NULL) { psCallbackList = psCallbackList->psNext; } else { psPrev->psNext = psNext; } psFiringTrigger = psCurr; if (!interpRunScript(psCurr->psContext, IRT_EVENT, psCurr->event, psCurr->offset)) // this could set psCurr->deactivated { ASSERT(false, "eventFireCallbackTrigger: event %s: code failed", eventGetEventID(psCurr->psContext->psCode, psCurr->event)); } if (psCurr->deactivated) { // don't need to add the trigger again - just free it eventFreeTrigger(psCurr); } else { // make sure the trigger goes back into the system psCurr->psNext = psAddedTriggers; psAddedTriggers = psCurr; } } else { psPrev = psCurr; } } else { psPrev = psCurr; } } // Delete marked triggers now eventPruneLists(); // 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 an object from the event system void eventRemoveContext(SCRIPT_CONTEXT *psContext) { ACTIVE_TRIGGER *psCurr, *psPrev, *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 (psPrev = NULL, psCurr = psTrigList; psCurr; psCurr = psNext) { psNext = psCurr->psNext; if (psCurr->psContext == psContext) { eventFreeTrigger(psCurr); if (psPrev) { 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 (psPrev = NULL, psCurr = psCallbackList; psCurr; psCurr = psNext) { psNext = psCurr->psNext; if (psCurr->psContext == psContext) { eventFreeTrigger(psCurr); if (psPrev) { 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; ASSERT( psCChunk != NULL, "eventRemoveContext: not enough value chunks" ); } 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; // FIXME FIXME FIXME - this is commented away because it made loading // different savegames many times crash for inexplicable reasons. It // will probably leak memory, though! /* for(i=0;i < CONTEXT_VALS ; i++) { if (psCChunk->asVals[i].type == VAL_STRING && psCChunk->asVals[i].v.sval) { free(psCChunk->asVals[i].v.sval); psCChunk->asVals[i].v.sval = NULL; } }*/ free(psCChunk); } psContext->psGlobals = NULL; // Remove it from the context list if (psContext == psContList) { psCCont = psContList; psContList = psContList->psNext; free(psCCont); } else { for(psCCont = psContList; psCCont && psCCont!=psContext; psCCont = psCCont->psNext) { psPCont = psCCont; } if (psCCont) { psPCont->psNext = psCCont->psNext; free(psContext); } else { ASSERT( false, "eventRemoveContext: context not found" ); } } }