bugfix(challenge): Fix Generals Challenge defeat during next mission intro cinematic#225
Merged
fbraz3 merged 1 commit intoJul 20, 2026
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change
Fixes a defeat screen appearing during the intro cinematic when continuing from one Generals Challenge mission to the next via the score screen Continue button.
Root cause
startNextCampaignGame()performedpopImmediate()/hideShell()before queuingMSG_NEW_GAME(GAME_SINGLE_PLAYER). Hiding the shell triggers the next menu's init (e.g. SaveLoad), which callsShell::showShellMap(TRUE). That appends its ownMSG_NEW_GAME(GAME_SHELL)for the shell map and overwritesm_pendingFilewith the shell map name.That
GAME_SHELLmessage then races ahead of theGAME_SINGLE_PLAYERmessage and is processed first byonNewGame():m_gameModebecomesGAME_SHELLisChallengeCampaigncheck intryStartNewGame()evaluates tofalse(it requiresm_gameMode == GAME_SINGLE_PLAYER)TheGameInfostaysnullplaceNetworkBuildingsForPlayer()is skippedPLAYER_HAS_N_OR_FEWER_BUILDINGSscript firesdoDefeat()a few frames after the map loads, visible as the defeat screen during the intro cinematicThe actual
GAME_SINGLE_PLAYERmessage is subsequently rejected by theonNewGame()guard (isInGame || isLoadingMap), so the wrong map/mode combination loads.The bug only reproduces on the Continue path. Loading the same save directly via Load Game works because that path uses
MSG_NEW_GAMEwithGAME_SINGLE_PLAYERand does not trigger the shell map race.Fix
Reorder
startNextCampaignGame()so that:m_pendingFileis set to the current campaign map before any shell teardownMSG_NEW_GAME(GAME_SINGLE_PLAYER)is queued beforepopImmediate()/hideShell(), guaranteeing it sits ahead of anyMSG_NEW_GAME(GAME_SHELL)appended byShell::showShellMap(TRUE)m_pendingFileis re-asserted after the shell teardown, sinceShell::showShellMap(TRUE)may have overwritten it with the shell map name (andprepareNewGame()copiesm_pendingFileintom_mapName, so the value present at queue-drain time is what actually loads)The shell's duplicate
MSG_NEW_GAME(GAME_SHELL)now lands behind ours and is rejected by the existingonNewGame()guard.Verification
Tested on macOS (Apple Silicon), preset
macos-vulkan:gc_americaboss-> win -> Continue -> next mission (GC_TankGeneral) loads and shows the defeat screen during the intro cinematic; the map has 0 objects owned by the local player.Instrumented trace (added temporarily during investigation, not part of this PR) confirmed the message ordering: without the fix the first
onNewGame()call receivedgameMode == GAME_SHELL; with the fix it receivesgameMode == GAME_SINGLE_PLAYERand the shell's follow-up message is rejected.Scope
Single file, single function (
ScoreScreen.cpp::startNextCampaignGame()). No gameplay balance, AI or rendering changes. Applies to Zero Hour only; the Generals replica can follow in a follow-up PR per the contribution guidelines if desired.AI generated code
The fix was authored with LLM assistance and polished/tested by the author (coolswood). The change is 21 inserted lines (one reorder plus explanatory comments) in a single function.