From b04e4788421f270f280dc25689851cbb8ebee53c Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Thu, 31 Jul 2025 05:27:20 +0000 Subject: [PATCH] botw: water level toggle amazingly the code already handles the flag being cleared to raise the water level, so only need to setup hooks for ocarina spot to toggle In MQ it's a diamond switch, so only need to turn it into a toggleable diamond switch --- .../vanilla-behavior/GIVanillaBehavior.h | 16 +++++++++ .../Enhancements/randomizer/hook_handlers.cpp | 34 +++++++++++++++++++ .../ovl_En_Okarina_Tag/z_en_okarina_tag.c | 15 ++++---- 3 files changed, 59 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 186307aede3..ce47d1593c0 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -1362,6 +1362,22 @@ typedef enum { // - `*EnDs` VB_OFFER_BLUE_POTION, + // #### `result` + // ```c + // this->switchFlag >= 0 + // ``` + // #### `args` + // - `*EnOkarinaTag` + VB_OKARINA_TAG_COMPLETE, + + // #### `result` + // ```c + // (this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag)) + // ``` + // #### `args` + // - `*EnOkarinaTag` + VB_OKARINA_TAG_COMPLETED, + // #### `result` // ```c // CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index d73cebca759..808915933ee 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -48,6 +48,7 @@ extern "C" { #include "src/overlays/actors/ovl_En_Ds/z_en_ds.h" #include "src/overlays/actors/ovl_En_Gm/z_en_gm.h" #include "src/overlays/actors/ovl_En_Js/z_en_js.h" +#include "src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.h" #include "src/overlays/actors/ovl_En_Door/z_en_door.h" #include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h" #include "src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.h" @@ -1328,6 +1329,30 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l *should |= RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF; break; } + case VB_OKARINA_TAG_COMPLETE: { + if (gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL) { + auto dungeon = + OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); + if (dungeon->IsVanilla()) { + EnOkarinaTag* enOkarinaTag = va_arg(args, EnOkarinaTag*); + if (enOkarinaTag->switchFlag >= 0 && Flags_GetSwitch(gPlayState, enOkarinaTag->switchFlag)) { + Flags_UnsetSwitch(gPlayState, enOkarinaTag->switchFlag); + *should = false; + } + } + } + break; + } + case VB_OKARINA_TAG_COMPLETED: { + if (gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL) { + auto dungeon = + OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); + if (dungeon->IsVanilla()) { + *should = false; + } + } + break; + } case VB_GRANNY_SAY_INSUFFICIENT_RUPEES: { if (EnDs_RandoCanGetGrannyItem()) { *should = gSaveContext.rupees < @@ -2114,6 +2139,15 @@ void RandomizerOnActorInitHandler(void* actorRef) { return; } + // Turn MQ switch into toggle + if (actor->id == ACTOR_OBJ_SWITCH && gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL && (actor->params & 7) == 3) { + auto dungeon = + OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); + if (dungeon->IsMQ()) { + actor->params |= 0x10; + } + } + // In ER, once Link has spawned we know the scene has loaded, so we can sanitize the last known entrance type if (actor->id == ACTOR_PLAYER && RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES)) { Grotto_SanitizeEntranceType(); diff --git a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c index 3dee59f2767..cb59641fd4b 100644 --- a/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c +++ b/soh/src/overlays/actors/ovl_En_Okarina_Tag/z_en_okarina_tag.c @@ -79,7 +79,8 @@ void EnOkarinaTag_Init(Actor* thisx, PlayState* play) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 当り?\t\t ☆☆☆☆☆ %d\n" VT_RST, this->unk_158); osSyncPrintf("\n\n"); - if ((this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag))) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETED, + (this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag)), this)) { Actor_Kill(&this->actor); } else { switch (this->type) { @@ -113,7 +114,8 @@ void func_80ABEF2C(EnOkarinaTag* this, PlayState* play) { player = GET_PLAYER(play); this->unk_15A++; - if ((this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag))) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETED, + (this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag)), this)) { this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED; } else { if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { @@ -148,7 +150,7 @@ void func_80ABF0CC(EnOkarinaTag* this, PlayState* play) { this->actionFunc = func_80ABEF2C; } else { if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { - if (this->switchFlag >= 0) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETE, this->switchFlag >= 0, this)) { Flags_SetSwitch(play, this->switchFlag); } if (play->sceneNum == SCENE_WATER_TEMPLE) { @@ -167,7 +169,7 @@ void func_80ABF0CC(EnOkarinaTag* this, PlayState* play) { (play->msgCtx.ocarinaMode == OCARINA_MODE_07) || (play->msgCtx.ocarinaMode == OCARINA_MODE_08) || (play->msgCtx.ocarinaMode == OCARINA_MODE_09) || (play->msgCtx.ocarinaMode == OCARINA_MODE_0A) || (play->msgCtx.ocarinaMode == OCARINA_MODE_0D)) { - if (this->switchFlag >= 0) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETE, this->switchFlag >= 0, this)) { Flags_SetSwitch(play, this->switchFlag); } play->msgCtx.ocarinaMode = OCARINA_MODE_04; @@ -190,7 +192,8 @@ void func_80ABF28C(EnOkarinaTag* this, PlayState* play) { this->unk_15A++; if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { - if ((this->switchFlag >= 0) && Flags_GetSwitch(play, this->switchFlag)) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETED, + (this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag)), this)) { this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED; } else if (((this->type != 4) || GameInteractor_Should(VB_BE_ELIGIBLE_TO_OPEN_DOT, @@ -237,7 +240,7 @@ void func_80ABF4C8(EnOkarinaTag* this, PlayState* play) { this->actionFunc = func_80ABF28C; } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); - if (this->switchFlag >= 0) { + if (GameInteractor_Should(VB_OKARINA_TAG_COMPLETE, this->switchFlag >= 0, this)) { Flags_SetSwitch(play, this->switchFlag); } switch (this->type) {