diff --git a/src/game.cpp b/src/game.cpp index e5bad4c6a4e..b24dae91815 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -95,6 +95,7 @@ #include "multigifts.h" #include "wzscriptdebug.h" #include "gamehistorylogger.h" +#include "wzapi.h" #include #if defined(__clang__) @@ -3379,7 +3380,7 @@ bool saveGame(const char *aFileName, GAME_TYPE saveType, bool isAutoSave) size_t fileExtension; char CurrentFileName[PATH_MAX] = {'\0'}; - triggerEvent(TRIGGER_GAME_SAVING); + executeFnAndProcessScriptQueuedRemovals([]() { triggerEvent(TRIGGER_GAME_SAVING); }); ASSERT_OR_RETURN(false, aFileName && strlen(aFileName) > 4, "Bad savegame filename"); sstrcpy(CurrentFileName, aFileName); diff --git a/src/init.cpp b/src/init.cpp index 72db7ea8d5e..dceab8f0cd9 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -99,6 +99,7 @@ #include "seqdisp.h" #include "version.h" #include "hci/teamstrategy.h" +#include "wzapi.h" #include #include @@ -1895,7 +1896,7 @@ bool stageThreeInitialise() if (getLevelLoadType() == GTYPE_SAVE_MIDMISSION || getLevelLoadType() == GTYPE_SAVE_START) { - triggerEvent(TRIGGER_GAME_LOADED); + executeFnAndProcessScriptQueuedRemovals([]() { triggerEvent(TRIGGER_GAME_LOADED); }); } else { @@ -1907,7 +1908,7 @@ bool stageThreeInitialise() triggerEventCheatMode(true); } - triggerEvent(TRIGGER_GAME_INIT); + executeFnAndProcessScriptQueuedRemovals([]() { triggerEvent(TRIGGER_GAME_INIT); }); playerBuiltHQ = structureExists(selectedPlayer, REF_HQ, true, false); } diff --git a/src/loop.cpp b/src/loop.cpp index d618c2e432b..3a1a29deb90 100644 --- a/src/loop.cpp +++ b/src/loop.cpp @@ -491,14 +491,6 @@ void countUpdate(bool synch) } } -template -static void executeFnAndProcessScriptQueuedRemovals(Fn fn) -{ - ASSERT(wzapi::scriptQueuedObjectRemovals().empty(), "Leftover script-queued object removals detected!"); - fn(); - wzapi::processScriptQueuedObjectRemovals(); -} - static void gameStateUpdate() { WZ_PROFILE_SCOPE(gameStateUpdate); @@ -586,7 +578,7 @@ static void gameStateUpdate() missionTimerUpdate(); - proj_UpdateAll(); + executeFnAndProcessScriptQueuedRemovals([]() { proj_UpdateAll(); }); for (FEATURE *psCFeat : apsFeatureLists[0]) { @@ -710,10 +702,16 @@ GAMECODE gameLoop() NETflush(); // Make sure that we aren't waiting too long to send data. } - unsigned before = wzGetTicks(); - GAMECODE renderReturn = renderLoop(); - pie_ScreenFrameRenderEnd(); // must happen here for proper renderBudget calculation - unsigned after = wzGetTicks(); + unsigned before, after; + GAMECODE renderReturn; + executeFnAndProcessScriptQueuedRemovals([&before, &after, &renderReturn]() + { + before = wzGetTicks(); + renderReturn = renderLoop(); + pie_ScreenFrameRenderEnd(); // must happen here for proper renderBudget calculation + after = wzGetTicks(); + }); + #if defined(__EMSCRIPTEN__) lastRenderDelta = (after - before); @@ -769,7 +767,7 @@ void videoLoop() { displayGameOver(getScriptWinLoseVideo() == PLAY_WIN, false); } - triggerEvent(TRIGGER_VIDEO_QUIT); + executeFnAndProcessScriptQueuedRemovals([]() { triggerEvent(TRIGGER_VIDEO_QUIT); }); } } } diff --git a/src/main.cpp b/src/main.cpp index b3d683fb45e..4ba4f3e621e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -116,6 +116,7 @@ #include "wzcrashhandlingproviders.h" #include "wzpropertyproviders.h" #include "3rdparty/gsl_finally.h" +#include "wzapi.h" #if defined(WZ_OS_UNIX) # include @@ -987,7 +988,7 @@ static void startGameLoop() { addMissionTimerInterface(); } - triggerEvent(TRIGGER_START_LEVEL); + executeFnAndProcessScriptQueuedRemovals([]() { triggerEvent(TRIGGER_START_LEVEL); }); screen_disableMapPreview(); if (!bMultiPlayer && getCamTweakOption_AutosavesOnly()) diff --git a/src/mission.cpp b/src/mission.cpp index 547449148fe..cc645b7af48 100644 --- a/src/mission.cpp +++ b/src/mission.cpp @@ -82,6 +82,7 @@ #include "lib/framework/wztime.h" #include "keybind.h" #include "campaigninfo.h" +#include "wzapi.h" #define IDMISSIONRES_TXT 11004 #define IDMISSIONRES_LOAD 11005 @@ -2113,7 +2114,10 @@ void intUpdateTransporterTimer(WIDGET *psWidget, const W_CONTEXT *psContext) if (psTransporter->action == DACTION_TRANSPORTWAITTOFLYIN) { missionFlyTransportersIn(selectedPlayer, false); - triggerEvent(TRIGGER_TRANSPORTER_ARRIVED, psTransporter); + executeFnAndProcessScriptQueuedRemovals([psTransporter]() + { + triggerEvent(TRIGGER_TRANSPORTER_ARRIVED, psTransporter); + }); } } } @@ -2859,7 +2863,7 @@ void missionTimerUpdate() if ((SDWORD)(gameTime - mission.startTime) > mission.time) { //the script can call the end game cos have failed! - triggerEvent(TRIGGER_MISSION_TIMEOUT); + executeFnAndProcessScriptQueuedRemovals([]() { triggerEvent(TRIGGER_MISSION_TIMEOUT); }); } } } diff --git a/src/transporter.cpp b/src/transporter.cpp index 85dd3fca08a..409eb5f085d 100644 --- a/src/transporter.cpp +++ b/src/transporter.cpp @@ -56,6 +56,7 @@ #include "visibility.h" #include "multiplay.h" #include "hci/groups.h" +#include "wzapi.h" //#define IDTRANS_FORM 9000 //The Transporter base form #define IDTRANS_CLOSE 9002 //The close button icon @@ -1280,7 +1281,7 @@ void processLaunchTransporter() //set the data for the transporter timer widgSetUserData(psWScreen, IDTRANTIMER_DISPLAY, (void *)psCurrTransporter); - triggerEvent(TRIGGER_TRANSPORTER_LAUNCH, psCurrTransporter); + executeFnAndProcessScriptQueuedRemovals([]() { triggerEvent(TRIGGER_TRANSPORTER_LAUNCH, psCurrTransporter); }); } } } diff --git a/src/wzapi.cpp b/src/wzapi.cpp index f8065821b04..82d6eb44a0d 100644 --- a/src/wzapi.cpp +++ b/src/wzapi.cpp @@ -4591,7 +4591,7 @@ wzapi::QueuedObjectRemovalsVector& wzapi::scriptQueuedObjectRemovals() { static QueuedObjectRemovalsVector instance = []() { - static constexpr size_t initialCapacity = 16; + static constexpr size_t initialCapacity = 32; QueuedObjectRemovalsVector ret; ret.reserve(initialCapacity); return ret; @@ -4605,6 +4605,11 @@ void wzapi::processScriptQueuedObjectRemovals() for (auto& objWithSfxFlag : queuedObjRemovals) { BASE_OBJECT* psObj = objWithSfxFlag.first; + if (psObj->died) + { + debug(LOG_MSG, "Object %p is already dead, not processing", psObj); + continue; + } if (objWithSfxFlag.second) { switch (psObj->type) diff --git a/src/wzapi.h b/src/wzapi.h index d5216ed347b..6fbeb52b6d9 100644 --- a/src/wzapi.h +++ b/src/wzapi.h @@ -1156,4 +1156,12 @@ namespace wzapi void processScriptQueuedObjectRemovals(); } // namespace wzapi +template +static void executeFnAndProcessScriptQueuedRemovals(Fn fn) +{ + ASSERT(wzapi::scriptQueuedObjectRemovals().empty(), "Leftover script-queued object removals detected!"); + fn(); + wzapi::processScriptQueuedObjectRemovals(); +} + #endif