summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJordan Longstaff <JordanLongstaff@users.noreply.github.com>2026-07-23 01:33:04 -0400
committerGitHub <noreply@github.com>2026-07-23 05:33:04 +0000
commit35dcba5944203d254781d1ac5f870c2eed13b802 (patch)
tree33ed89afd4d67d5fad443953982e92ed5f0ca2d7
parentc71203ad06da8883cba28af0f6b81090ac046a56 (diff)
[Enhancement] Ingo Race Once (#6965)
-rw-r--r--soh/soh/Enhancements/Minigames/IngoRaceOnce.cpp15
-rw-r--r--soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h8
-rw-r--r--soh/soh/SohGui/SohMenuEnhancements.cpp5
-rw-r--r--soh/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c3
4 files changed, 30 insertions, 1 deletions
diff --git a/soh/soh/Enhancements/Minigames/IngoRaceOnce.cpp b/soh/soh/Enhancements/Minigames/IngoRaceOnce.cpp
new file mode 100644
index 000000000..8f1ed554f
--- /dev/null
+++ b/soh/soh/Enhancements/Minigames/IngoRaceOnce.cpp
@@ -0,0 +1,15 @@
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+#include "functions.h"
+}
+
+#define CVAR_INGO_RACE_ONCE_NAME CVAR_ENHANCEMENT("IngoRaceOnce")
+#define CVAR_INGO_RACE_ONCE_VALUE CVarGetInteger(CVAR_INGO_RACE_ONCE_NAME, 0)
+
+static void RegisterIngoRaceOnce() {
+ COND_VB_SHOULD(VB_LINK_WIN_EPONA, CVAR_INGO_RACE_ONCE_NAME, { *should = true; });
+}
+
+static RegisterShipInitFunc initFunc(RegisterIngoRaceOnce, { CVAR_INGO_RACE_ONCE_NAME });
diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
index 81c2acc2f..bcf4dc892 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -1530,6 +1530,14 @@ typedef enum {
// #### `result`
// ```c
+ // gSaveContext.eventInf[0] & 0x40
+ // ```
+ // #### `args`
+ // - None
+ VB_LINK_WIN_EPONA,
+
+ // #### `result`
+ // ```c
// !Flags_GetSwitch(play, this->dyna.actor.params & 0x3F)
// ```
// #### `args`
diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp
index 27ccfe998..5112c78ac 100644
--- a/soh/soh/SohGui/SohMenuEnhancements.cpp
+++ b/soh/soh/SohGui/SohMenuEnhancements.cpp
@@ -1620,6 +1620,11 @@ void SohMenu::AddMenuEnhancements() {
.CVar(CVAR_ENHANCEMENT("SkipAmyPuzzle"))
.Options(CheckboxOptions().Tooltip("Amy's block pushing puzzle instantly solved."));
+ AddWidget(path, "Ingo's Race", WIDGET_SEPARATOR_TEXT);
+ AddWidget(path, "Only Race Once", WIDGET_CVAR_CHECKBOX)
+ .CVar(CVAR_ENHANCEMENT("IngoRaceOnce"))
+ .Options(CheckboxOptions().Tooltip("Link only needs to race Ingo once to win Epona."));
+
path.column = SECTION_COLUMN_3;
AddWidget(path, "Rupee Diving Game", WIDGET_SEPARATOR_TEXT);
AddWidget(path, "Time Limit: %d seconds", WIDGET_CVAR_SLIDER_INT)
diff --git a/soh/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c b/soh/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c
index 03aebe1c7..2f059d515 100644
--- a/soh/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c
+++ b/soh/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c
@@ -6,6 +6,7 @@
#include "z_en_horse_game_check.h"
#include "overlays/actors/ovl_En_Horse/z_en_horse.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED
@@ -110,7 +111,7 @@ void EnHorseGameCheck_FinishIngoRace(EnHorseGameCheckIngoRace* this, PlayState*
gSaveContext.cutsceneIndex = 0;
if (this->result == INGORACE_PLAYER_WIN) {
play->nextEntranceIndex = ENTR_LON_LON_RANCH_7;
- if (gSaveContext.eventInf[0] & 0x40) {
+ if (GameInteractor_Should(VB_LINK_WIN_EPONA, gSaveContext.eventInf[0] & 0x40)) {
gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & ~0xF) | 6;
gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & ~0x8000) | 0x8000;
play->transitionType = TRANS_TYPE_FADE_WHITE;