From 236c9c81f59795ec75512c932e7b6c666b098e73 Mon Sep 17 00:00:00 2001 From: Jordan Longstaff Date: Wed, 22 Jul 2026 23:56:43 -0400 Subject: [PATCH] Hookify Bombchu Bowling options (#6968) Cuccos get destroyed when options turned on --- .../Enhancements/Minigames/BombchuBowling.cpp | 95 +++++++++++++++++++ .../vanilla-behavior/GIVanillaBehavior.h | 16 ++++ .../ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c | 9 +- 3 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 soh/soh/Enhancements/Minigames/BombchuBowling.cpp diff --git a/soh/soh/Enhancements/Minigames/BombchuBowling.cpp b/soh/soh/Enhancements/Minigames/BombchuBowling.cpp new file mode 100644 index 0000000000..24ae8246c4 --- /dev/null +++ b/soh/soh/Enhancements/Minigames/BombchuBowling.cpp @@ -0,0 +1,95 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "functions.h" +extern PlayState* gPlayState; +} + +#define CVAR_BOWLING_NAME CVAR_ENHANCEMENT("CustomizeBombchuBowling") +#define CVAR_BOWLING_VALUE CVarGetInteger(CVAR_BOWLING_NAME, 0) + +#define CVAR_CUCCO_SMALL_NAME CVAR_ENHANCEMENT("BombchuBowlingNoSmallCucco") +#define CVAR_CUCCO_SMALL_VALUE CVarGetInteger(CVAR_CUCCO_SMALL_NAME, 0) + +#define CVAR_CUCCO_BIG_NAME CVAR_ENHANCEMENT("BombchuBowlingNoBigCucco") +#define CVAR_CUCCO_BIG_VALUE CVarGetInteger(CVAR_CUCCO_BIG_NAME, 0) + +static constexpr s32 CUCCO_BOWLING_AMMO_DEFAULT = 10; +#define CVAR_BOWLING_AMMO_NAME CVAR_ENHANCEMENT("BombchuBowlingAmmo") +#define CVAR_BOWLING_AMMO_VALUE CVarGetInteger(CVAR_BOWLING_AMMO_NAME, CUCCO_BOWLING_AMMO_DEFAULT) + +static constexpr f32 CUCCO_SEARCH_Z = -520.0f; + +typedef enum { + CUCCO_INDEX_SMALL, + CUCCO_INDEX_BIG, +} BombchuBowlingCuccoIndex; + +static void KillSmallCucco() { + Actor* cucco = gPlayState->actorCtx.actorLists[ACTORCAT_PROP].head; + + while (cucco != NULL) { + if (cucco->id == ACTOR_EN_SYATEKI_NIW && cucco->home.pos.z > CUCCO_SEARCH_Z) { + Actor_Kill(cucco); + break; + } + cucco = cucco->next; + } +} + +static void KillBigCucco() { + Actor* cucco = gPlayState->actorCtx.actorLists[ACTORCAT_PROP].head; + + while (cucco != NULL) { + if (cucco->id == ACTOR_EN_SYATEKI_NIW && cucco->home.pos.z < CUCCO_SEARCH_Z) { + Actor_Kill(cucco); + break; + } + cucco = cucco->next; + } +} + +static void RegisterBombchuBowlingNoSmallCucco() { + s32 noCucco = CVAR_BOWLING_VALUE && CVAR_CUCCO_SMALL_VALUE; + + if (noCucco && gPlayState != NULL && gPlayState->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY) { + KillSmallCucco(); + } + + COND_VB_SHOULD(VB_SPAWN_BOMBCHU_BOWLING_CUCCOS, noCucco, { + s32 index = va_arg(args, s32); + if (index == CUCCO_INDEX_SMALL) { + *should = false; + } + }); +} + +static void RegisterBombchuBowlingNoBigCucco() { + s32 noCucco = CVAR_BOWLING_VALUE && CVAR_CUCCO_BIG_VALUE; + + if (noCucco && gPlayState != NULL && gPlayState->sceneNum == SCENE_BOMBCHU_BOWLING_ALLEY) { + KillBigCucco(); + } + + COND_VB_SHOULD(VB_SPAWN_BOMBCHU_BOWLING_CUCCOS, noCucco, { + s32 index = va_arg(args, s32); + if (index == CUCCO_INDEX_BIG) { + *should = false; + } + }); +} + +static void RegisterBombchuBowlingAmmo() { + COND_VB_SHOULD(VB_SET_BOMBCHU_BOWLING_AMMO, + CVAR_BOWLING_VALUE && (CVAR_BOWLING_AMMO_VALUE != CUCCO_BOWLING_AMMO_DEFAULT), { + gPlayState->bombchuBowlingStatus = CVAR_BOWLING_AMMO_VALUE; + *should = false; + }); +} + +static RegisterShipInitFunc initFunc_SmallCucco(RegisterBombchuBowlingNoSmallCucco, + { CVAR_BOWLING_NAME, CVAR_CUCCO_SMALL_NAME }); +static RegisterShipInitFunc initFunc_BigCucco(RegisterBombchuBowlingNoBigCucco, + { CVAR_BOWLING_NAME, CVAR_CUCCO_BIG_NAME }); +static RegisterShipInitFunc initFunc_Ammo(RegisterBombchuBowlingAmmo, { CVAR_BOWLING_NAME, CVAR_BOWLING_AMMO_NAME }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index f8196a1a11..81c2acc2f9 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2340,6 +2340,14 @@ typedef enum { // - `*EnGb` VB_SELL_POES_TO_POE_COLLECTOR, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `None` + VB_SET_BOMBCHU_BOWLING_AMMO, + // #### `result` // ```c // true @@ -2546,6 +2554,14 @@ typedef enum { // - `*BossVa` VB_SPAWN_BLUE_WARP, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `s32` (Cucco index; 0 = small, 1 = big) + VB_SPAWN_BOMBCHU_BOWLING_CUCCOS, + // #### `result` // ```c // this->timer == 4 diff --git a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c index 32d8bbcaa0..cb89cebd60 100644 --- a/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c +++ b/soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c @@ -75,10 +75,7 @@ void EnBomBowlMan_Init(Actor* thisx, PlayState* play2) { Actor_SetScale(&this->actor, 0.013f); for (i = 0; i < 2; i++) { - if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeBombchuBowling"), 0) && - CVarGetInteger(i == 0 ? CVAR_ENHANCEMENT("BombchuBowlingNoSmallCucco") - : CVAR_ENHANCEMENT("BombchuBowlingNoBigCucco"), - 0)) { + if (!GameInteractor_Should(VB_SPAWN_BOMBCHU_BOWLING_CUCCOS, true, i)) { continue; } @@ -321,9 +318,7 @@ void EnBomBowlMan_HandlePlayChoice(EnBomBowlMan* this, PlayState* play) { Rupees_ChangeBy(-30); this->minigamePlayStatus = 1; this->wallStatus[0] = this->wallStatus[1] = 0; - if (CVarGetInteger(CVAR_ENHANCEMENT("CustomizeBombchuBowling"), 0)) { - play->bombchuBowlingStatus = CVarGetInteger(CVAR_ENHANCEMENT("BombchuBowlingAmmo"), 10); - } else { + if (GameInteractor_Should(VB_SET_BOMBCHU_BOWLING_AMMO, true)) { play->bombchuBowlingStatus = 10; } Flags_SetSwitch(play, 0x38);