From dea77e98fafa1f1705088e9bb76e903931e5a1ce Mon Sep 17 00:00:00 2001 From: Misa Date: Thu, 18 May 2023 19:11:04 -0700 Subject: [PATCH] Defer hardreset to end of frame in quittomenu This fixes a bug where the wrong music can play on the title screen, as reported by AllyTally on Discord. The bug can be triggered by triggering a room transition right as game.quittomenu() is called (which is easiest to achieve by placing the player on an oscillating/"out of bounds" room border in a custom level so they go back and forth between two rooms every frame, and triggering gamestate 1013, which starts a fadeout to menu if all custom crewmates are rescued). When this happens, game.quittomenu() calls script.hardreset(), but the rest of the frame still executes, even though we set game.gamestate to TITLEMODE too (because game.quittomenu() was called by game.updatestate() which was called by gamelogic(), and game.gamestate is only checked at the start of the frame). This ends up triggering a room transition, and since map.custommode is guaranteed to now be off (because of script.hardreset()), the main game music area code kicks in, and plays something that isn't Presenting VVVVVV. The bug here is that we're resetting too early when we still have the rest of an in-game frame to execute. So, instead, we should only reset at the end of the frame, and this can be achieved with a defer callback. --- desktop_version/src/Game.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/desktop_version/src/Game.cpp b/desktop_version/src/Game.cpp index d75aaf8b..2d6c7dfa 100644 --- a/desktop_version/src/Game.cpp +++ b/desktop_version/src/Game.cpp @@ -7145,6 +7145,11 @@ bool Game::save_exists(void) return telesummary != "" || quicksummary != ""; } +static void hardreset(void) +{ + script.hardreset(); +} + void Game::quittomenu(void) { gamestate = TITLEMODE; @@ -7204,7 +7209,9 @@ void Game::quittomenu(void) { createmenu(Menu::mainmenu); } - script.hardreset(); + /* We might not be at the end of the frame yet. + * If we hardreset() now, some state might still persist. */ + DEFER_CALLBACK(hardreset); } void Game::returntolab(void)