From 1e49453d78de33477fd481450c3d2fe472b15cde Mon Sep 17 00:00:00 2001 From: Antonio Martinez Date: Mon, 25 Aug 2025 06:24:07 -0400 Subject: [PATCH] Fix double-exit conditions WITHOUT changing checkpoint count --- src/d_player.h | 2 ++ src/g_game.c | 8 ++++++++ src/k_pwrlv.c | 14 +++++++++++--- src/p_saveg.cpp | 4 ++++ src/p_spec.c | 2 -- 5 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/d_player.h b/src/d_player.h index 62c30d5f5..cdcaa6562 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -900,6 +900,8 @@ struct player_t boolean pullup; // True if the player is attached to a pullup hook + boolean finalized; // Did PWR finalize already, don't repeat it even if exit conditions are weird. + tic_t ebrakefor; // Ebrake timer, used for visuals. UINT16 faultflash; // Used for misc FAULT visuals diff --git a/src/g_game.c b/src/g_game.c index 2f84b4ef0..882fd86dc 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2290,6 +2290,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) boolean cangrabitems; + boolean finalized; + SINT8 xtralife; uint8_t public_key[PUBKEYLENGTH]; @@ -2482,6 +2484,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) bigwaypointgap = 0; duelscore = 0; + finalized = false; + tallyactive = false; cangrabitems = 0; @@ -2518,6 +2522,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) gradingfactor = players[player].gradingfactor; gradingpointnum = players[player].gradingpointnum; + finalized = players[player].finalized; + roundscore = players[player].roundscore; exiting = players[player].exiting; @@ -2668,6 +2674,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps) p->botvars.foe = botfoe; p->xtralife = xtralife; + p->finalized = finalized; + // SRB2kart p->itemtype = itemtype; p->itemamount = itemamount; diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index 9ce2a2f72..b2571bf74 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -210,6 +210,13 @@ void K_UpdatePowerLevels(player_t *player, UINT8 gradingpoint, boolean forfeit) return; } + // Probably being called from some stray codepath or a double exit. + // We have already finished calculating PWR, don't touch anything! + if (player->finalized) + { + return; + } + CONS_Debug(DBG_PWRLV, "\n========\n"); CONS_Debug(DBG_PWRLV, "* Power Level change for player %s (CHECKPOINT %d) *\n", player_names[playerNum], gradingpoint); CONS_Debug(DBG_PWRLV, "========\n"); @@ -383,6 +390,9 @@ void K_UpdatePowerLevels(player_t *player, UINT8 gradingpoint, boolean forfeit) void K_UpdatePowerLevelsFinalize(player_t *player, boolean onForfeit) { + if (player->finalized) + return; + // Finalize power level increments for any checkpoints not yet calculated. // For spectate / quit / NO CONTEST INT16 checksleft = 0; @@ -405,9 +415,7 @@ void K_UpdatePowerLevelsFinalize(player_t *player, boolean onForfeit) K_UpdatePowerLevels(player, player->gradingpointnum + i, onForfeit); } - // Dubious, but if this is called multiple times better to not touch PWR? - // Only direct side effets should be on checkpoint cross... - player->gradingpointnum = K_GetNumGradingPoints(); + player->finalized = true; } INT16 K_FinalPowerIncrement(player_t *player, INT16 yourPower, INT16 baseInc) diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index b0de9a36d..d4feebbef 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -610,6 +610,8 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT8(save->p, players[i].pullup); + WRITEUINT8(save->p, players[i].finalized); + WRITEUINT32(save->p, players[i].ebrakefor); WRITEUINT32(save->p, players[i].roundscore); @@ -1283,6 +1285,8 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].pullup = READUINT8(save->p); + players[i].finalized = READUINT8(save->p); + players[i].ebrakefor = READUINT32(save->p); players[i].roundscore = READUINT32(save->p); diff --git a/src/p_spec.c b/src/p_spec.c index a88dec1da..d312b6d1f 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2129,8 +2129,6 @@ static void K_HandleLapIncrement(player_t *player) UINT16 oldexp = player->exp; K_CheckpointCrossAward(player); - - // Update power levels for this lap. K_UpdatePowerLevels(player, player->gradingpointnum, false); if (player->exp > oldexp)