summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Dubé <159546+serprex@users.noreply.github.com>2026-08-14 22:24:03 +0000
committerGitHub <noreply@github.com>2026-08-14 22:24:03 +0000
commitca0a17cfe717a1760e040e519a033b621c73d3ab (patch)
tree01dfc3e59191c86be09b33682df688092847735c
parentafcfe4f7bf7f5fd1e4314ea21d123756cd772195 (diff)
bombchu bowling setting: first item (#7070)
desirable for speedrun settings that want less variance. also use for moving rando logic into hooks
-rw-r--r--soh/soh/Enhancements/Minigames/BombchuBowling.cpp17
-rw-r--r--soh/soh/Enhancements/enhancementTypes.h10
-rw-r--r--soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h17
-rw-r--r--soh/soh/Enhancements/randomizer/SeedContext.h1
-rw-r--r--soh/soh/Enhancements/randomizer/hook_handlers.cpp31
-rw-r--r--soh/soh/SohGui/SohMenuEnhancements.cpp19
-rw-r--r--soh/src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.c65
7 files changed, 117 insertions, 43 deletions
diff --git a/soh/soh/Enhancements/Minigames/BombchuBowling.cpp b/soh/soh/Enhancements/Minigames/BombchuBowling.cpp
index 24ae8246c..1d734d7f1 100644
--- a/soh/soh/Enhancements/Minigames/BombchuBowling.cpp
+++ b/soh/soh/Enhancements/Minigames/BombchuBowling.cpp
@@ -1,8 +1,10 @@
+#include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "functions.h"
+#include "src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h"
extern PlayState* gPlayState;
}
@@ -19,6 +21,9 @@ 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)
+#define CVAR_BOWLING_FIRST_PRIZE_NAME CVAR_ENHANCEMENT("BombchuBowlingFirstPrize")
+#define CVAR_BOWLING_FIRST_PRIZE_VALUE CVarGetInteger(CVAR_BOWLING_FIRST_PRIZE_NAME, BOWLING_FIRST_PRIZE_RANDOM)
+
static constexpr f32 CUCCO_SEARCH_Z = -520.0f;
typedef enum {
@@ -88,8 +93,20 @@ static void RegisterBombchuBowlingAmmo() {
});
}
+static void RegisterBombchuBowlingFirstPrize() {
+ COND_VB_SHOULD(VB_SET_BOMBCHU_BOWLING_PRIZE_SELECT,
+ !IS_RANDO && CVAR_BOWLING_VALUE && (CVAR_BOWLING_FIRST_PRIZE_VALUE != BOWLING_FIRST_PRIZE_RANDOM), {
+ EnBomBowlMan* bowlMan = va_arg(args, EnBomBowlMan*);
+ s16 prizeSelect = CVAR_BOWLING_FIRST_PRIZE_VALUE - 1;
+ bowlMan->prizeSelect = prizeSelect;
+ *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 });
+static RegisterShipInitFunc initFunc_FirstPrize(RegisterBombchuBowlingFirstPrize,
+ { CVAR_BOWLING_NAME, CVAR_BOWLING_FIRST_PRIZE_NAME, "IS_RANDO" });
diff --git a/soh/soh/Enhancements/enhancementTypes.h b/soh/soh/Enhancements/enhancementTypes.h
index 6dced4263..e235bba4a 100644
--- a/soh/soh/Enhancements/enhancementTypes.h
+++ b/soh/soh/Enhancements/enhancementTypes.h
@@ -124,6 +124,16 @@ typedef enum {
INGO_RACE_NONE,
} IngoRaceType;
+// The Bombchu Bowling prize cycle always runs in this order, only the entry it starts on is random
+typedef enum {
+ BOWLING_FIRST_PRIZE_RANDOM,
+ BOWLING_FIRST_PRIZE_BOMB_BAG,
+ BOWLING_FIRST_PRIZE_PURPLE_RUPEE,
+ BOWLING_FIRST_PRIZE_BOMBCHUS,
+ BOWLING_FIRST_PRIZE_HEART_PIECE,
+ BOWLING_FIRST_PRIZE_BOMBS,
+} BombchuBowlingFirstPrize;
+
typedef enum {
RANDOMIZE_OFF,
RANDOMIZE_ON_NEW_SCENE,
diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
index e41669089..85d148333 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -2482,6 +2482,23 @@ typedef enum {
// true
// ```
// #### `args`
+ // - `*EnBomBowlMan`
+ // - `s16*` (prize to show, an `ExItemType`)
+ VB_SET_BOMBCHU_BOWLING_PRIZE,
+
+ // #### `result`
+ // ```c
+ // true
+ // ```
+ // #### `args`
+ // - `*EnBomBowlMan`
+ VB_SET_BOMBCHU_BOWLING_PRIZE_SELECT,
+
+ // #### `result`
+ // ```c
+ // true
+ // ```
+ // #### `args`
// - `int32_t` (button - promoted from `s16`)
VB_SET_BUTTON_ITEM_FROM_C_BUTTON_SLOT,
diff --git a/soh/soh/Enhancements/randomizer/SeedContext.h b/soh/soh/Enhancements/randomizer/SeedContext.h
index 5dc7d6ee2..8630e600c 100644
--- a/soh/soh/Enhancements/randomizer/SeedContext.h
+++ b/soh/soh/Enhancements/randomizer/SeedContext.h
@@ -1,7 +1,6 @@
#pragma once
#include "randomizerTypes.h"
-#include "z64save.h"
#include "item_override.h"
#include "hint.h"
#include "fishsanity.h"
diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
index 78df18747..fc4c7b906 100644
--- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp
+++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
@@ -45,6 +45,7 @@ extern "C" {
#include "src/overlays/actors/ovl_En_Box/z_en_box.h"
#include "src/overlays/actors/ovl_En_Skj/z_en_skj.h"
#include "src/overlays/actors/ovl_En_Hy/z_en_hy.h"
+#include "src/overlays/actors/ovl_En_Bom_Bowl_Man/z_en_bom_bowl_man.h"
#include "src/overlays/actors/ovl_En_Bom_Bowl_Pit/z_en_bom_bowl_pit.h"
#include "src/overlays/actors/ovl_En_Ge1/z_en_ge1.h"
#include "src/overlays/actors/ovl_En_Ge2/z_en_ge2.h"
@@ -1940,6 +1941,36 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
*should = INV_CONTENT((RAND_GET_OPTION(RSK_BOMBCHU_BAG) ? ITEM_BOMBCHU : ITEM_BOMB)) != ITEM_NONE;
break;
}
+ case VB_SET_BOMBCHU_BOWLING_PRIZE_SELECT: {
+ EnBomBowlMan* bowlMan = va_arg(args, EnBomBowlMan*);
+ bowlMan->prizeSelect = 0;
+ *should = false;
+ break;
+ }
+ case VB_SET_BOMBCHU_BOWLING_PRIZE: {
+ EnBomBowlMan* bowlMan = va_arg(args, EnBomBowlMan*);
+ s16* prize = va_arg(args, s16*);
+ switch (bowlMan->prizeSelect) {
+ case 0:
+ *prize = Flags_GetItemGetInf(ITEMGETINF_11) ? EXITEM_PURPLE_RUPEE_BOWLING : EXITEM_BOMB_BAG_BOWLING;
+ break;
+ case 1:
+ *prize =
+ Flags_GetItemGetInf(ITEMGETINF_12) ? EXITEM_PURPLE_RUPEE_BOWLING : EXITEM_HEART_PIECE_BOWLING;
+ break;
+ case 2:
+ *prize = EXITEM_BOMBCHUS_BOWLING;
+ break;
+ case 3:
+ *prize = EXITEM_PURPLE_RUPEE_BOWLING;
+ break;
+ case 4:
+ *prize = EXITEM_BOMBS_BOWLING;
+ break;
+ }
+ *should = false;
+ break;
+ }
case VB_SHOULD_CHECK_FOR_FISHING_RECORD: {
f32 sFishOnHandLength = *va_arg(args, f32*);
*should = *should || ShouldGiveFishingPrize(sFishOnHandLength);
diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp
index 9393eaf95..5672a45f7 100644
--- a/soh/soh/SohGui/SohMenuEnhancements.cpp
+++ b/soh/soh/SohGui/SohMenuEnhancements.cpp
@@ -5,13 +5,14 @@
#include <soh/OTRGlobals.h>
#include <soh/Enhancements/cosmetics/authenticGfxPatches.h>
#include <soh/Enhancements/TimeDisplay/TimeDisplay.h>
-#include "soh/Enhancements/randomizer/randomizer.h"
#include "soh/Enhancements/Restorations/GetItemManipulation.h"
+#include "soh/Enhancements/randomizer/SeedContext.h"
#include <ship/Context.h>
extern "C" {
#include "functions.h"
#include "variables.h"
+#include "macros.h"
extern PlayState* gPlayState;
}
@@ -87,6 +88,15 @@ static const std::map<int32_t, const char*> sleepingWaterfallOptions = {
{ WATERFALL_NEVER, "Never" },
};
+static const std::map<int32_t, const char*> bombchuBowlingFirstPrizeOptions = {
+ { BOWLING_FIRST_PRIZE_RANDOM, "Random" },
+ { BOWLING_FIRST_PRIZE_BOMB_BAG, "Bomb Bag" },
+ { BOWLING_FIRST_PRIZE_PURPLE_RUPEE, "Purple Rupee" },
+ { BOWLING_FIRST_PRIZE_BOMBCHUS, "Bombchus" },
+ { BOWLING_FIRST_PRIZE_HEART_PIECE, "Heart Piece" },
+ { BOWLING_FIRST_PRIZE_BOMBS, "Bombs" },
+};
+
static const std::map<int32_t, const char*> allPowers = {
{ DAMAGE_VANILLA, "Vanilla (1x)" }, { DAMAGE_DOUBLE, "Double (2x)" },
{ DAMAGE_QUADRUPLE, "Quadruple (4x)" }, { DAMAGE_OCTUPLE, "Octuple (8x)" },
@@ -1524,6 +1534,13 @@ void SohMenu::AddMenuEnhancements() {
.DefaultValue(10)
.Format("%d bombchus")
.Tooltip("The number of Bombchus available at the start of the Bombchu Bowling minigame."));
+ AddWidget(path, "First Prize", WIDGET_CVAR_COMBOBOX)
+ .CVar(CVAR_ENHANCEMENT("BombchuBowlingFirstPrize"))
+ .PreFunc(bombchuBowlingDisabledFunc)
+ .Options(ComboboxOptions()
+ .ComboMap(bombchuBowlingFirstPrizeOptions)
+ .DefaultIndex(BOWLING_FIRST_PRIZE_RANDOM)
+ .Tooltip("The prize the cycle starts on."));
AddWidget(path, "Horseback Archery", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Customize Behavior##HBA", WIDGET_CVAR_CHECKBOX)
.CVar(CVAR_ENHANCEMENT("CustomizeHorsebackArchery"))
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 ea9b13a35..baf0a27d0 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
@@ -3,8 +3,6 @@
#include "overlays/actors/ovl_En_Syateki_Niw/z_en_syateki_niw.h"
#include "overlays/actors/ovl_En_Ex_Item/z_en_ex_item.h"
#include "objects/object_bg/object_bg.h"
-#include "soh/OTRGlobals.h"
-#include "soh/Enhancements/game-interactor/GameInteractor.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS \
@@ -88,7 +86,9 @@ void EnBomBowlMan_Init(Actor* thisx, PlayState* play2) {
}
}
- this->prizeSelect = IS_RANDO ? 0 : (s16)Rand_ZeroFloat(4.99f);
+ if (GameInteractor_Should(VB_SET_BOMBCHU_BOWLING_PRIZE_SELECT, true, this)) {
+ this->prizeSelect = (s16)Rand_ZeroFloat(4.99f);
+ }
this->actor.targetMode = 1;
this->actionFunc = EnBomBowMan_SetupWaitAsleep;
}
@@ -174,17 +174,9 @@ void EnBomBowMan_CheckBeatenDC(EnBomBowlMan* this, PlayState* play) {
this->eyeMode = CHU_GIRL_EYES_AWAKE;
this->blinkTimer = (s16)Rand_ZeroFloat(60.0f) + 20;
- bool bombchuBowlingClosed;
- if (IS_RANDO) {
- // when rando'd, check if we have bombchus if chus are in logic
- // and check if we have a bomb bag if chus aren't in logic
- u8 explosive = Randomizer_GetSettingValue(RSK_BOMBCHU_BAG) ? ITEM_BOMBCHU : ITEM_BOMB;
- bombchuBowlingClosed = (INV_CONTENT(explosive) == ITEM_NONE);
- } else {
- // if not rando'd, check if we have beaten Dodongo's Cavern
- bombchuBowlingClosed = !((Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) || BREG(2));
- }
- if (bombchuBowlingClosed) {
+ // Check for beaten Dodongo's Cavern
+ if (!GameInteractor_Should(VB_BE_ABLE_TO_PLAY_BOMBCHU_BOWLING,
+ (Flags_GetEventChkInf(EVENTCHKINF_USED_DODONGOS_CAVERN_BLUE_WARP)) || BREG(2))) {
this->actionFunc = EnBomBowMan_WaitNotBeatenDC;
} else {
this->actor.textId = 0x18;
@@ -407,39 +399,30 @@ void EnBomBowMan_ChooseShowPrize(EnBomBowlMan* this, PlayState* play) {
SkelAnime_Update(&this->skelAnime);
if (this->prizeRevealTimer == 0) {
- switch (this->prizeSelect) {
- case 0:
- prizeTemp = EXITEM_BOMB_BAG_BOWLING;
- if (Flags_GetItemGetInf(ITEMGETINF_11)) {
- prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING;
- }
- break;
- case 1:
- if (!IS_RANDO) {
- prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING;
- } else {
- prizeTemp = EXITEM_HEART_PIECE_BOWLING;
- if (Flags_GetItemGetInf(ITEMGETINF_12)) {
+ if (GameInteractor_Should(VB_SET_BOMBCHU_BOWLING_PRIZE, true, this, &prizeTemp)) {
+ switch (this->prizeSelect) {
+ case 0:
+ prizeTemp = EXITEM_BOMB_BAG_BOWLING;
+ if (Flags_GetItemGetInf(ITEMGETINF_11)) {
prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING;
}
- }
- break;
- case 2:
- prizeTemp = EXITEM_BOMBCHUS_BOWLING;
- break;
- case 3:
- if (!IS_RANDO) {
+ break;
+ case 1:
+ prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING;
+ break;
+ case 2:
+ prizeTemp = EXITEM_BOMBCHUS_BOWLING;
+ break;
+ case 3:
prizeTemp = EXITEM_HEART_PIECE_BOWLING;
if (Flags_GetItemGetInf(ITEMGETINF_12)) {
prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING;
}
- } else {
- prizeTemp = EXITEM_PURPLE_RUPEE_BOWLING;
- }
- break;
- case 4:
- prizeTemp = EXITEM_BOMBS_BOWLING;
- break;
+ break;
+ case 4:
+ prizeTemp = EXITEM_BOMBS_BOWLING;
+ break;
+ }
}
this->prizeIndex = prizeTemp;