From 5c3067de6a853351413d965e6764e37889d60d41 Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Mon, 5 May 2025 15:10:38 -0500 Subject: [PATCH 1/2] zNPCSpawner: Matches and additional function definitions --- src/SB/Game/zNPCSpawner.cpp | 283 ++++++++++++++++++++++++++++++++++- src/SB/Game/zNPCSpawner.h | 4 +- src/SB/Game/zNPCTypeCommon.h | 1 + 3 files changed, 280 insertions(+), 8 deletions(-) diff --git a/src/SB/Game/zNPCSpawner.cpp b/src/SB/Game/zNPCSpawner.cpp index 5a89ef58d..c7349973b 100644 --- a/src/SB/Game/zNPCSpawner.cpp +++ b/src/SB/Game/zNPCSpawner.cpp @@ -130,18 +130,287 @@ void zNPCSpawner::Reset() void zNPCSpawner::MapPreferred() { - for (S32 i = 0; i < 0x10; i++) + for (S32 i = 0; i < 16; i++) { SMNPCStatus* npc_stat = &this->npcpool[i]; if (npc_stat->npc != NULL) { - // FIXME - // zMovePoint* sp = (zMovePoint*)npc_stat->npc->FirstAssigned(); - // if (sp != NULL&& /*TODO*/) - // { - // npc_stat->sp_prefer = sp; - // } + zMovePoint* sp = (zMovePoint*)npc_stat->npc->FirstAssigned(); + if (sp != NULL) + { + SMSPStatus* sp_stat = StatForSP(sp, 0); + if (sp_stat != NULL) + { + npc_stat->sp_prefer = sp; + sp_stat->npc_prefer = npc_stat->npc; + } + } + } + } +} + +void zNPCSpawner::Timestep(F32 dt) +{ + if (flg_spawner & 0x8) + { + ChildHeartbeat(dt); + } + + if (flg_spawner & 0x10) + { + ChildCleanup(dt); + } + + if (!(flg_spawner & 0x4)) + { + tmr_wave = -1.0f > tmr_wave - dt ? -1.0f : tmr_wave - dt; + + switch (wavemode) + { + case SM_WAVE_DISCREET: + UpdateDiscreet(dt); + break; + case SM_WAVE_CONTINUOUS: + UpdateContinuous(dt); + break; + } + } +} + +void zNPCSpawner::UpdateDiscreet(F32 dt) +{ + SMSPStatus* spstat = NULL; + + switch (wavestat) + { + case SM_STAT_BEGIN: + FillPending(); + + if (pendlist.cnt > 0) + { + wavestat = SM_STAT_INPROG; + zEntEvent(npc_owner, eEventDuploWaveBegin); + + flg_spawner &= ~0x20; + } + + tmr_wave = tym_delay; + + break; + case SM_STAT_INPROG: + if (pendlist.cnt < 1) + { + wavestat = SM_STAT_MARKTIME; + } + else if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + wavestat = SM_STAT_ABORT; + } + else if (tmr_wave < 0.0f) + { + SMNPCStatus* npcstat = NextPendingNPC(0); + if (npcstat != NULL) + { + spstat = SelectSP(npcstat); + } + + if (!(spstat == NULL)) + { + SpawnBeastie(npcstat, spstat); + } + + tmr_wave = tym_delay * (0.25f * (xurand() - 0.5f)) + tym_delay; + } + + break; + case SM_STAT_MARKTIME: + if (actvlist.cnt < 1) + { + wavestat = SM_STAT_DONE; + } + else if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + wavestat = SM_STAT_ABORT; } + + break; + case SM_STAT_ABORT: + if (actvlist.cnt < 1) + { + wavestat = SM_STAT_DONE; + } + + ClearPending(); + + break; + case SM_STAT_DONE: + if (!(flg_spawner & 0x20)) + { + zEntEvent(npc_owner, eEventDuploWaveComplete); + } + + if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + if (!(flg_spawner & 0x20)) + { + flg_spawner |= 0x20; + + zEntEvent(npc_owner, eEventDuploExpiredMaxNPC); + zEntEvent(npc_owner, eEventDuploSuperDuperDone); + + if (flg_spawner & 0x2) + { + zEntEvent(npc_owner, eEventDuploDuperIsDoner); + } + } + } + else + { + if (flg_spawner & 0x2) + { + if (!(flg_spawner & 0x20)) + { + flg_spawner |= 0x20; + + zEntEvent(npc_owner, eEventDuploSuperDuperDone); + zEntEvent(npc_owner, eEventDuploDuperIsDoner); + } + } + else + { + wavestat = SM_STAT_BEGIN; + } + } + + break; + default: + break; + } +} + +void zNPCSpawner::UpdateContinuous(F32 dt) +{ + SMSPStatus* spstat = NULL; + + switch (wavestat) + { + case SM_STAT_BEGIN: + FillPending(); + + if (pendlist.cnt > 0) + { + wavestat = SM_STAT_INPROG; + zEntEvent(npc_owner, eEventDuploWaveBegin); + + flg_spawner &= ~0x20; + } + + tmr_wave = tym_delay; + + break; + case SM_STAT_INPROG: + if (pendlist.cnt < 1) + { + wavestat = SM_STAT_MARKTIME; + } + else if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + wavestat = SM_STAT_ABORT; + } + else if (tmr_wave < 0.0f) + { + SMNPCStatus* npcstat = NextPendingNPC(0); + if (npcstat != NULL) + { + spstat = SelectSP(npcstat); + } + + if (!(spstat == NULL)) + { + SpawnBeastie(npcstat, spstat); + } + + tmr_wave = tym_delay * (0.25f * (xurand() - 0.5f)) + tym_delay; + } + + break; + // MarkTime case is the significantly different one between this function and UpdateDiscreet + case SM_STAT_MARKTIME: + if (flg_spawner & 0x2) + { + wavestat = SM_STAT_ABORT; + } + else if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + wavestat = SM_STAT_ABORT; + } + else + { + if (tmr_wave < 0.0f) + { + tmr_wave = tym_delay * (0.25f * (xurand() - 0.5f)) + tym_delay; + + ReFillPending(); + + if (pendlist.cnt > 0) + { + wavestat = SM_STAT_INPROG; + } + } + else if (pendlist.cnt > 0) + { + wavestat = SM_STAT_INPROG; + } + } + + break; + case SM_STAT_ABORT: + if (actvlist.cnt < 1) + { + wavestat = SM_STAT_DONE; + } + + ClearPending(); + + break; + case SM_STAT_DONE: + if (!(flg_spawner & 0x20)) + { + zEntEvent(npc_owner, eEventDuploWaveComplete); + } + + if (max_spawn > 0 && !(cnt_spawn < max_spawn)) + { + if (!(flg_spawner & 0x20)) + { + flg_spawner |= 0x20; + + zEntEvent(npc_owner, eEventDuploExpiredMaxNPC); + zEntEvent(npc_owner, eEventDuploSuperDuperDone); + + if (flg_spawner & 0x2) + { + zEntEvent(npc_owner, eEventDuploDuperIsDoner); + } + } + } + else + { + if (flg_spawner & 0x2) + { + if (!(flg_spawner & 0x20)) + { + flg_spawner |= 0x20; + + zEntEvent(npc_owner, eEventDuploSuperDuperDone); + zEntEvent(npc_owner, eEventDuploDuperIsDoner); + } + } + } + + break; + default: + break; } } diff --git a/src/SB/Game/zNPCSpawner.h b/src/SB/Game/zNPCSpawner.h index 615fa42fa..d6e9033c6 100644 --- a/src/SB/Game/zNPCSpawner.h +++ b/src/SB/Game/zNPCSpawner.h @@ -90,16 +90,18 @@ struct zNPCSpawner : RyzMemData // NextPendingNPC. void ClearActive(); void ClearPending(); - SMNPCStatus* NextPendingNPC( S32 arg0 ); + SMNPCStatus* NextPendingNPC(S32 arg0); st_XORDEREDARRAY* FillPending(); st_XORDEREDARRAY* ReFillPending(); void SetNPCStatus(zNPCCommon* npc, en_SM_NPC_STATUS status); SMNPCStatus* StatForNPC(zNPCCommon* npc); + SMSPStatus* StatForSP(zMovePoint* mp, S32 arg0); S32 SpawnBeastie(SMNPCStatus* npcstat, SMSPStatus* spstat); SMNPCStatus* ToastedBeastie(zNPCCommon* npc); void ChildHeartbeat(F32 dt); + void ChildCleanup(F32 dt); }; void zNPCSpawner_Startup(); diff --git a/src/SB/Game/zNPCTypeCommon.h b/src/SB/Game/zNPCTypeCommon.h index 65bf44702..463202dac 100644 --- a/src/SB/Game/zNPCTypeCommon.h +++ b/src/SB/Game/zNPCTypeCommon.h @@ -449,6 +449,7 @@ struct zNPCCommon : xNPCBasic //Size of zNPCCommon: 0x2A0 int (*)(xGoal*, void*, en_trantype*, float, void*), int (*)(xGoal*, void*, en_trantype*, float, void*), int (*)(xGoal*, void*, en_trantype*, float, void*)); + zMovePoint* FirstAssigned(); // defined from zNPCGoalRobo.cpp xVec3* Center(); From dd96425cceb49510c84e63ca2c618d758cdeff00 Mon Sep 17 00:00:00 2001 From: Josh Sanchez Date: Mon, 5 May 2025 15:11:00 -0500 Subject: [PATCH 2/2] Config: Use more VS Code-friendly settings --- .vscode/settings.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 09e36b599..861363e42 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,11 +1,11 @@ { "[c]": { "files.encoding": "utf8", - "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" + "editor.defaultFormatter": "xaver.clang-format" }, "[cpp]": { "files.encoding": "utf8", - "editor.defaultFormatter": "llvm-vs-code-extensions.vscode-clangd" + "editor.defaultFormatter": "xaver.clang-format" }, "[python]": { "editor.defaultFormatter": "ms-python.black-formatter" @@ -19,5 +19,5 @@ ".clangd": "yaml" }, // Disable C/C++ IntelliSense, use clangd instead - "C_Cpp.intelliSenseEngine": "disabled", + "C_Cpp.intelliSenseEngine": "default", }