From fa7ef3df649933929ccf2faffb1020cb20a82c0b Mon Sep 17 00:00:00 2001 From: Maxime Morel Date: Thu, 22 Oct 2026 13:08:51 +0200 Subject: [PATCH] Corpses --- port/src/main.c | 2 ++ src/game/chr.c | 13 +++++++++++++ src/game/chraction.c | 43 +++++++++++++++++++++++++++++++++-------- src/game/gfxmemory.c | 30 ++++++++++++++++++++-------- src/game/setup.c | 14 ++++++++++++++ src/game/wallhitreset.c | 14 ++++++++++++++ src/include/bss.h | 2 ++ src/include/constants.h | 2 ++ 8 files changed, 104 insertions(+), 16 deletions(-) diff --git a/port/src/main.c b/port/src/main.c index c8b959edb..707e4bd85 100644 --- a/port/src/main.c +++ b/port/src/main.c @@ -170,6 +170,8 @@ PD_CONSTRUCTOR static void gameConfigInit(void) configRegisterInt("Game.DisableMpDeathMusic", &g_MusicDisableMpDeath, 0, 1); configRegisterInt("Game.GEMuzzleFlashes", &g_BgunGeMuzzleFlashes, 0, 1); configRegisterInt("Game.MaxExplosions", &g_MaxExplosions, 6, 96); + configRegisterInt("Game.DecalLimitMultiplier", &g_DecalLimitMultiplier, 1, MAX_DECAL_LIMIT_MULTIPLIER); + configRegisterInt("Game.MaxCorpses", &g_MaxCorpses, -1, MAX_CORPSES_LIMIT); // -1 = never fade for (s32 j = 0; j < MAX_PLAYERS; ++j) { const s32 i = j + 1; configRegisterFloat(strFmt("Game.Player%d.FovY", i), &g_PlayerExtCfg[j].fovy, 5.f, 175.f); diff --git a/src/game/chr.c b/src/game/chr.c index c9ba3ed50..e5a662340 100644 --- a/src/game/chr.c +++ b/src/game/chr.c @@ -2633,6 +2633,19 @@ s32 chrTick(struct prop *prop) } #if VERSION >= VERSION_NTSC_1_0 +#ifndef PLATFORM_N64 + if (g_MaxCorpses != 0 && !g_Vars.normmplayerisrunning && needsupdate) { + // Kept corpses are drawn rather than deleted, and don't count towards the visible chr budget + if (chr->actiontype != ACT_DEAD + && (chr->actiontype != ACT_DRUGGEDKO || (chr->chrflags & CHRCFLAG_KEEPCORPSEKO))) { + var8009cdb0++; + + if (var8009cdb0 > 30) { + needsupdate = false; + } + } + } else +#endif if (!g_Vars.normmplayerisrunning && needsupdate) { if (chr->actiontype == ACT_DEAD || (chr->actiontype == ACT_DRUGGEDKO && (chr->chrflags & CHRCFLAG_KEEPCORPSEKO) == 0)) { diff --git a/src/game/chraction.c b/src/game/chraction.c index 1ea0b8b72..94108108c 100644 --- a/src/game/chraction.c +++ b/src/game/chraction.c @@ -7199,7 +7199,14 @@ bool chrTrySurrender(struct chrdata *chr) bool chrFadeOut(struct chrdata *chr) { chrBeginDead(chr); +#ifndef PLATFORM_N64 + // Scripted removals still fade when corpses are kept forever + if (chr->actiontype == ACT_DEAD || chr->actiontype == ACT_DRUGGEDKO) { + chr->act_dead.fadenow = true; + } +#else chrFadeCorpse(chr); +#endif return true; } @@ -8197,6 +8204,12 @@ void chrTickSurrender(struct chrdata *chr) void chrFadeCorpse(struct chrdata *chr) { +#ifndef PLATFORM_N64 + if (g_MaxCorpses < 0 && chr->aibot == NULL) { + return; + } +#endif + if (chr->actiontype == ACT_DEAD || chr->actiontype == ACT_DRUGGEDKO) { chr->act_dead.fadenow = true; } @@ -8204,6 +8217,12 @@ void chrFadeCorpse(struct chrdata *chr) void chrFadeCorpseWhenOffScreen(struct chrdata *chr) { +#ifndef PLATFORM_N64 + if (g_MaxCorpses < 0 && chr->aibot == NULL) { + return; + } +#endif + if (chr->actiontype == ACT_DEAD) { chr->act_dead.fadewheninvis = true; } @@ -13459,6 +13478,10 @@ void cutsceneStart(u32 ailistid) * - Run BG scripts * - Choose which corpses to fade */ +// 0 keeps the original corpse limits, -1 never fades corpses, otherwise the number of corpses kept on screen, +// off screen and spawned +s32 g_MaxCorpses = 0; + void chraTickBg(void) { s32 i; @@ -13470,10 +13493,10 @@ void chraTickBg(void) #if VERSION >= VERSION_NTSC_1_0 s32 spawnslen; #endif - struct chrdata *onscreen[5]; - struct chrdata *offscreen[5]; + struct chrdata *onscreen[MAX_CORPSES_LIMIT]; + struct chrdata *offscreen[MAX_CORPSES_LIMIT]; #if VERSION >= VERSION_NTSC_1_0 - struct chrdata *spawns[10]; + struct chrdata *spawns[MAX_CORPSES_LIMIT]; #endif s32 writeindex; s32 maxdeadonscreen; @@ -13599,7 +13622,7 @@ void chraTickBg(void) spawns[spawnslen] = chr; spawnslen++; - if (spawnslen >= 10) { + if (spawnslen >= (g_MaxCorpses > 0 ? g_MaxCorpses : 10)) { writeindex = rngRandom() % spawnslen; chrFadeCorpse(spawns[writeindex]); spawns[writeindex] = spawns[spawnslen - 1]; @@ -13620,12 +13643,16 @@ void chraTickBg(void) // 5 chrs (alive or dead) to keep the number of polygons low. maxdeadonscreen = 5 - numaliveonscreen; + if (g_MaxCorpses > 0) { + maxdeadonscreen = g_MaxCorpses; + } + // If the game is lagging, take the number of 60ths over 6 since the // previous frame and reduce the limit by that amount. So if it's been, say, // 8 60ths since the last frame then the max corpses will be reduced by 2. // This is why corpses are more likely to fade on screen when you change // weapons - the lag spike from changing guns triggers a lower corpse limit. - if (g_Vars.lvupdate60 > 6) { + if (g_Vars.lvupdate60 > 6 && g_MaxCorpses == 0) { maxdeadonscreen = maxdeadonscreen - g_Vars.lvupdate60 + 6; } @@ -13651,7 +13678,7 @@ void chraTickBg(void) #else // Decide which corpses to fade. // NTSC Beta implements its engagement counter here. - if (numdeadonscreen) { + if (numdeadonscreen && g_MaxCorpses >= 0) { numdeadonscreen = 0; #if VERSION >= VERSION_NTSC_1_0 onscreenlen = 0; @@ -13690,7 +13717,7 @@ void chraTickBg(void) onscreen[onscreenlen] = chr; onscreenlen++; - if (onscreenlen >= (VERSION >= VERSION_NTSC_1_0 ? 2 : 3)) { + if (onscreenlen >= (g_MaxCorpses > 0 ? g_MaxCorpses : (VERSION >= VERSION_NTSC_1_0 ? 2 : 3))) { writeindex = rngRandom() % onscreenlen; chrFadeCorpseWhenOffScreen(onscreen[writeindex]); onscreen[writeindex] = onscreen[onscreenlen - 1]; @@ -13705,7 +13732,7 @@ void chraTickBg(void) offscreenlen++; // Allow up to 5 corpses off-screen - if (offscreenlen >= (VERSION >= VERSION_NTSC_1_0 ? 5 : 6)) { + if (offscreenlen >= (g_MaxCorpses > 0 ? g_MaxCorpses : (VERSION >= VERSION_NTSC_1_0 ? 5 : 6))) { writeindex = rngRandom() % offscreenlen; if (offscreen[writeindex]->actiontype != ACT_DEAD) { diff --git a/src/game/gfxmemory.c b/src/game/gfxmemory.c index be47a8fa5..4843d7963 100644 --- a/src/game/gfxmemory.c +++ b/src/game/gfxmemory.c @@ -111,15 +111,29 @@ void gfxReset(void) g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1] = strtol(argFindByPrefix(1, "-mvtx"), NULL, 0) * 1024; } - // %d Players : Allocating %d bytes for master dl's\n - g_GfxBuffers[0] = mempAlloc(g_GfxSizesByPlayerCount[PLAYERCOUNT() - 1] * NUM_GFXTASKS, MEMPOOL_STAGE); - g_GfxBuffers[1] = g_GfxBuffers[0] + g_GfxSizesByPlayerCount[PLAYERCOUNT() - 1]; - g_GfxBuffers[2] = g_GfxBuffers[1] + g_GfxSizesByPlayerCount[PLAYERCOUNT() - 1]; + { + u32 gfxsize = g_GfxSizesByPlayerCount[PLAYERCOUNT() - 1]; + u32 vtxsize = g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1]; - // Allocating %d bytes for mtxvtx space\n - g_VtxBuffers[0] = mempAlloc(g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1] * NUM_GFXTASKS, MEMPOOL_STAGE); - g_VtxBuffers[1] = g_VtxBuffers[0] + g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1]; - g_VtxBuffers[2] = g_VtxBuffers[1] + g_VtxSizesByPlayerCount[PLAYERCOUNT() - 1]; +#ifndef PLATFORM_N64 + // Each extra rendered decal needs display list commands and per-frame colours + if (g_DecalLimitMultiplier > 1) { + u32 extradecals = 360 * (g_DecalLimitMultiplier - 1); + gfxsize = ALIGN16(gfxsize + extradecals * 6 * sizeof(Gfx)); + vtxsize = ALIGN16(vtxsize + extradecals * 32); + } +#endif + + // %d Players : Allocating %d bytes for master dl's\n + g_GfxBuffers[0] = mempAlloc(gfxsize * NUM_GFXTASKS, MEMPOOL_STAGE); + g_GfxBuffers[1] = g_GfxBuffers[0] + gfxsize; + g_GfxBuffers[2] = g_GfxBuffers[1] + gfxsize; + + // Allocating %d bytes for mtxvtx space\n + g_VtxBuffers[0] = mempAlloc(vtxsize * NUM_GFXTASKS, MEMPOOL_STAGE); + g_VtxBuffers[1] = g_VtxBuffers[0] + vtxsize; + g_VtxBuffers[2] = g_VtxBuffers[1] + vtxsize; + } g_GfxActiveBufferIndex = 0; g_GfxRequestedDisplayList = false; diff --git a/src/game/setup.c b/src/game/setup.c index 568984461..ffbe86ea0 100644 --- a/src/game/setup.c +++ b/src/game/setup.c @@ -1400,6 +1400,14 @@ void setupLoadFiles(s32 stagenum) numobjs += g_Vars.numaibuddies; // the buddy's weapon } +#ifndef PLATFORM_N64 + // Kept corpses hold on to their slots, so reserve extra ones for spawned chrs and their weapons + if (!g_Vars.normmplayerisrunning) { + numchrs += g_MaxCorpses < 0 ? MAX_CORPSES_LIMIT : g_MaxCorpses; + numobjs += g_MaxCorpses < 0 ? MAX_CORPSES_LIMIT : g_MaxCorpses; + } +#endif + numobjs += setupCountCommandType(OBJTYPE_WEAPON); numobjs += setupCountCommandType(OBJTYPE_KEY); numobjs += setupCountCommandType(OBJTYPE_HAT); @@ -1531,6 +1539,12 @@ void setupCreateProps(s32 stagenum) numchrs += g_Vars.numaibuddies; } +#ifndef PLATFORM_N64 + if (!g_Vars.normmplayerisrunning) { + numchrs += g_MaxCorpses < 0 ? MAX_CORPSES_LIMIT : g_MaxCorpses; + } +#endif + chrmgrConfigure(numchrs); } else { chrmgrConfigure(0); diff --git a/src/game/wallhitreset.c b/src/game/wallhitreset.c index 6ca25d69f..9774dbc4a 100644 --- a/src/game/wallhitreset.c +++ b/src/game/wallhitreset.c @@ -20,6 +20,7 @@ u32 var8009cc6c; s32 g_WallhitsCriticalSpareLimit; s32 g_WallhitsGoalSpareLimit; f32 g_WallhitTargetBloodRatio; +s32 g_DecalLimitMultiplier = 1; /** * Initialises an array of room numbers and a linked list of structs. @@ -81,6 +82,19 @@ void wallhitReset(void) break; } +#ifndef PLATFORM_N64 + if (g_DecalLimitMultiplier > 1) { + g_WallhitsMax *= g_DecalLimitMultiplier; + g_MinPropWallhits *= g_DecalLimitMultiplier; + g_MaxPropWallhits *= g_DecalLimitMultiplier; + g_MinBgWallhitsPerRoom *= g_DecalLimitMultiplier; + g_MaxBgWallhitsPerRoom *= g_DecalLimitMultiplier; + var8009cc6c *= g_DecalLimitMultiplier; + g_WallhitsCriticalSpareLimit *= g_DecalLimitMultiplier; + g_WallhitsGoalSpareLimit *= g_DecalLimitMultiplier; + } +#endif + g_WallhitCountsPerRoom = NULL; g_WallhitsNumSettled = 0; g_WallhitsNumFree = 0; diff --git a/src/include/bss.h b/src/include/bss.h index 63dc22fb9..634b09da5 100644 --- a/src/include/bss.h +++ b/src/include/bss.h @@ -201,6 +201,8 @@ extern u32 g_SkyStageNum; extern bool g_SkyLightningActive; extern struct explosion *g_Explosions; extern s32 g_MaxExplosions; +extern s32 g_DecalLimitMultiplier; +extern s32 g_MaxCorpses; extern struct smoke *g_Smokes; extern s32 g_MaxSmokes; extern Mtx var800a3448; diff --git a/src/include/constants.h b/src/include/constants.h index 2457a7f4a..bf472b672 100644 --- a/src/include/constants.h +++ b/src/include/constants.h @@ -28,6 +28,8 @@ #define MAX_SQUADRONS 16 #define MAX_TEAMS 8 #define MAX_EXPLOSIONS_DEFAULT 6 +#define MAX_DECAL_LIMIT_MULTIPLIER 10 +#define MAX_CORPSES_LIMIT 64 #define NUM_BOTDIFFS 6 #define NUM_CYCLEABLE_WEAPONS 45