From b7a3d4e5083f68dd345992d371c1fbf0512f8b53 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 6 Apr 2024 21:52:55 -0700 Subject: [PATCH 1/3] Splitscreen GP: fix player positions if GAME OVERed player is present - If splitscreen player spawns GAME OVERed, make absolute certain they appear in last place and don't affect any higher positions --- src/p_user.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_user.c b/src/p_user.c index f9aa4bbfb..3348a312e 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -4169,6 +4169,7 @@ void P_PlayerThink(player_t *player) player->respawn.pointz = player->mo->z; player->pflags |= PF_LOSTLIFE|PF_ELIMINATED|PF_NOCONTEST; + player->realtime = UINT32_MAX; K_InitPlayerTally(player); } From 44ea14104e2417cfe91abf242288e2be726b3616 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 6 Apr 2024 22:19:32 -0700 Subject: [PATCH 2/3] Add G_GametypeAllowsRetrying, split away from G_GametypeUsesLives - Cases for lives specifically and not retrying use G_GametypeUsesLives - Such as HUD elements and GAME OVER - Cases for retrying and losing lives use G_GametypeAllowsRetrying - Such as GP bonus rounds --- src/g_game.c | 30 ++++++++++++++++++++++++------ src/g_game.h | 1 + src/k_grandprix.c | 2 +- src/lua_baselib.c | 9 +++++++++ src/menus/transient/pause-game.c | 4 ++-- src/p_user.c | 6 +++--- 6 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index e2eec43a7..509691f56 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -3077,7 +3077,7 @@ void G_BeginLevelExit(void) g_exit.losing = true; g_exit.retry = false; - if (!G_GametypeUsesLives() || skipstats != 0) + if (!G_GametypeAllowsRetrying() || skipstats != 0) { g_exit.losing = false; // never force a retry } @@ -3108,11 +3108,11 @@ void G_BeginLevelExit(void) { if (playeringame[i] && !players[i].spectator && !players[i].bot) { - if (players[i].lives > 0) - { - g_exit.retry = true; - break; - } + if (G_GametypeUsesLives() && players[i].lives <= 0) + continue; + + g_exit.retry = true; + break; } } } @@ -3445,6 +3445,24 @@ boolean G_GametypeUsesLives(void) if (modeattacking) // NOT in Record Attack return false; + if (grandprixinfo.gp == true) // In Grand Prix + return true; + + return false; +} + +// +// G_GametypeAllowsRetrying +// +// Returns true if retrying is allowed at all. +// (Retrying may still not be possible if the player doesn't +// have enough lives.) +// +boolean G_GametypeAllowsRetrying(void) +{ + if (modeattacking) // Attack modes have their own retry system + return false; + if ((grandprixinfo.gp == true) // In Grand Prix && grandprixinfo.eventmode != GPEVENT_BONUS) // NOT in bonus round { diff --git a/src/g_game.h b/src/g_game.h index 019172d7e..16676cf33 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -198,6 +198,7 @@ INT32 G_GetGametypeByName(const char *gametypestr); INT32 G_GuessGametypeByTOL(UINT32 tol); boolean G_GametypeUsesLives(void); +boolean G_GametypeAllowsRetrying(void); boolean G_GametypeHasTeams(void); boolean G_GametypeHasSpectators(void); INT16 G_SometimesGetDifferentEncore(void); diff --git a/src/k_grandprix.c b/src/k_grandprix.c index b9e0168e8..297d5d3ed 100644 --- a/src/k_grandprix.c +++ b/src/k_grandprix.c @@ -855,7 +855,7 @@ void K_FakeBotResults(player_t *bot) --------------------------------------------------*/ void K_PlayerLoseLife(player_t *player) { - if (!G_GametypeUsesLives()) + if (!G_GametypeUsesLives() || !G_GametypeAllowsRetrying()) { return; } diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 18d2dc2c7..181a80b45 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -2916,6 +2916,14 @@ static int lib_gGametypeUsesLives(lua_State *L) return 1; } +static int lib_gGametypeAllowsRetrying(lua_State *L) +{ + //HUDSAFE + INLEVEL + lua_pushboolean(L, G_GametypeAllowsRetrying()); + return 1; +} + static int lib_gGametypeHasTeams(lua_State *L) { //HUDSAFE @@ -3795,6 +3803,7 @@ static luaL_Reg lib[] = { {"G_SetCustomExitVars",lib_gSetCustomExitVars}, {"G_ExitLevel",lib_gExitLevel}, {"G_GametypeUsesLives",lib_gGametypeUsesLives}, + {"G_GametypeAllowsRetrying",lib_gGametypeAllowsRetrying}, {"G_GametypeHasTeams",lib_gGametypeHasTeams}, {"G_GametypeHasSpectators",lib_gGametypeHasSpectators}, {"G_TicsToHours",lib_gTicsToHours}, diff --git a/src/menus/transient/pause-game.c b/src/menus/transient/pause-game.c index 6575a9522..7e283504e 100644 --- a/src/menus/transient/pause-game.c +++ b/src/menus/transient/pause-game.c @@ -197,11 +197,11 @@ void M_OpenPauseMenu(void) { retryallowed = true; } - else if (G_GametypeUsesLives()) + else if (G_GametypeAllowsRetrying()) { for (i = 0; i <= splitscreen; i++) { - if (players[g_localplayers[i]].lives <= 1) + if (G_GametypeUsesLives() && players[g_localplayers[i]].lives <= 1) continue; retryallowed = true; break; diff --git a/src/p_user.c b/src/p_user.c index 3348a312e..94451957b 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -684,7 +684,7 @@ void P_EndingMusic(void) { jingle = "RETIRE"; - if (G_GametypeUsesLives() == true) + if (G_GametypeAllowsRetrying() == true) { // A retry will be happening nointer = true; @@ -694,7 +694,7 @@ void P_EndingMusic(void) { jingle = "_lose"; - if (G_GametypeUsesLives() == true) + if (G_GametypeAllowsRetrying() == true) { // A retry will be happening nointer = true; @@ -1245,7 +1245,7 @@ void P_DoPlayerExit(player_t *player, pflags_t flags) const boolean losing = K_IsPlayerLosing(player); // HEY!!!! Set it AFTER K_UpdateAllPlayerPositions!!!! const boolean specialout = (specialstageinfo.valid == true && losing == true); - if (G_GametypeUsesLives() && losing) + if (losing) { // Remove a life from the losing player K_PlayerLoseLife(player); From e8c84cb0130ba4e67edc60e3cefdbf92bc8803f1 Mon Sep 17 00:00:00 2001 From: James R Date: Sun, 7 Apr 2024 02:20:59 -0700 Subject: [PATCH 3/3] Splitscreen GP: timer is considered 000 for GAME OVERed players --- src/hud/timer.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/hud/timer.cpp b/src/hud/timer.cpp index 490dcae8d..d37f79d7c 100644 --- a/src/hud/timer.cpp +++ b/src/hud/timer.cpp @@ -26,6 +26,11 @@ constexpr INT32 kHudFlags = V_HUDTRANS | V_SLIDEIN; tic_t player_timer(const player_t* player) { + if (player->realtime == UINT32_MAX) + { + return 0; + } + return K_TranslateTimer(player->realtime, 0, nullptr); }