From 8aa7b2fc716cf40251bc9cb97db598d1d055636c Mon Sep 17 00:00:00 2001 From: Jordan Longstaff Date: Wed, 3 Dec 2025 10:58:06 -0500 Subject: [PATCH] Modularize Hyper Enemies hook (#5968) * Modularize Hyper Enemies hook * Use extern "C" * Make mod file self-contained --- .../Enhancements/Difficulty/HyperEnemies.cpp | 33 +++++++++++++++++++ soh/soh/Enhancements/mods.cpp | 29 ---------------- soh/soh/Enhancements/mods.h | 1 - soh/soh/SohGui/SohMenuEnhancements.cpp | 1 - 4 files changed, 33 insertions(+), 31 deletions(-) create mode 100644 soh/soh/Enhancements/Difficulty/HyperEnemies.cpp diff --git a/soh/soh/Enhancements/Difficulty/HyperEnemies.cpp b/soh/soh/Enhancements/Difficulty/HyperEnemies.cpp new file mode 100644 index 000000000..b2e0c933b --- /dev/null +++ b/soh/soh/Enhancements/Difficulty/HyperEnemies.cpp @@ -0,0 +1,33 @@ +#include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" +#include "functions.h" +#include "macros.h" + +extern "C" PlayState* gPlayState; + +static constexpr int32_t CVAR_HYPER_ENEMIES_DEFAULT = 0; +#define CVAR_HYPER_ENEMIES_NAME CVAR_ENHANCEMENT("HyperEnemies") +#define CVAR_HYPER_ENEMIES_VALUE CVarGetInteger(CVAR_HYPER_ENEMIES_NAME, CVAR_HYPER_ENEMIES_DEFAULT) + +static void MakeHyperEnemies(void* refActor) { + // Run the update function a second time to make enemies and minibosses move and act twice as fast. + + Player* player = GET_PLAYER(gPlayState); + Actor* actor = static_cast(refActor); + + // Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies. + bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2; + bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2; + + // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes. + if (isEnemy && !isExcludedEnemy && !Player_InBlockingCsMode(gPlayState, player)) { + GameInteractor::RawAction::UpdateActor(actor); + } +} + +static void UpdateHyperEnemiesState() { + COND_HOOK(OnActorUpdate, CVAR_HYPER_ENEMIES_VALUE, MakeHyperEnemies); +} + +static RegisterShipInitFunc initFunc(UpdateHyperEnemiesState, { CVAR_HYPER_ENEMIES_NAME }); diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 205c35ae6..3e724c54f 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -198,34 +198,6 @@ void RegisterHyperBosses() { [](int16_t fileNum) { UpdateHyperBossesState(); }); } -void UpdateHyperEnemiesState() { - static uint32_t actorUpdateHookId = 0; - if (actorUpdateHookId != 0) { - GameInteractor::Instance->UnregisterGameHook(actorUpdateHookId); - actorUpdateHookId = 0; - } - - if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0)) { - actorUpdateHookId = - GameInteractor::Instance->RegisterGameHook([](void* refActor) { - // Run the update function a second time to make enemies and minibosses move and act twice as fast. - - Player* player = GET_PLAYER(gPlayState); - Actor* actor = static_cast(refActor); - - // Some enemies are not in the ACTORCAT_ENEMY category, and some are that aren't really enemies. - bool isEnemy = actor->category == ACTORCAT_ENEMY || actor->id == ACTOR_EN_TORCH2; - bool isExcludedEnemy = actor->id == ACTOR_EN_FIRE_ROCK || actor->id == ACTOR_EN_ENCOUNT2; - - // Don't apply during cutscenes because it causes weird behaviour and/or crashes on some cutscenes. - if (CVarGetInteger(CVAR_ENHANCEMENT("HyperEnemies"), 0) && isEnemy && !isExcludedEnemy && - !Player_InBlockingCsMode(gPlayState, player)) { - GameInteractor::RawAction::UpdateActor(actor); - } - }); - } -} - // this map is used for enemies that can be uniquely identified by their id // and that are always counted // enemies that can't be uniquely identified by their id @@ -476,7 +448,6 @@ void InitMods() { RegisterTTS(); RegisterOcarinaTimeTravel(); RegisterHyperBosses(); - UpdateHyperEnemiesState(); RegisterEnemyDefeatCounts(); RegisterRandomizedEnemySizes(); RandoKaleido_RegisterHooks(); diff --git a/soh/soh/Enhancements/mods.h b/soh/soh/Enhancements/mods.h index fe5083ce2..9a0c6794b 100644 --- a/soh/soh/Enhancements/mods.h +++ b/soh/soh/Enhancements/mods.h @@ -7,7 +7,6 @@ extern "C" { #endif -void UpdateHyperEnemiesState(); void UpdateHyperBossesState(); void InitMods(); void SwitchAge(); diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index e73aa59cc..c32b11755 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1291,7 +1291,6 @@ void SohMenu::AddMenuEnhancements() { .Options(CheckboxOptions().Tooltip("All Major Bosses move and act twice as fast.")); AddWidget(path, "Hyper Enemies", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("HyperEnemies")) - .Callback([](WidgetInfo& info) { UpdateHyperEnemiesState(); }) .Options(CheckboxOptions().Tooltip("All Regular Enemies and Mini-Bosses move and act twice as fast.")); AddWidget(path, "Enable Visual Guard Vision", WIDGET_CVAR_CHECKBOX).CVar(CVAR_ENHANCEMENT("GuardVision")); AddWidget(path, "Leever Spawn Rate: %d seconds", WIDGET_CVAR_SLIDER_INT)