diff options
| author | Jordan Longstaff <JordanLongstaff@users.noreply.github.com> | 2026-07-25 10:01:44 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-07-25 14:01:44 +0000 |
| commit | 2b3521195612f83227c0d6f73dc5b0a68abe4edd (patch) | |
| tree | b58e8e9992452de32e5547ce8218a990620d879f | |
| parent | 783139310ae89427ce90b0476be86b08e4261c79 (diff) | |
[Enhancement] Award both prizes for high score in Horseback Archery (#6982)
4 files changed, 72 insertions, 30 deletions
diff --git a/soh/soh/Enhancements/Minigames/HorsebackArchery.cpp b/soh/soh/Enhancements/Minigames/HorsebackArchery.cpp index f268a5b17..37d7bec40 100644 --- a/soh/soh/Enhancements/Minigames/HorsebackArchery.cpp +++ b/soh/soh/Enhancements/Minigames/HorsebackArchery.cpp @@ -9,37 +9,64 @@ extern SaveContext gSaveContext; extern void EnGe1_TalkAfterGame_Archery(EnGe1* enGe1, PlayState* play); } -static void RegisterHorsebackArcheryEnhancements() { - COND_VB_SHOULD(VB_PLAY_HORSEBACK_ARCHERY, - CVarGetInteger(CVAR_ENHANCEMENT("CustomizeHorsebackArchery"), 0) && - CVarGetInteger(CVAR_ENHANCEMENT("InstantHorsebackArcheryWin"), 0), - { - EnGe1* enGe1 = va_arg(args, EnGe1*); - PlayState* play = va_arg(args, PlayState*); - Rupees_ChangeBy(-20); - Flags_SetEventChkInf(EVENTCHKINF_PLAYED_HORSEBACK_ARCHERY); - gSaveContext.minigameScore = 1500; - Message_CloseTextbox(play); - enGe1->actionFunc = EnGe1_TalkAfterGame_Archery; - *should = false; - }); - - COND_VB_SHOULD(VB_SCORE_HORSEBACK_ARCHERY_TARGET, - CVarGetInteger(CVAR_ENHANCEMENT("CustomizeHorsebackArchery"), 0) && - CVarGetInteger(CVAR_ENHANCEMENT("HorsebackArcheryAlwaysScore"), 0), - { - s32* scoreIndex = va_arg(args, s32*); - *scoreIndex = 2; // inner ring = 100 points - }); - - COND_VB_SHOULD(VB_SET_HORSEBACK_ARCHERY_AMMO, CVarGetInteger(CVAR_ENHANCEMENT("CustomizeHorsebackArchery"), 0), { +#define CVAR_ARCHERY_CUSTOMIZE_NAME CVAR_ENHANCEMENT("CustomizeHorsebackArchery") +#define CVAR_ARCHERY_CUSTOMIZE_VALUE CVarGetInteger(CVAR_ARCHERY_CUSTOMIZE_NAME, 0) + +static constexpr s32 CVAR_ARCHERY_AMMO_DEFAULT = 20; + +#define CVAR_ARCHERY_AMMO_NAME CVAR_ENHANCEMENT("HorsebackArcheryAmmo") +#define CVAR_ARCHERY_AMMO_VALUE CVarGetInteger(CVAR_ARCHERY_AMMO_NAME, CVAR_ARCHERY_AMMO_DEFAULT) +#define CVAR_ARCHERY_AMMO_CHANGED (CVAR_ARCHERY_AMMO_VALUE != CVAR_ARCHERY_AMMO_DEFAULT) + +#define CVAR_ARCHERY_ALWAYS_SCORE_NAME CVAR_ENHANCEMENT("HorsebackArcheryAlwaysScore") +#define CVAR_ARCHERY_ALWAYS_SCORE_VALUE CVarGetInteger(CVAR_ARCHERY_ALWAYS_SCORE_NAME, 0) + +#define CVAR_ARCHERY_INSTANT_WIN_NAME CVAR_ENHANCEMENT("InstantHorsebackArcheryWin") +#define CVAR_ARCHERY_INSTANT_WIN_VALUE CVarGetInteger(CVAR_ARCHERY_INSTANT_WIN_NAME, 0) + +#define CVAR_ARCHERY_BOTH_PRIZES_NAME CVAR_ENHANCEMENT("HorsebackArcheryBothPrizes") +#define CVAR_ARCHERY_BOTH_PRIZES_VALUE CVarGetInteger(CVAR_ARCHERY_BOTH_PRIZES_NAME, 0) + +static void RegisterHorsebackArcheryInstantWin() { + COND_VB_SHOULD(VB_PLAY_HORSEBACK_ARCHERY, CVAR_ARCHERY_CUSTOMIZE_VALUE && CVAR_ARCHERY_INSTANT_WIN_VALUE, { + EnGe1* enGe1 = va_arg(args, EnGe1*); + PlayState* play = va_arg(args, PlayState*); + Rupees_ChangeBy(-20); + Flags_SetEventChkInf(EVENTCHKINF_PLAYED_HORSEBACK_ARCHERY); + gSaveContext.minigameScore = 1500; + Message_CloseTextbox(play); + enGe1->actionFunc = EnGe1_TalkAfterGame_Archery; + *should = false; + }); +} + +static void RegisterHorsebackArcheryAlwaysScore() { + COND_VB_SHOULD(VB_SCORE_HORSEBACK_ARCHERY_TARGET, CVAR_ARCHERY_CUSTOMIZE_VALUE && CVAR_ARCHERY_ALWAYS_SCORE_VALUE, { + s32* scoreIndex = va_arg(args, s32*); + *scoreIndex = 2; // inner ring = 100 points + }); +} + +static void RegisterHorsebackArcheryAmmo() { + COND_VB_SHOULD(VB_SET_HORSEBACK_ARCHERY_AMMO, CVAR_ARCHERY_CUSTOMIZE_VALUE && CVAR_ARCHERY_AMMO_CHANGED, { InterfaceContext* interfaceCtx = va_arg(args, InterfaceContext*); - interfaceCtx->hbaAmmo = CVarGetInteger(CVAR_ENHANCEMENT("HorsebackArcheryAmmo"), 20); + interfaceCtx->hbaAmmo = CVAR_ARCHERY_AMMO_VALUE; *should = false; }); } -static RegisterShipInitFunc - initFunc(RegisterHorsebackArcheryEnhancements, - { CVAR_ENHANCEMENT("CustomizeHorsebackArchery"), CVAR_ENHANCEMENT("InstantHorsebackArcheryWin"), - CVAR_ENHANCEMENT("HorsebackArcheryAlwaysScore"), CVAR_ENHANCEMENT("HorsebackArcheryAmmo") }); +static void RegisterHorsebackArcheryBothPrizes() { + COND_VB_SHOULD(VB_END_HORSEBACK_ARCHERY, CVAR_ARCHERY_BOTH_PRIZES_VALUE, { + EnGe1* enGe1 = va_arg(args, EnGe1*); + enGe1->actionFunc = EnGe1_TalkAfterGame_Archery; + *should = false; + }) +} + +static RegisterShipInitFunc initFunc_InstantWin(RegisterHorsebackArcheryInstantWin, + { CVAR_ARCHERY_CUSTOMIZE_NAME, CVAR_ARCHERY_INSTANT_WIN_NAME }); +static RegisterShipInitFunc initFunc_AlwaysScore(RegisterHorsebackArcheryAlwaysScore, + { CVAR_ARCHERY_CUSTOMIZE_NAME, CVAR_ARCHERY_ALWAYS_SCORE_NAME }); +static RegisterShipInitFunc initFunc_Ammo(RegisterHorsebackArcheryAmmo, + { CVAR_ARCHERY_CUSTOMIZE_NAME, CVAR_ARCHERY_AMMO_NAME }); +static RegisterShipInitFunc initFunc_BothPrizes(RegisterHorsebackArcheryBothPrizes, { CVAR_ARCHERY_BOTH_PRIZES_NAME }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index f81b47c91..2c02cfe94 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -697,6 +697,14 @@ typedef enum { // #### `result` // ```c + // true + // ``` + // #### `args` + // - `*EnGe1` + VB_END_HORSEBACK_ARCHERY, + + // #### `result` + // ```c // !(this->stateFlags3 & PLAYER_STATE3_PAUSE_ACTION_FUNC) // ``` // #### `args` diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index dccbb7237..e0dfbc5f8 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1691,6 +1691,11 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip("Allow fishing even when not having any item equipped on the B button, " "fixing a vanilla bug. Always enabled in randomizer.")); + AddWidget(path, "Multiple Prizes", WIDGET_SEPARATOR_TEXT); + AddWidget(path, "Horseback Archery", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("HorsebackArcheryBothPrizes")) + .Options(CheckboxOptions().Tooltip("Link can win both Horseback Archery prizes in one attempt")); + // Extra Modes path.sidebarName = "Extra Modes"; AddSidebarEntry("Enhancements", path.sidebarName, 3); diff --git a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c index 3f9f6cd34..b29c676e2 100644 --- a/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c +++ b/soh/src/overlays/actors/ovl_En_Ge1/z_en_ge1.c @@ -511,7 +511,9 @@ void EnGe1_WaitTillItemGiven_Archery(EnGe1* this, PlayState* play) { return; } if (Actor_HasParent(&this->actor, play)) { - this->actionFunc = EnGe1_SetupWait_Archery; + if (GameInteractor_Should(VB_END_HORSEBACK_ARCHERY, true, this)) { + this->actionFunc = EnGe1_SetupWait_Archery; + } if (this->stateFlags & GE1_STATE_GIVE_QUIVER) { Flags_SetItemGetInf(ITEMGETINF_0F); |
