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 186307aed..ce47d1593 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 d73cebca7..808915933 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 3dee59f27..cb59641fd 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) {