Ingo Race Once: add option to skip both races (#6975)

This commit is contained in:
Jordan Longstaff
2026-07-24 12:30:08 -04:00
committed by GitHub
parent 9d1e5d2811
commit 5af79defb6
5 changed files with 48 additions and 5 deletions
@@ -1,15 +1,31 @@
#include "soh/Enhancements/enhancementTypes.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
extern "C" {
#include "functions.h"
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
}
#define CVAR_INGO_RACE_ONCE_NAME CVAR_ENHANCEMENT("IngoRaceOnce")
#define CVAR_INGO_RACE_ONCE_VALUE CVarGetInteger(CVAR_INGO_RACE_ONCE_NAME, 0)
#define CVAR_INGO_RACE_ONCE_VALUE CVarGetInteger(CVAR_INGO_RACE_ONCE_NAME, INGO_RACE_TWICE)
static void RegisterIngoRaceOnce() {
COND_VB_SHOULD(VB_LINK_WIN_EPONA, CVAR_INGO_RACE_ONCE_NAME, { *should = true; });
COND_VB_SHOULD(VB_RACE_INGO, CVAR_INGO_RACE_ONCE_VALUE == INGO_RACE_NONE, {
s32 entranceIndex = va_arg(args, s32);
if (entranceIndex == 2 && (gSaveContext.eventInf[0] & 0x10) == 0) {
gPlayState->nextEntranceIndex = ENTR_LON_LON_RANCH_7;
gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & ~0xF) | 0x8006;
gPlayState->transitionType = TRANS_TYPE_FADE_WHITE;
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
gSaveContext.timerState = TIMER_STATE_OFF;
Environment_ForcePlaySequence(NA_BGM_INGO);
*should = false;
}
})
COND_VB_SHOULD(VB_LINK_WIN_EPONA, CVAR_INGO_RACE_ONCE_VALUE != INGO_RACE_TWICE, { *should = true; });
}
static RegisterShipInitFunc initFunc(RegisterIngoRaceOnce, { CVAR_INGO_RACE_ONCE_NAME });
+6
View File
@@ -118,6 +118,12 @@ typedef enum {
WATERFALL_NEVER,
} SleepingWaterfallType;
typedef enum {
INGO_RACE_TWICE,
INGO_RACE_ONCE,
INGO_RACE_NONE,
} IngoRaceType;
typedef enum {
RANDOMIZE_OFF,
RANDOMIZE_ON_NEW_SCENE,
@@ -2277,6 +2277,14 @@ typedef enum {
// - None
VB_PREVENT_STRENGTH,
// #### `result`
// ```c
// true
// ```
// #### `args`
// - `s32` (entrance index)
VB_RACE_INGO,
// #### `result`
// ```c
// true
+12 -2
View File
@@ -55,6 +55,12 @@ static const std::map<int32_t, const char*> skipForcedDialogOptions = {
{ FORCED_DIALOG_SKIP_ALL, "All" },
};
static const std::map<int32_t, const char*> ingoRaceOptions = {
{ INGO_RACE_TWICE, "Twice" },
{ INGO_RACE_ONCE, "Once" },
{ INGO_RACE_NONE, "None" },
};
static const std::map<int32_t, const char*> timeTravelOptions = {
{ TIME_TRAVEL_DISABLED, "Disabled" },
{ TIME_TRAVEL_OOT, "Ocarina of Time" },
@@ -1621,9 +1627,13 @@ void SohMenu::AddMenuEnhancements() {
.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)
AddWidget(path, "Number of Races", WIDGET_CVAR_COMBOBOX)
.CVar(CVAR_ENHANCEMENT("IngoRaceOnce"))
.Options(CheckboxOptions().Tooltip("Link only needs to race Ingo once to win Epona."));
.Options(ComboboxOptions()
.ComboMap(ingoRaceOptions)
.DefaultIndex(INGO_RACE_TWICE)
.Tooltip("Number of races Link must win against Ingo to earn Epona. "
"Only works if Link is riding Epona, not the other rideable horse."));
path.column = SECTION_COLUMN_3;
AddWidget(path, "Rupee Diving Game", WIDGET_SEPARATOR_TEXT);
+4 -1
View File
@@ -2,6 +2,7 @@
#include "overlays/actors/ovl_En_Horse/z_en_horse.h"
#include "objects/object_in/object_in.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_FRIENDLY | ACTOR_FLAG_UPDATE_CULLING_DISABLED)
@@ -694,7 +695,9 @@ void func_80A7A568(EnIn* this, PlayState* play) {
phi_a2 = 0;
transitionType = TRANS_TYPE_CIRCLE(TCA_NORMAL, TCC_BLACK, TCS_FAST);
}
func_80A79BAC(this, play, phi_a2, transitionType);
if (GameInteractor_Should(VB_RACE_INGO, true, phi_a2)) {
func_80A79BAC(this, play, phi_a2, transitionType);
}
play->msgCtx.stateTimer = 0;
gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & ~0x8000) | 0x8000;
play->msgCtx.msgMode = MSGMODE_TEXT_CLOSING;