diff --git a/soh/soh/Enhancements/Difficulty/HorsebackArchery.cpp b/soh/soh/Enhancements/Difficulty/HorsebackArchery.cpp new file mode 100644 index 000000000..f268a5b17 --- /dev/null +++ b/soh/soh/Enhancements/Difficulty/HorsebackArchery.cpp @@ -0,0 +1,45 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "functions.h" +#include "src/overlays/actors/ovl_En_Ge1/z_en_ge1.h" +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), { + InterfaceContext* interfaceCtx = va_arg(args, InterfaceContext*); + interfaceCtx->hbaAmmo = CVarGetInteger(CVAR_ENHANCEMENT("HorsebackArcheryAmmo"), 20); + *should = false; + }); +} + +static RegisterShipInitFunc + initFunc(RegisterHorsebackArcheryEnhancements, + { CVAR_ENHANCEMENT("CustomizeHorsebackArchery"), CVAR_ENHANCEMENT("InstantHorsebackArcheryWin"), + CVAR_ENHANCEMENT("HorsebackArcheryAlwaysScore"), CVAR_ENHANCEMENT("HorsebackArcheryAmmo") }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 8f1b6ebf8..e87a3ff55 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -907,6 +907,31 @@ typedef enum { // - `*EnGe1` VB_GIVE_ITEM_FROM_HORSEBACK_ARCHERY, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*EnGe1` + // - `*PlayState` + VB_PLAY_HORSEBACK_ARCHERY, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*s32` (scoreIndex: 0=30pts, 1=60pts, 2=100pts) + VB_SCORE_HORSEBACK_ARCHERY_TARGET, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*InterfaceContext` + VB_SET_HORSEBACK_ARCHERY_AMMO, + // #### `result` // ```c // true diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 477bb6f70..fc4f9f95c 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1430,6 +1430,33 @@ void SohMenu::AddMenuEnhancements() { .DefaultValue(10) .Format("%d bombchus") .Tooltip("The number of Bombchus available at the start of the Bombchu Bowling minigame.")); + AddWidget(path, "Horseback Archery", WIDGET_SEPARATOR_TEXT); + AddWidget(path, "Customize Behavior##HBA", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("CustomizeHorsebackArchery")) + .Options(CheckboxOptions().Tooltip("Turn on/off changes to the Horseback Archery minigame behavior.")); + auto hbaDisabledFunc = [](WidgetInfo& info) { + info.options->disabled = CVarGetInteger(CVAR_ENHANCEMENT("CustomizeHorsebackArchery"), 0) == 0; + info.options->disabledTooltip = "This option is disabled because \"Customize Behavior\" is turned off."; + }; + AddWidget(path, "Instant Win##HBA", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("InstantHorsebackArcheryWin")) + .PreFunc(hbaDisabledFunc) + .Options(CheckboxOptions().Tooltip("Skips the Horseback Archery minigame, automatically awarding the prize.")); + AddWidget(path, "Always Score 100##HBA", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("HorsebackArcheryAlwaysScore")) + .PreFunc(hbaDisabledFunc) + .Options(CheckboxOptions().Tooltip( + "Every arrow that hits a target scores 100 points (inner ring) regardless of where it lands.")); + AddWidget(path, "Arrow Count", WIDGET_CVAR_SLIDER_INT) + .CVar(CVAR_ENHANCEMENT("HorsebackArcheryAmmo")) + .PreFunc(hbaDisabledFunc) + .Options(IntSliderOptions() + .Min(15) + .Max(40) + .DefaultValue(20) + .Format("%d arrows") + .Tooltip("The number of arrows available at the start of the Horseback Archery minigame.")); + AddWidget(path, "Frogs' Ocarina Game", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Customize Behavior##Frogs", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("CustomizeFrogsOcarinaGame")) diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 4b782d954..884114369 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1711,7 +1711,9 @@ void Interface_InitHorsebackArchery(PlayState* play) { gSaveContext.minigameState = 1; interfaceCtx->unk_23C = interfaceCtx->unk_240 = interfaceCtx->unk_242 = 0; gSaveContext.minigameScore = sHBAScoreTier = 0; - interfaceCtx->hbaAmmo = 20; + if (GameInteractor_Should(VB_SET_HORSEBACK_ARCHERY_AMMO, true, interfaceCtx)) { + interfaceCtx->hbaAmmo = 20; + } } void func_800849EC(PlayState* play) { 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 5b610e379..68203791a 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 @@ -599,7 +599,7 @@ void EnGe1_BeginGame_Archery(EnGe1* this, PlayState* play) { if (gSaveContext.rupees < 20) { Message_ContinueTextbox(play, 0x85); this->actionFunc = EnGe1_TalkTooPoor_Archery; - } else { + } else if (GameInteractor_Should(VB_PLAY_HORSEBACK_ARCHERY, true, this, play)) { Rupees_ChangeBy(-20); play->nextEntranceIndex = ENTR_GERUDOS_FORTRESS_EAST_EXIT; gSaveContext.nextCutsceneIndex = 0xFFF0; diff --git a/soh/src/overlays/actors/ovl_En_Yabusame_Mark/z_en_yabusame_mark.c b/soh/src/overlays/actors/ovl_En_Yabusame_Mark/z_en_yabusame_mark.c index 683e601a0..10df16846 100644 --- a/soh/src/overlays/actors/ovl_En_Yabusame_Mark/z_en_yabusame_mark.c +++ b/soh/src/overlays/actors/ovl_En_Yabusame_Mark/z_en_yabusame_mark.c @@ -6,6 +6,7 @@ #include "z_en_yabusame_mark.h" #include "vt.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS 0 @@ -160,6 +161,8 @@ void func_80B42F74(EnYabusameMark* this, PlayState* play) { } } + GameInteractor_Should(VB_SCORE_HORSEBACK_ARCHERY_TARGET, true, &scoreIndex); + osSyncPrintf("\n\n"); osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ posX ☆☆☆☆☆ %f\n" VT_RST, arrowHitPos.x); osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ posY ☆☆☆☆☆ %f\n" VT_RST, arrowHitPos.y);