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) {