From aedddc21e9f0eb3659c05050442d69d35f7284e2 Mon Sep 17 00:00:00 2001 From: Amber Burton Date: Mon, 29 Jun 2026 00:48:27 -0400 Subject: [PATCH] Sync's Ganons Trials and Fixes Softlock (#6828) Previous co op softlock fix introduced a possible trial softlock making barrier never dissappear. This not only ensures that softlock cant happen, it syncs the trial flags in real time and allows all cutscenes to finish playing to properly remove the barrier even if the beams are physically visible in your game. --- soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp | 5 +++++ soh/src/code/z_demo.c | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp b/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp index 436ac92fd9..b05ab6f021 100644 --- a/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp +++ b/soh/soh/Network/Anchor/Packets/UpdateTeamState.cpp @@ -199,6 +199,11 @@ void Anchor::HandlePacket_UpdateTeamState(nlohmann::json payload) { gSaveContext.ship.stats.firstInput = loadedData.ship.stats.firstInput; gSaveContext.ship.stats.fileCreatedAt = loadedData.ship.stats.fileCreatedAt; + // Ensure ganon barrier state matches trials + if (gSaveContext.eventChkInf[10] & 0x2000 && gSaveContext.eventChkInf[11] & 0xFC00) { + gSaveContext.eventChkInf[12] |= 0x8; + } + // Restore master sword state // Disabling this for now, not really sure I understand why I did this in the past // u8 hasMasterSword = CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, 1); diff --git a/soh/src/code/z_demo.c b/soh/src/code/z_demo.c index fda3cd0618..ecf26beadd 100644 --- a/soh/src/code/z_demo.c +++ b/soh/src/code/z_demo.c @@ -1229,31 +1229,43 @@ void Cutscene_Command_Terminator(PlayState* play, CutsceneContext* csCtx, CsCmdB play->nextEntranceIndex = ENTR_INSIDE_GANONS_CASTLE_2; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_BLACK; + Flags_SetEventChkInf(EVENTCHKINF_COMPLETED_FOREST_TRIAL); + gSaveContext.eventChkInf[11] &= ~0x800; break; case 108: play->nextEntranceIndex = ENTR_INSIDE_GANONS_CASTLE_3; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_BLACK; + Flags_SetEventChkInf(EVENTCHKINF_COMPLETED_WATER_TRIAL); + gSaveContext.eventChkInf[11] &= ~0x1000; break; case 109: play->nextEntranceIndex = ENTR_INSIDE_GANONS_CASTLE_4; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_BLACK; + Flags_SetEventChkInf(EVENTCHKINF_COMPLETED_SHADOW_TRIAL); + gSaveContext.eventChkInf[11] &= ~0x2000; break; case 110: play->nextEntranceIndex = ENTR_INSIDE_GANONS_CASTLE_5; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_BLACK; + Flags_SetEventChkInf(EVENTCHKINF_COMPLETED_FIRE_TRIAL); + gSaveContext.eventChkInf[11] &= ~0x4000; break; case 111: play->nextEntranceIndex = ENTR_INSIDE_GANONS_CASTLE_6; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_BLACK; + Flags_SetEventChkInf(EVENTCHKINF_COMPLETED_LIGHT_TRIAL); + gSaveContext.eventChkInf[11] &= ~0x8000; break; case 112: play->nextEntranceIndex = ENTR_INSIDE_GANONS_CASTLE_7; play->transitionTrigger = TRANS_TRIGGER_START; play->transitionType = TRANS_TYPE_FADE_BLACK; + Flags_SetEventChkInf(EVENTCHKINF_COMPLETED_SPIRIT_TRIAL); + gSaveContext.eventChkInf[10] &= ~0x2000; break; case 113: if (Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FOREST_TRIAL) &&