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
This commit is contained in:
Demur Rumed 2025-07-31 05:27:20 +00:00
commit b04e478842
3 changed files with 59 additions and 6 deletions

View file

@ -1362,6 +1362,22 @@ typedef enum {
// - `*EnDs` // - `*EnDs`
VB_OFFER_BLUE_POTION, 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` // #### `result`
// ```c // ```c
// CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) // CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD)

View file

@ -48,6 +48,7 @@ extern "C" {
#include "src/overlays/actors/ovl_En_Ds/z_en_ds.h" #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_Gm/z_en_gm.h"
#include "src/overlays/actors/ovl_En_Js/z_en_js.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_En_Door/z_en_door.h"
#include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h" #include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h"
#include "src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.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; *should |= RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE) == RO_GENERIC_OFF;
break; 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: { case VB_GRANNY_SAY_INSUFFICIENT_RUPEES: {
if (EnDs_RandoCanGetGrannyItem()) { if (EnDs_RandoCanGetGrannyItem()) {
*should = gSaveContext.rupees < *should = gSaveContext.rupees <
@ -2114,6 +2139,15 @@ void RandomizerOnActorInitHandler(void* actorRef) {
return; 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 // 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)) { if (actor->id == ACTOR_PLAYER && RAND_GET_OPTION(RSK_SHUFFLE_ENTRANCES)) {
Grotto_SanitizeEntranceType(); Grotto_SanitizeEntranceType();

View file

@ -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(VT_FGCOL(GREEN) "☆☆☆☆☆ 当り?\t\t ☆☆☆☆☆ %d\n" VT_RST, this->unk_158);
osSyncPrintf("\n\n"); 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); Actor_Kill(&this->actor);
} else { } else {
switch (this->type) { switch (this->type) {
@ -113,7 +114,8 @@ void func_80ABEF2C(EnOkarinaTag* this, PlayState* play) {
player = GET_PLAYER(play); player = GET_PLAYER(play);
this->unk_15A++; 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; this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED;
} else { } else {
if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) {
@ -148,7 +150,7 @@ void func_80ABF0CC(EnOkarinaTag* this, PlayState* play) {
this->actionFunc = func_80ABEF2C; this->actionFunc = func_80ABEF2C;
} else { } else {
if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { 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); Flags_SetSwitch(play, this->switchFlag);
} }
if (play->sceneNum == SCENE_WATER_TEMPLE) { 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_07) || (play->msgCtx.ocarinaMode == OCARINA_MODE_08) ||
(play->msgCtx.ocarinaMode == OCARINA_MODE_09) || (play->msgCtx.ocarinaMode == OCARINA_MODE_0A) || (play->msgCtx.ocarinaMode == OCARINA_MODE_09) || (play->msgCtx.ocarinaMode == OCARINA_MODE_0A) ||
(play->msgCtx.ocarinaMode == OCARINA_MODE_0D)) { (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); Flags_SetSwitch(play, this->switchFlag);
} }
play->msgCtx.ocarinaMode = OCARINA_MODE_04; play->msgCtx.ocarinaMode = OCARINA_MODE_04;
@ -190,7 +192,8 @@ void func_80ABF28C(EnOkarinaTag* this, PlayState* play) {
this->unk_15A++; this->unk_15A++;
if ((this->ocarinaSong != 6) || (gSaveContext.scarecrowSpawnSongSet)) { 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; this->actor.flags &= ~ACTOR_FLAG_ATTENTION_ENABLED;
} else if (((this->type != 4) || } else if (((this->type != 4) ||
GameInteractor_Should(VB_BE_ELIGIBLE_TO_OPEN_DOT, GameInteractor_Should(VB_BE_ELIGIBLE_TO_OPEN_DOT,
@ -237,7 +240,7 @@ void func_80ABF4C8(EnOkarinaTag* this, PlayState* play) {
this->actionFunc = func_80ABF28C; this->actionFunc = func_80ABF28C;
} else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) { } else if (play->msgCtx.ocarinaMode == OCARINA_MODE_03) {
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); 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); Flags_SetSwitch(play, this->switchFlag);
} }
switch (this->type) { switch (this->type) {