Fix Platform Failing to Lower After Defeating Big Octo#6622
Conversation
| // when Big Octo dies, the clear flag goes permanently unread. This fallback catches that case: the clear flag is | ||
| // only ever set by Big Octo's death, and the switch flag is only set once the platform has already begun its | ||
| // descent. | ||
| if (thisx->params == 0 && Flags_GetClear(play, thisx->room) && !Flags_GetSwitch(play, this->switchFlag)) { |
There was a problem hiding this comment.
does this only happen due to cutscene skips?
code should be made as a timesaver hook
There was a problem hiding this comment.
Investigated this angle a bit. The VB_PLAY_ONEPOINT_ACTOR_CS hook fires identically in both successful and failed rando runs. Vanilla runs without the timesaver show the same flag sequence, so the timesaver does not seem to be a factor.
OnePointCutscene_Attention does route through OnePointCutscene_Init, so the ACTOR_BG_BDAN_SWITCH skip in the timesave handler does fire after Big Octo dies, but the Bdan switch is ACTORCAT_SWITCH (cat 0) and the platform is ACTORCAT_BG (cat 1). The switch skip happens one frame after the platform has already transitioned to SinkToFloorHeight, so it can't interfere.
Failed run 1:
[11:06:04.065] VB_PLAY_ONEPOINT_ACTOR_CS ID:198 Cat:6
[11:06:39.708] Clear Flag Set - 0x6Failed run 2:
[11:14:26.621] VB_PLAY_ONEPOINT_ACTOR_CS ID:198 Cat:6
[11:15:17.470] Clear Flag Set - 0x6No fail, rando:
[04:55:28.234] VB_PLAY_ONEPOINT_ACTOR_CS ID:198 Cat:6
[04:55:46.784] Clear Flag Set - 0x6
[04:55:46.834] Switch Flag Set - 0x1fNo fail, vanilla:
[04:52:53.185] Clear Flag Set - 0x6
[04:52:53.251] Switch Flag Set - 0x1fThere was a problem hiding this comment.
why doesn't this show up on console?
There was a problem hiding this comment.
A little suspect in general that this actually happens without the cutscene skip, as this bug definitely didn't exist in Ship before we had those.
This fixes #4339.
After defeating Big Octo, the platform sometimes fails to lower, softlocking dungeon progression. One comment that stuck out to me and one I was able to also experience when trying to reproduce the bug was the platform not rotating during the fight before it occurs.
I added diagnostic logging to the Big Octo platform state machine and Big Octo's death sequence and was able to get "successful" logs twice. In both failures:
Flags_SetClearfor room 6 was confirmed to fire on Big Octo's deathBattleInProgressfunction never detected the clear flagThis means that the platform was not in
BattleInProgresswhen Big Octo died, despite plenty of time for the cutscene sequence to complete.BgBdanObjects_OctoPlatform_BattleInProgressis the only state that checks forFlags_GetClear, and the platform itself has to pass through a multi-state cutscene sequence to reach it:WaitForRutoToStartCutsceneRaiseToUpperPositionWaitForRutoToAdvanceCutscenePauseBeforeDescendingDescendWithBigOctoWaitForBigOctoToStartBattleBattleInProgressIf the platform fails to reach
BattleInProgressfor any reason -- or is knocked out of it -- Big Octo's death goes permanently unacknowledged. The clear flag is set but never read. This is actually a structural vulnerability on original hardware as well, but there are never enough differing variables to trigger it.To fix this, a fallback check was added to
BgBdanObjects_Updateto detect when Big Octo has been defeated but the platform has not yet responded:This mirrors the existing transition in
BattleInProgress:Shipwright/soh/src/overlays/actors/ovl_Bg_Bdan_Objects/z_bg_bdan_objects.c
Lines 308 to 311 in a6ceda9
The three conditions ensure it only fires when the bug is actively occurring:
params == 0: Only the Big Octo platform variant, not the elevator or water objectsFlags_GetClear: Big Octo is dead -- this flag is only set byEn_Bigokuta's death sequence!Flags_GetSwitch: The platform has not already begun its descent -- the switch flag is set by both the normalBattleInProgresspath and theInitreentry path, so this condition is false during all post-battle statesThere is no combination of normal gameplay states where all three conditions are true simultaneously unless the bug has occurred. The switch flag life cycle for the Big Octo platform (params == 0) is:
Flags_SetSwitch-> switch onFlags_UnsetSwitch-> switch offFlags_SetSwitch-> switch onThe fallback only fires between steps 2 and 3 -- when the switch is off and the clear flag is set -- which is exactly the window where the bug manifests.
This bug is incredibly difficult to reproduce reliably. My two reproductions captured via logging both occurred in randomizer seeds on the first-visit path, with Big Octo defeated quickly via Deku Stick jump slash. In the second instance, Big Octo entered his retreat state on battle start which is an impossibility -- he is hardcoded to always move toward Link first. This, along with the platform not rotating during the battle, heavily suggests memory corruption as the underlying trigger, but this is hard to prove and the structural fix addresses the symptom regardless of root cause.