From ae62048910acf9b83f207fcb6aa2512408584a98 Mon Sep 17 00:00:00 2001 From: Jordan Longstaff Date: Wed, 16 Sep 2026 14:15:17 -0400 Subject: [PATCH] Hookify three Glitch Restoration options (#7200) --- .../Restorations/EarlyEyeballFrog.cpp | 13 ++++++++++ .../Restorations/QuickBongoKill.cpp | 13 ++++++++++ .../Restorations/QuickPutaway.cpp | 13 ++++++++++ .../vanilla-behavior/GIVanillaBehavior.h | 24 +++++++++++++++++++ .../overlays/actors/ovl_Boss_Sst/z_boss_sst.c | 16 ++++--------- soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c | 14 +++++------ .../actors/ovl_player_actor/z_player.c | 3 +-- 7 files changed, 75 insertions(+), 21 deletions(-) create mode 100644 soh/soh/Enhancements/Restorations/EarlyEyeballFrog.cpp create mode 100644 soh/soh/Enhancements/Restorations/QuickBongoKill.cpp create mode 100644 soh/soh/Enhancements/Restorations/QuickPutaway.cpp diff --git a/soh/soh/Enhancements/Restorations/EarlyEyeballFrog.cpp b/soh/soh/Enhancements/Restorations/EarlyEyeballFrog.cpp new file mode 100644 index 0000000000..5e8e2007a0 --- /dev/null +++ b/soh/soh/Enhancements/Restorations/EarlyEyeballFrog.cpp @@ -0,0 +1,13 @@ +#include + +#include "soh/cvar_prefixes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/ShipInit.hpp" + +static constexpr const char* CVAR_EARLY_EYEBALL_FROG = CVAR_ENHANCEMENT("EarlyEyeballFrog"); + +static void RegisterEarlyEyeballFrog() { + COND_VB_SHOULD(VB_GIVE_EYEBALL_FROG_EARLY, CVarGetInteger(CVAR_EARLY_EYEBALL_FROG, 0), { *should = true; }); +} + +static RegisterShipInitFunc initFunc(RegisterEarlyEyeballFrog, { CVAR_EARLY_EYEBALL_FROG }); diff --git a/soh/soh/Enhancements/Restorations/QuickBongoKill.cpp b/soh/soh/Enhancements/Restorations/QuickBongoKill.cpp new file mode 100644 index 0000000000..2db7fa9a9c --- /dev/null +++ b/soh/soh/Enhancements/Restorations/QuickBongoKill.cpp @@ -0,0 +1,13 @@ +#include + +#include "soh/cvar_prefixes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/ShipInit.hpp" + +static constexpr const char* CVAR_QUICK_BONGO_KILL = CVAR_ENHANCEMENT("QuickBongoKill"); + +static void RegisterQuickBongoKill() { + COND_VB_SHOULD(VB_ALLOW_QUICK_BONGO_KILL, CVarGetInteger(CVAR_QUICK_BONGO_KILL, 0), { *should = true; }); +} + +static RegisterShipInitFunc initFunc(RegisterQuickBongoKill, { CVAR_QUICK_BONGO_KILL }); diff --git a/soh/soh/Enhancements/Restorations/QuickPutaway.cpp b/soh/soh/Enhancements/Restorations/QuickPutaway.cpp new file mode 100644 index 0000000000..cc7ec3adbf --- /dev/null +++ b/soh/soh/Enhancements/Restorations/QuickPutaway.cpp @@ -0,0 +1,13 @@ +#include + +#include "soh/cvar_prefixes.h" +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/ShipInit.hpp" + +static constexpr const char* CVAR_QUICK_PUTAWAY = CVAR_ENHANCEMENT("QuickPutaway"); + +static void RegisterQuickPutaway() { + COND_VB_SHOULD(VB_ALLOW_QUICK_PUTAWAY, CVarGetInteger(CVAR_QUICK_PUTAWAY, 0), { *should = true; }); +} + +static RegisterShipInitFunc initFunc(RegisterQuickPutaway, { CVAR_QUICK_PUTAWAY }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index ef1deb6931..19f9bfb9ef 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -17,6 +17,22 @@ typedef enum { // - `int32_t` (entrance index) (promoted from `uint16_t` by va_arg) VB_ALLOW_ENTRANCE_CS_FOR_EITHER_AGE, + // #### `result` + // ```c + // (this->actionFunc != BossSst_HeadLurk) && (this->actionFunc != BossSst_HeadIntro) + // ``` + // #### `args` + // - None + VB_ALLOW_QUICK_BONGO_KILL, + + // #### `result` + // ```c + // !(this->stateFlags1 & PLAYER_STATE1_START_CHANGING_HELD_ITEM) + // ``` + // #### `args` + // - None + VB_ALLOW_QUICK_PUTAWAY, + // #### `result` // ```c // sPuzzleState == 0xF @@ -1011,6 +1027,14 @@ typedef enum { // - `*EnJs` VB_GIVE_BOMBCHUS_FROM_CARPET_SALESMAN, + // #### `result` + // ```c + // false + // ``` + // #### `args` + // - None + VB_GIVE_EYEBALL_FROG_EARLY, + // #### `result` // ```c // true diff --git a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c index 0209a77872..d293b1565e 100644 --- a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c +++ b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c @@ -377,21 +377,12 @@ void BossSst_HeadSetupLurk(BossSst* this) { } void BossSst_HeadLurk(BossSst* this, PlayState* play) { - if (CVarGetInteger(CVAR_ENHANCEMENT("QuickBongoKill"), 0)) { - this->colliderCyl.base.acFlags |= AC_ON; - } - if (this->actor.yDistToPlayer < 1000.0f) { BossSst_HeadSetupIntro(this, play); } } void BossSst_HeadSetupIntro(BossSst* this, PlayState* play) { - // Make sure to restore original behavior if the quick kill didn't happen - if (CVarGetInteger(CVAR_ENHANCEMENT("QuickBongoKill"), 0)) { - this->colliderCyl.base.acFlags &= ~AC_ON; - } - Player* player = GET_PLAYER(play); this->timer = 611; @@ -2632,7 +2623,8 @@ void BossSst_UpdateHand(Actor* thisx, PlayState* play) { CollisionCheck_SetAT(play, &play->colChkCtx, &this->colliderJntSph.base); } - if ((sHead->actionFunc != BossSst_HeadLurk) && (sHead->actionFunc != BossSst_HeadIntro) && + if (GameInteractor_Should(VB_ALLOW_QUICK_BONGO_KILL, + (this->actionFunc != BossSst_HeadLurk) && (this->actionFunc != BossSst_HeadIntro)) && (this->colliderJntSph.base.acFlags & AC_ON)) { CollisionCheck_SetAC(play, &play->colChkCtx, &this->colliderJntSph.base); } @@ -2688,8 +2680,8 @@ void BossSst_UpdateHead(Actor* thisx, PlayState* play) { CollisionCheck_SetAT(play, &play->colChkCtx, &this->colliderJntSph.base); } - if ((this->actionFunc != BossSst_HeadLurk || CVarGetInteger(CVAR_ENHANCEMENT("QuickBongoKill"), 0)) && - (this->actionFunc != BossSst_HeadIntro)) { + if (GameInteractor_Should(VB_ALLOW_QUICK_BONGO_KILL, + (this->actionFunc != BossSst_HeadLurk) && (this->actionFunc != BossSst_HeadIntro))) { if (this->colliderCyl.base.acFlags & AC_ON) { CollisionCheck_SetAC(play, &play->colChkCtx, &this->colliderCyl.base); } diff --git a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c index 45b37141e8..4f4ee702c5 100644 --- a/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c +++ b/soh/src/overlays/actors/ovl_En_Kz/z_en_kz.c @@ -126,7 +126,7 @@ s16 EnKz_UpdateTalkState(PlayState* play, Actor* thisx) { switch (Message_GetState(&play->msgCtx)) { case TEXT_STATE_DONE: - if (CVarGetInteger(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 0)) { + if (GameInteractor_Should(VB_GIVE_EYEBALL_FROG_EARLY, false)) { if (Message_ShouldAdvance(play)) { talkState = NPC_TALK_STATE_ITEM_GIVEN; } @@ -147,7 +147,7 @@ s16 EnKz_UpdateTalkState(PlayState* play, Actor* thisx) { } break; case TEXT_STATE_CLOSING: - if (CVarGetInteger(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 0)) { + if (GameInteractor_Should(VB_GIVE_EYEBALL_FROG_EARLY, false)) { talkState = NPC_TALK_STATE_IDLE; switch (this->actor.textId) { case 0x4012: @@ -181,7 +181,7 @@ s16 EnKz_UpdateTalkState(PlayState* play, Actor* thisx) { } if (this->actor.textId == 0x4014) { if (play->msgCtx.choiceIndex == 0) { - if (!CVarGetInteger(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 0)) { + if (!GameInteractor_Should(VB_GIVE_EYEBALL_FROG_EARLY, false)) { EnKz_SetupGetItem(this, play); } talkState = NPC_TALK_STATE_ACTION; @@ -287,12 +287,12 @@ void func_80A9CB18(EnKz* this, PlayState* play) { this->actor.textId = 0x4014; this->sfxPlayed = false; player->actor.textId = this->actor.textId; - if (!CVarGetInteger(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 0)) { + if (!GameInteractor_Should(VB_GIVE_EYEBALL_FROG_EARLY, false)) { this->isTrading = true; } return; } - if (!CVarGetInteger(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 0)) { + if (!GameInteractor_Should(VB_GIVE_EYEBALL_FROG_EARLY, false)) { this->isTrading = false; } if (Flags_GetInfTable(INFTABLE_139)) { @@ -455,7 +455,7 @@ void EnKz_StopMweep(EnKz* this, PlayState* play) { void EnKz_Wait(EnKz* this, PlayState* play) { if (this->interactInfo.talkState == NPC_TALK_STATE_ACTION) { - if (CVarGetInteger(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 0)) { + if (GameInteractor_Should(VB_GIVE_EYEBALL_FROG_EARLY, false)) { this->interactInfo.talkState = NPC_TALK_STATE_IDLE; } this->actionFunc = EnKz_SetupGetItem; @@ -476,7 +476,7 @@ void EnKz_SetupGetItem(EnKz* this, PlayState* play) { this->interactInfo.talkState = NPC_TALK_STATE_TALKING; this->actionFunc = EnKz_StartTimer; } else { - if (CVarGetInteger(CVAR_ENHANCEMENT("EarlyEyeballFrog"), 0)) { + if (GameInteractor_Should(VB_GIVE_EYEBALL_FROG_EARLY, false)) { getItemId = Actor_GetPlayerExchangeItemId(play) == EXCH_ITEM_PRESCRIPTION ? GI_FROG : GI_TUNIC_ZORA; } else { getItemId = this->isTrading ? GI_FROG : GI_TUNIC_ZORA; diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 61d8fc082a..b5bbc6c58f 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -2612,8 +2612,7 @@ void Player_StartChangingHeldItem(Player* this, PlayState* play) { void Player_UpdateItems(Player* this, PlayState* play) { if ((this->actor.category == ACTORCAT_PLAYER) && - (CVarGetInteger(CVAR_ENHANCEMENT("QuickPutaway"), 0) || - !(this->stateFlags1 & PLAYER_STATE1_START_CHANGING_HELD_ITEM)) && + GameInteractor_Should(VB_ALLOW_QUICK_PUTAWAY, !(this->stateFlags1 & PLAYER_STATE1_START_CHANGING_HELD_ITEM)) && ((this->heldItemAction == this->itemAction) || (this->stateFlags1 & PLAYER_STATE1_SHIELDING)) && (gSaveContext.health != 0) && (play->csCtx.state == CS_STATE_IDLE) && (this->csAction == 0) && (play->shootingGalleryStatus == 0) && (play->activeCamera == CAM_ID_MAIN) &&