diff --git a/soh/soh/Enhancements/presets.h b/soh/soh/Enhancements/presets.h index f88dfaf8c..c54622e2a 100644 --- a/soh/soh/Enhancements/presets.h +++ b/soh/soh/Enhancements/presets.h @@ -303,6 +303,7 @@ const std::vector enhancementsCvars = { CVAR_ENHANCEMENT("TimeSavers.SkipChildStealth"), CVAR_ENHANCEMENT("TimeSavers.SkipTowerEscape"), CVAR_ENHANCEMENT("TimeSavers.SkipForcedDialog"), + CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), CVAR_ENHANCEMENT("SlowTextSpeed"), }; diff --git a/soh/soh/Enhancements/timesaver_hook_handlers.cpp b/soh/soh/Enhancements/timesaver_hook_handlers.cpp index 317c751a3..703fc125f 100644 --- a/soh/soh/Enhancements/timesaver_hook_handlers.cpp +++ b/soh/soh/Enhancements/timesaver_hook_handlers.cpp @@ -22,6 +22,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Tk/z_en_tk.h" #include "src/overlays/actors/ovl_En_Fu/z_en_fu.h" #include "src/overlays/actors/ovl_Bg_Spot02_Objects/z_bg_spot02_objects.h" +#include "src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h" #include "src/overlays/actors/ovl_Bg_Hidan_Kousi/z_bg_hidan_kousi.h" #include "src/overlays/actors/ovl_Bg_Dy_Yoseizo/z_bg_dy_yoseizo.h" #include "src/overlays/actors/ovl_En_Dnt_Demo/z_en_dnt_demo.h" @@ -92,6 +93,9 @@ void EnDntDemo_JudgeSkipToReward(EnDntDemo* enDntDemo, PlayState* play) { } } +void BgSpot03Taki_KeepOpen(BgSpot03Taki* bgSpot03Taki, PlayState* play) { +} + static int successChimeCooldown = 0; void RateLimitedSuccessChime() { if (successChimeCooldown == 0) { @@ -676,6 +680,8 @@ static uint32_t enFuUpdateHook = 0; static uint32_t enFuKillHook = 0; static uint32_t bgSpot02UpdateHook = 0; static uint32_t bgSpot02KillHook = 0; +static uint32_t bgSpot03UpdateHook = 0; +static uint32_t bgSpot03KillHook = 0; static uint32_t enPoSistersUpdateHook = 0; static uint32_t enPoSistersKillHook = 0; void TimeSaverOnActorInitHandler(void* actorRef) { @@ -753,6 +759,41 @@ void TimeSaverOnActorInitHandler(void* actorRef) { }); } + if (actor->id == ACTOR_BG_SPOT03_TAKI && Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY) && + (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME || + INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_OCARINA_FAIRY)) { + bgSpot03UpdateHook = GameInteractor::Instance->RegisterGameHook([](void* innerActorRef) mutable { + Actor* innerActor = static_cast(innerActorRef); + if (innerActor->id == ACTOR_BG_SPOT03_TAKI && Flags_GetEventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY) && + (INV_CONTENT(ITEM_OCARINA_TIME) == ITEM_OCARINA_TIME || + INV_CONTENT(ITEM_OCARINA_FAIRY) == ITEM_OCARINA_FAIRY) && + (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), IS_RANDO)) + ) { + BgSpot03Taki* bgSpot03 = static_cast(innerActorRef); + if (bgSpot03->actionFunc == func_808ADEF0) { + bgSpot03->actionFunc = BgSpot03Taki_KeepOpen; + bgSpot03->state = WATERFALL_OPENED; + bgSpot03->openingAlpha = 0.0f; + Flags_SetSwitch(gPlayState, bgSpot03->switchFlag); + func_8003EBF8(gPlayState, &gPlayState->colCtx.dyna, bgSpot03->dyna.bgId); + BgSpot03Taki_ApplyOpeningAlpha(bgSpot03, 0); + BgSpot03Taki_ApplyOpeningAlpha(bgSpot03, 1); + + GameInteractor::Instance->UnregisterGameHook(bgSpot03UpdateHook); + GameInteractor::Instance->UnregisterGameHook(bgSpot03KillHook); + bgSpot03UpdateHook = 0; + bgSpot03KillHook = 0; + } + } + }); + bgSpot03KillHook = GameInteractor::Instance->RegisterGameHook([](int16_t sceneNum) mutable { + GameInteractor::Instance->UnregisterGameHook(bgSpot03UpdateHook); + GameInteractor::Instance->UnregisterGameHook(bgSpot03KillHook); + bgSpot03UpdateHook = 0; + bgSpot03KillHook = 0; + }); + } + if (actor->id == ACTOR_EN_DNT_DEMO && (IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO))) { EnDntDemo* enDntDemo = static_cast(actorRef); enDntDemo->actionFunc = EnDntDemo_JudgeSkipToReward; diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp index 050cbf463..17346fdd5 100644 --- a/soh/soh/SohMenuBar.cpp +++ b/soh/soh/SohMenuBar.cpp @@ -761,6 +761,9 @@ void DrawEnhancementsMenu() { "- Not within range of Ocarina playing spots"); UIWidgets::PaddedEnhancementCheckbox("Pause Warp", CVAR_ENHANCEMENT("PauseWarp"), true, false); UIWidgets::Tooltip("Selection of warp song in pause menu initiates warp. Disables song playback."); + UIWidgets::PaddedEnhancementCheckbox("Open Sleeping Waterfall", CVAR_ENHANCEMENT("TimeSavers.SleepingWaterfall"), true, false); + UIWidgets::Tooltip("If Link has an ocarina and has learned Zelda's Lullaby, " + "the waterfall in Zora's River will be open without having to play it."); ImGui::EndTable(); ImGui::EndMenu(); diff --git a/soh/src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.c b/soh/src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.c index 71341097b..e3441d28f 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.c +++ b/soh/src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.c @@ -14,8 +14,6 @@ void BgSpot03Taki_Destroy(Actor* thisx, PlayState* play); void BgSpot03Taki_Update(Actor* thisx, PlayState* play); void BgSpot03Taki_Draw(Actor* thisx, PlayState* play); -void func_808ADEF0(BgSpot03Taki* this, PlayState* play); - const ActorInit Bg_Spot03_Taki_InitVars = { ACTOR_BG_SPOT03_TAKI, ACTORCAT_BG, diff --git a/soh/src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h b/soh/src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h index 60d820bdb..6eba416e7 100644 --- a/soh/src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h +++ b/soh/src/overlays/actors/ovl_Bg_Spot03_Taki/z_bg_spot03_taki.h @@ -26,4 +26,8 @@ typedef struct BgSpot03Taki { /* 0x0174 */ u8 bufferIndex; } BgSpot03Taki; // size = 0x0178 +void func_808ADEF0(BgSpot03Taki* bgSpot03Taki, PlayState* play); + +void BgSpot03Taki_ApplyOpeningAlpha(BgSpot03Taki* bgSpot03Taki, s32 bufferIndex); + #endif