From 2d70ae7075a0748fdd1811629d1bc4f9178ab9cf Mon Sep 17 00:00:00 2001 From: Cyd Date: Tue, 11 Aug 2026 22:57:00 -0500 Subject: [PATCH] An abort during prep goes back to the menu, not the desktop Cyd Alt+Q'ed out of a mission and landed on the desktop. From a RUNNING race that was never the intent - the single-binary loop returns to the setup screen whenever the console says the mission completed - but the console only learned that from PhaseRunning. A mission that died while still PREPPING - Alt+Q during loading, or during the commit hold - left the console in PhaseWaiting forever, MissionCompleted() answered False, and WinMain fell out of the race loop to the desktop. The hole is as old as the race loop, but it had no traffic until tonight: the commit hold makes the prep window somewhere players actually stand, and changing your mind there is exactly what Alt+Q is for. The console now counts a prep death as a completed mission: back to the menu, lobby intact - a host lands on the setup page still hosting, the commit board comes down, and the remote console channels close, which ends the members' prep too (their consoles vanishing already means the mission cannot start; now it means it promptly). Co-Authored-By: Claude Opus 5 (1M context) --- RP_L4/RPL4CONSOLE.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/RP_L4/RPL4CONSOLE.cpp b/RP_L4/RPL4CONSOLE.cpp index 8b8309b..85ecdbb 100644 --- a/RP_L4/RPL4CONSOLE.cpp +++ b/RP_L4/RPL4CONSOLE.cpp @@ -704,6 +704,32 @@ namespace switch (gPhase) { case PhaseWaiting: + // + // A mission can die before it ever runs - Alt+Q during the + // commit hold, or while loading. The console only learned a + // mission was over from PhaseRunning, so an abort during prep + // left it in PhaseWaiting forever, MissionCompleted() answered + // False, and WinMain's single-binary loop fell out to the + // DESKTOP instead of returning to the setup screen. The commit + // hold makes the prep window somewhere players actually stand, + // so the hole finally had traffic. A prep death counts as a + // completed mission now: back to the menu, lobby intact. + // + if (state == Application::EndingMission || + state == Application::StoppingMission || + state == Application::AbortingMission) + { + DEBUG_STREAM << "LocalConsole: mission ended during prep - " + << "back to the menu\n" << std::flush; + InterlockedExchange(&gMissionRunning, 0); + gPhase = PhaseStopped; + DestroyStatusBoard(); + if (gNetworkRace) + { + DisconnectRemotes(); + } + break; + } if (gNetworkRace) { MarshalRemotes();