From 16836172105ee90802f2e81ddcedf67193b2a20d Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Thu, 18 Apr 2024 21:13:40 -0500 Subject: [PATCH] Migrate rainbow bridge --- .../game-interactor/GameInteractor.h | 2 + .../Enhancements/randomizer/hook_handlers.cpp | 57 +++++++++++++ .../Enhancements/timesaver_hook_handlers.cpp | 7 ++ .../ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c | 82 +++++-------------- 4 files changed, 85 insertions(+), 63 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h index a3d7e9045..8dc20e215 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h @@ -113,6 +113,7 @@ typedef enum { GI_VB_SHIEK_PREPARE_TO_GIVE_SERENADE_OF_WATER, // Vanilla condition: !EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT and EVENTCHKINF_USED_FOREST_TEMPLE_BLUE_WARP GI_VB_BE_ELIGIBLE_FOR_PRELUDE_OF_LIGHT, + GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, /* Vanilla Condition: ``` LINK_IS_ADULT && @@ -255,6 +256,7 @@ typedef enum { GI_VB_PLAY_ROYAL_FAMILY_TOMB_EXPLODE, // Opt: *EnOkarinaTag GI_VB_PLAY_DOOR_OF_TIME_CS, + GI_VB_PLAY_RAINBOW_BRIDGE_CS, /*** Give Items ***/ diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index f47d1adad..a2fe8697e 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -116,6 +116,59 @@ bool CompletedAllTrials() { Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FOREST_TRIAL); } +bool MeetsRainbowBridgeRequirements() { + switch (RAND_GET_OPTION(RSK_RAINBOW_BRIDGE)) { + case RO_BRIDGE_VANILLA: { + if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT)) { + return true; + } + break; + } + case RO_BRIDGE_STONES: { + if ((CheckStoneCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_STONE_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_MEDALLIONS: { + if ((CheckMedallionCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_DUNGEON_REWARDS: { + if ((CheckMedallionCount() + CheckStoneCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_REWARD_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_DUNGEONS: { + if ((CheckDungeonCount() + CheckBridgeRewardCount()) >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_TOKENS: { + if (gSaveContext.inventory.gsTokens >= RAND_GET_OPTION(RSK_RAINBOW_BRIDGE_TOKEN_COUNT)) { + return true; + } + break; + } + case RO_BRIDGE_GREG: { + if (Flags_GetRandomizerInf(RAND_INF_GREG_FOUND)) { + return true; + } + break; + } + case RO_BRIDGE_ALWAYS_OPEN: { + return true; + } + } + + return false; +} + // Todo Move this to randomizer context, clear it out on save load etc static std::queue randomizerQueuedChecks; static RandomizerCheck randomizerQueuedCheck = RC_UNKNOWN_CHECK; @@ -996,6 +1049,10 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void *should = false; break; } + case GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE: { + *should = MeetsRainbowBridgeRequirements(); + break; + } case GI_VB_TRADE_TIMER_ODD_MUSHROOM: case GI_VB_TRADE_TIMER_EYEDROPS: case GI_VB_TRADE_TIMER_FROG: diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 18249e0bf..886b3ddea 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -666,6 +666,13 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, void* break; } + case GI_VB_PLAY_RAINBOW_BRIDGE_CS: { + if (CVarGetInteger("gTimeSavers.SkipCutscene.Story", IS_RANDO)) { + *should = false; + func_800F595C(NA_BGM_BRIDGE_TO_GANONS); + } + break; + } } } diff --git a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c index b592edcd5..543770505 100644 --- a/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c +++ b/soh/src/overlays/actors/ovl_Bg_Gjyo_Bridge/z_bg_gjyo_bridge.c @@ -7,6 +7,7 @@ #include "z_bg_gjyo_bridge.h" #include "objects/object_gjyo_objects/object_gjyo_objects.h" #include "scenes/dungeons/ganon_tou/ganon_tou_scene.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -50,8 +51,7 @@ void BgGjyoBridge_Init(Actor* thisx, PlayState* play) { this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, thisx, colHeader); - int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); - if (Flags_GetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT) || (IS_RANDO && bridge == RO_BRIDGE_ALWAYS_OPEN)) { + if (Flags_GetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT)) { this->actionFunc = func_808787A4; } else { this->dyna.actor.draw = NULL; @@ -70,8 +70,10 @@ void func_808787A4(BgGjyoBridge* this, PlayState* play) { } void LaunchBridgeCutscene(BgGjyoBridge* this, PlayState* play) { - play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs); - gSaveContext.cutsceneTrigger = 1; + if (GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL)) { + play->csCtx.segment = SEGMENTED_TO_VIRTUAL(gRainbowBridgeCs); + gSaveContext.cutsceneTrigger = 1; + } this->actionFunc = BgGjyoBridge_SpawnBridge; } @@ -84,70 +86,24 @@ u8 CheckPlayerPosition(Player* player, PlayState* play) { void BgGjyoBridge_TriggerCutscene(BgGjyoBridge* this, PlayState* play) { Player* player = GET_PLAYER(play); - if (!IS_RANDO) { - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && - (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) && CheckPlayerPosition(player, play)) { - LaunchBridgeCutscene(this, play); - } - } else { - int bridge = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE); - int bridgeStoneCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_STONE_COUNT); - int bridgeMedallionCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT); - int bridgeRewardCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_REWARD_COUNT); - int bridgeDungeonCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT); - int bridgeTokenCount = Randomizer_GetSettingValue(RSK_RAINBOW_BRIDGE_TOKEN_COUNT); + u8 vanillaBridgeCondition = + CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && + CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && + (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) && + CheckPlayerPosition(player, play); - switch (bridge) { - case RO_BRIDGE_VANILLA: - if (CHECK_QUEST_ITEM(QUEST_MEDALLION_SPIRIT) && CHECK_QUEST_ITEM(QUEST_MEDALLION_SHADOW) && - (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT)) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_STONES: - if ((CheckStoneCount() + CheckBridgeRewardCount()) >= bridgeStoneCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_MEDALLIONS: - if ((CheckMedallionCount() + CheckBridgeRewardCount()) >= bridgeMedallionCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_DUNGEON_REWARDS: - if ((CheckMedallionCount() + CheckStoneCount() + CheckBridgeRewardCount()) >= bridgeRewardCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_DUNGEONS: - if ((CheckDungeonCount() + CheckBridgeRewardCount()) >= bridgeDungeonCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_TOKENS: - if (gSaveContext.inventory.gsTokens >= bridgeTokenCount) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - case RO_BRIDGE_GREG: - if (Flags_GetRandomizerInf(RAND_INF_GREG_FOUND)) { - this->actionFunc = BgGjyoBridge_SpawnBridge; - func_800F595C(NA_BGM_BRIDGE_TO_GANONS); - } - break; - } + if (GameInteractor_Should(GI_VB_BE_ELIGIBLE_FOR_RAINBOW_BRIDGE, vanillaBridgeCondition, NULL)) { + LaunchBridgeCutscene(this, play); } } void BgGjyoBridge_SpawnBridge(BgGjyoBridge* this, PlayState* play) { - if (IS_RANDO || (play->csCtx.state != CS_STATE_IDLE) && (play->csCtx.npcActions[2] != NULL) && - (play->csCtx.npcActions[2]->action == 2)) { + u8 vanillaBridgeCondition = + (play->csCtx.state != CS_STATE_IDLE) && + (play->csCtx.npcActions[2] != NULL) && + (play->csCtx.npcActions[2]->action == 2); + + if (!GameInteractor_Should(GI_VB_PLAY_RAINBOW_BRIDGE_CS, true, NULL) || vanillaBridgeCondition) { this->dyna.actor.draw = BgGjyoBridge_Draw; func_8003EC50(play, &play->colCtx.dyna, this->dyna.bgId); Flags_SetEventChkInf(EVENTCHKINF_RAINBOW_BRIDGE_BUILT);