diff --git a/soh/soh/Enhancements/FireTimerMultiplier.cpp b/soh/soh/Enhancements/FireTimerMultiplier.cpp new file mode 100644 index 000000000..4850d5515 --- /dev/null +++ b/soh/soh/Enhancements/FireTimerMultiplier.cpp @@ -0,0 +1,24 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +extern PlayState* gPlayState; +} + +void RegisterFireTimerMultiplier() { + COND_VB_SHOULD(VB_FIRE_TIMER_TICK, CVarGetInteger(CVAR_ENHANCEMENT("FireTimerMultiplier"), 0) != 0, { + int factor = CVarGetInteger(CVAR_ENHANCEMENT("FireTimerMultiplier"), 0); + if (factor != 0) { + if (factor > 0 && gPlayState->gameplayFrames % (factor + 1) != 0) { + *should = false; + } else if (gPlayState->gameplayFrames % (6 + factor) == 0) { + s16* timer = va_arg(args, s16*); + if (*timer != 0) { + *timer--; + } + } + } + }); +} + +static RegisterShipInitFunc initFunc(RegisterFireTimerMultiplier, { CVAR_ENHANCEMENT("FireTimerMultiplier") }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 5159118b1..94690d0ac 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -527,6 +527,14 @@ typedef enum { // - `*EnElf` VB_FAIRY_HEAL, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - `*s16` + VB_FIRE_TIMER_TICK, + // #### `result` // ```c // false diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 58f197512..6eb341ac8 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1123,6 +1123,10 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip("Dying will delete your file.\n\n" ICON_FA_EXCLAMATION_TRIANGLE " WARNING " ICON_FA_EXCLAMATION_TRIANGLE "\nTHIS IS NOT REVERSIBLE!\nUSE AT YOUR OWN RISK!")); + AddWidget(path, "Fire Timer Multiplier", WIDGET_CVAR_SLIDER_INT) + .CVar(CVAR_ENHANCEMENT("FireTimerMultiplier")) + .Options(IntSliderOptions().Min(-5).Max(5).DefaultValue(0).Format("%+d").Tooltip( + "-5 will be half as much time, +5 will be 6x as much time")); AddWidget(path, "Always Win Goron Pot", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("GoronPot")) .Options(CheckboxOptions().Tooltip("Always get the Heart Piece/Purple Rupee from the Spinning Goron Pot.")); diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Curtain/z_bg_hidan_curtain.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Curtain/z_bg_hidan_curtain.c index d818bf03e..3b583be89 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Curtain/z_bg_hidan_curtain.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Curtain/z_bg_hidan_curtain.c @@ -6,6 +6,7 @@ #include "z_bg_hidan_curtain.h" #include "objects/gameplay_keep/gameplay_keep.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED @@ -191,7 +192,10 @@ void BgHidanCurtain_TurnOff(BgHidanCurtain* this, PlayState* play) { } void BgHidanCurtain_WaitForTimer(BgHidanCurtain* this, PlayState* play) { - DECR(this->timer); + if (GameInteractor_Should(VB_FIRE_TIMER_TICK, true, &this->timer)) { + DECR(this->timer); + } + if (this->timer == 0) { this->actionFunc = BgHidanCurtain_TurnOn; } diff --git a/soh/src/overlays/actors/ovl_Bg_Hidan_Fwbig/z_bg_hidan_fwbig.c b/soh/src/overlays/actors/ovl_Bg_Hidan_Fwbig/z_bg_hidan_fwbig.c index 2caf4183d..24061d95c 100644 --- a/soh/src/overlays/actors/ovl_Bg_Hidan_Fwbig/z_bg_hidan_fwbig.c +++ b/soh/src/overlays/actors/ovl_Bg_Hidan_Fwbig/z_bg_hidan_fwbig.c @@ -8,6 +8,7 @@ #include "z_bg_hidan_fwbig.h" #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_hidan_objects/object_hidan_objects.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED @@ -165,9 +166,12 @@ void BgHidanFwbig_Lower(BgHidanFwbig* this, PlayState* play) { } void BgHidanFwbig_WaitForTimer(BgHidanFwbig* this, PlayState* play) { - if (this->timer != 0) { - this->timer--; + if (GameInteractor_Should(VB_FIRE_TIMER_TICK, true, &this->timer)) { + if (this->timer != 0) { + this->timer--; + } } + if (this->timer == 0) { this->actionFunc = BgHidanFwbig_Rise; }