From b60df7d4860616bc5abf4e749aaddc8817a36052 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Sun, 10 Mar 2024 20:55:15 -0700 Subject: [PATCH 1/9] WIP: Skip Tally --- src/k_tally.cpp | 16 +++++++++++++++- src/k_tally.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/k_tally.cpp b/src/k_tally.cpp index 53a0fbb7f..273b91dc2 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -35,6 +35,7 @@ #include "st_stuff.h" #include "r_fps.h" #include "g_party.h" +#include "g_input.h" boolean level_tally_t::UseBonuses(void) { @@ -311,6 +312,7 @@ void level_tally_t::Init(player_t *player) laps = totalLaps = 0; points = pointLimit = 0; powerStones = 0; + canFastForward = false; rank = GRADE_INVALID; @@ -1392,7 +1394,19 @@ void K_InitPlayerTally(player_t *player) void K_TickPlayerTally(player_t *player) { - player->tally.Tick(); + boolean fastForwardInput = G_PlayerInputDown(G_LocalSplitscreenPartyPosition(player - players), gc_a, 0); + + if (fastForwardInput && player->tally.state == TALLY_ST_DONE) + player->tally.delay = std::min(player->tally.delay, TICRATE); + + do + player->tally.Tick(); + while (player->tally.state != TALLY_ST_DONE && (fastForwardInput && player->tally.canFastForward)); + + if (!fastForwardInput) + player->tally.canFastForward = true; + else + player->tally.canFastForward = false; } void K_DrawPlayerTally(void) diff --git a/src/k_tally.h b/src/k_tally.h index 9f7c3d866..407f2b5f8 100644 --- a/src/k_tally.h +++ b/src/k_tally.h @@ -96,6 +96,7 @@ struct level_tally_t UINT8 xtraBlink; boolean showGrade; boolean done; + boolean canFastForward; #ifdef __cplusplus boolean UseBonuses(void); From 551acaf06ef2dda74136167ee83ac839c05bd238 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Mon, 11 Mar 2024 18:57:16 -0700 Subject: [PATCH 2/9] Refine tally skip --- src/k_tally.cpp | 30 +++++++++++++++++++++++------- src/k_tally.h | 2 +- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/k_tally.cpp b/src/k_tally.cpp index 273b91dc2..c65831076 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -312,7 +312,7 @@ void level_tally_t::Init(player_t *player) laps = totalLaps = 0; points = pointLimit = 0; powerStones = 0; - canFastForward = false; + releasedFastForward = false; rank = GRADE_INVALID; @@ -1395,18 +1395,34 @@ void K_InitPlayerTally(player_t *player) void K_TickPlayerTally(player_t *player) { boolean fastForwardInput = G_PlayerInputDown(G_LocalSplitscreenPartyPosition(player - players), gc_a, 0); + boolean allowFastForward = player->tally.state > TALLY_ST_GOTTHRU_SLIDEIN + && player->tally.releasedFastForward + && grandprixinfo.gp + && player->tally.state != TALLY_ST_DONE; + + if (fastForwardInput && allowFastForward) + { + do + player->tally.Tick(); + while (player->tally.state != TALLY_ST_DONE); - if (fastForwardInput && player->tally.state == TALLY_ST_DONE) player->tally.delay = std::min(player->tally.delay, TICRATE); - - do + musiccountdown = 2; // gets decremented to 1 in G_Ticker to immediately trigger intermission music [blows raspberry] + } + else + { player->tally.Tick(); - while (player->tally.state != TALLY_ST_DONE && (fastForwardInput && player->tally.canFastForward)); + } if (!fastForwardInput) - player->tally.canFastForward = true; + { + player->tally.releasedFastForward = true; + } else - player->tally.canFastForward = false; + { + player->tally.releasedFastForward = false; + } + } void K_DrawPlayerTally(void) diff --git a/src/k_tally.h b/src/k_tally.h index 407f2b5f8..62587cd7b 100644 --- a/src/k_tally.h +++ b/src/k_tally.h @@ -96,7 +96,7 @@ struct level_tally_t UINT8 xtraBlink; boolean showGrade; boolean done; - boolean canFastForward; + boolean releasedFastForward; #ifdef __cplusplus boolean UseBonuses(void); From 29ba47459c1945390cdf3bac5d6290a03c9b10e7 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 12 Mar 2024 05:26:04 -0700 Subject: [PATCH 3/9] Time Attack replays: go to intermission --- src/g_demo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_demo.cpp b/src/g_demo.cpp index 9ea033f53..e1cf7c2d0 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -3989,7 +3989,7 @@ boolean G_CheckDemoStatus(void) if (demo.quitafterplaying) I_Quit(); - if (multiplayer && !demo.attract) + if (!demo.attract) G_FinishExitLevel(); else { From ed4c4d83633bd5e9a9d8905f7ee783fded457d55 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 12 Mar 2024 05:28:58 -0700 Subject: [PATCH 4/9] Time Attack replays: let tally finish even if replay data ends during tally - If tally is skipped, the replay will be cut short - Just stop reading the demo if this happened after the tally started - It's okay to let the level continue without any input because the player already finished (we know the result) --- src/g_demo.cpp | 10 +++++++++- src/g_demo.h | 1 + src/p_tick.c | 14 +++++++++----- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/g_demo.cpp b/src/g_demo.cpp index e1cf7c2d0..e9c089a56 100644 --- a/src/g_demo.cpp +++ b/src/g_demo.cpp @@ -3958,6 +3958,7 @@ void G_StopDemo(void) demobuf.buffer = NULL; demo.playback = false; demo.timing = false; + demo.waitingfortally = false; g_singletics = false; { @@ -3989,7 +3990,13 @@ boolean G_CheckDemoStatus(void) if (demo.quitafterplaying) I_Quit(); - if (!demo.attract) + // When this replay was recorded, the player skipped + // the Tally and ended the demo early. + // Keep the demo open and don't boot to intermission + // YET, pause demo playback. + if (!demo.waitingfortally && modeattacking && exitcountdown) + demo.waitingfortally = true; + else if (!demo.attract) G_FinishExitLevel(); else { @@ -4024,6 +4031,7 @@ boolean G_CheckDemoStatus(void) Z_Free(demobuf.buffer); demo.recording = false; + demo.waitingfortally = false; return false; } diff --git a/src/g_demo.h b/src/g_demo.h index 7a43d33c0..a7f99b241 100644 --- a/src/g_demo.h +++ b/src/g_demo.h @@ -90,6 +90,7 @@ struct demovars_s { boolean quitafterplaying; // quit after playing a demo from cmdline boolean deferstart; // don't start playing demo right away boolean netgame; // multiplayer netgame + boolean waitingfortally; // demo ended but we're keeping the level open for the tally to finish tic_t savebutton; // Used to determine when the local player can choose to save the replay while the race is still going boolean willsave; diff --git a/src/p_tick.c b/src/p_tick.c index c797e70df..55d051709 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -904,7 +904,7 @@ void P_Ticker(boolean run) if (playeringame[i]) G_WriteDemoTiccmd(&players[i].cmd, i); } - if (demo.playback) + if (demo.playback && !demo.waitingfortally) { G_ReadDemoExtraData(); for (i = 0; i < MAXPLAYERS; i++) @@ -1150,9 +1150,12 @@ void P_Ticker(boolean run) exitcountdown--; } - if (server && exitcountdown == 1) + if (exitcountdown == 1) { - SendNetXCmd(XD_EXITLEVEL, NULL, 0); + if (demo.playback) + G_FinishExitLevel(); + else if (server) + SendNetXCmd(XD_EXITLEVEL, NULL, 0); } } } @@ -1204,14 +1207,15 @@ void P_Ticker(boolean run) if (cv_recordmultiplayerdemos.value && demo.savebutton && demo.savebutton + 3*TICRATE < leveltime) G_CheckDemoTitleEntry(); } - else if (demo.playback) // Use Ghost data for consistency checks. + else if (demo.playback && !demo.waitingfortally) // Use Ghost data for consistency checks. { G_ConsAllGhostTics(); } if (modeattacking) { - G_GhostTicker(); + if (!demo.waitingfortally) + G_GhostTicker(); if (!demo.playback) G_TickTimeStickerMedals(); } From 5caa30d8d810ab2e51365fc4c0b9c0f7772ed93c Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 12 Mar 2024 06:41:31 -0700 Subject: [PATCH 5/9] Replays: let G_IsPartyLocal work --- src/g_party.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/g_party.cpp b/src/g_party.cpp index 6f83841c0..c0e1844c0 100644 --- a/src/g_party.cpp +++ b/src/g_party.cpp @@ -101,7 +101,7 @@ public: bool local() const { // consoleplayer is not valid yet. - if (!addedtogame) + if (!addedtogame && !demo.playback) { return false; } From 59fb8aad8c0653e020f09fc9eba885521c65c5e0 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 12 Mar 2024 05:34:55 -0700 Subject: [PATCH 6/9] Replays: end level music at tally of currently viewed player - This is symmetrical with splitscreen behavior - One edge case: if you switch away from the player after the level music stops but before the intermission music starts, then the silence will continue until you view another tally that reaches the intermission music - I think the benefit of doing the proper tally music at all outweighs this edge case --- src/g_game.c | 5 ++++- src/p_user.c | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/g_game.c b/src/g_game.c index 45f7ae9ba..c6d1f9539 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -2003,7 +2003,7 @@ void G_Ticker(boolean run) memset(player_name_changes, 0, sizeof player_name_changes); } - if (Playing() == true) + if (Playing() == true || demo.playback) { if (musiccountdown > 1) { @@ -2017,7 +2017,10 @@ void G_Ticker(boolean run) P_EndingMusic(); } } + } + if (Playing() == true) + { P_InvincGrowMusic(); K_TickMidVote(); diff --git a/src/p_user.c b/src/p_user.c index 63bfe58ba..b86271c69 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -1273,7 +1273,7 @@ void P_DoPlayerExit(player_t *player, pflags_t flags) K_UpdatePowerLevelsFinalize(player, false); - if (P_IsPartyPlayer(player) && !specialout && musiccountdown == 0) + if (G_IsPartyLocal(player - players) && !specialout && musiccountdown == 0) { Music_Play("finish_silence"); musiccountdown = MUSIC_COUNTDOWN_MAX; @@ -3833,7 +3833,7 @@ void P_DoTimeOver(player_t *player) P_DamageMobj(player->mo, NULL, NULL, 1, DMG_TIMEOVER); } - if (P_IsPartyPlayer(player) && musiccountdown == 0) + if (G_IsPartyLocal(player - players) && musiccountdown == 0) { Music_Play("finish_silence"); musiccountdown = MUSIC_COUNTDOWN_MAX; From 6b413e530f5002851e50917b7450663452616a8d Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 12 Mar 2024 05:48:49 -0700 Subject: [PATCH 7/9] Tally skipping: allow in Match Race, disallow in replays --- src/k_tally.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/k_tally.cpp b/src/k_tally.cpp index c65831076..2fc9fb055 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -1397,7 +1397,12 @@ void K_TickPlayerTally(player_t *player) boolean fastForwardInput = G_PlayerInputDown(G_LocalSplitscreenPartyPosition(player - players), gc_a, 0); boolean allowFastForward = player->tally.state > TALLY_ST_GOTTHRU_SLIDEIN && player->tally.releasedFastForward - && grandprixinfo.gp + // - Not allowed online so we don't have to do any + // networking. + // - Not allowed in replays because splitscreen party + // doesn't exist and it's just simpler to not think + // about. + && (!netgame && !demo.playback) && player->tally.state != TALLY_ST_DONE; if (fastForwardInput && allowFastForward) From 2af5f32a72466959348d0de91acd96090a9e6441 Mon Sep 17 00:00:00 2001 From: James R Date: Tue, 12 Mar 2024 06:06:25 -0700 Subject: [PATCH 8/9] Tally skipping: make sure player is actually local splitscreen before doing button check --- src/k_tally.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_tally.cpp b/src/k_tally.cpp index 2fc9fb055..e78986f54 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -1394,7 +1394,8 @@ void K_InitPlayerTally(player_t *player) void K_TickPlayerTally(player_t *player) { - boolean fastForwardInput = G_PlayerInputDown(G_LocalSplitscreenPartyPosition(player - players), gc_a, 0); + boolean fastForwardInput = !demo.playback && P_IsMachineLocalPlayer(player) && + G_PlayerInputDown(G_LocalSplitscreenPartyPosition(player - players), gc_a, 0); boolean allowFastForward = player->tally.state > TALLY_ST_GOTTHRU_SLIDEIN && player->tally.releasedFastForward // - Not allowed online so we don't have to do any From 1a70892fd7ed384354a55997674326e956437d2e Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Tue, 12 Mar 2024 06:14:08 -0700 Subject: [PATCH 9/9] Tally: disallow skipping tryagain/gameover (but cover for it if we do allow it later) --- src/k_tally.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/k_tally.cpp b/src/k_tally.cpp index e78986f54..519428dcb 100644 --- a/src/k_tally.cpp +++ b/src/k_tally.cpp @@ -1397,6 +1397,7 @@ void K_TickPlayerTally(player_t *player) boolean fastForwardInput = !demo.playback && P_IsMachineLocalPlayer(player) && G_PlayerInputDown(G_LocalSplitscreenPartyPosition(player - players), gc_a, 0); boolean allowFastForward = player->tally.state > TALLY_ST_GOTTHRU_SLIDEIN + && player->tally.state <= TALLY_ST_DONE && player->tally.releasedFastForward // - Not allowed online so we don't have to do any // networking. @@ -1410,7 +1411,7 @@ void K_TickPlayerTally(player_t *player) { do player->tally.Tick(); - while (player->tally.state != TALLY_ST_DONE); + while (player->tally.state != TALLY_ST_DONE && player->tally.state != TALLY_ST_GAMEOVER_DONE); player->tally.delay = std::min(player->tally.delay, TICRATE); musiccountdown = 2; // gets decremented to 1 in G_Ticker to immediately trigger intermission music [blows raspberry]