From cd1d619c9fc807124a08ba149051d188cc044a8b Mon Sep 17 00:00:00 2001 From: Jordan Longstaff Date: Fri, 14 Nov 2025 11:30:04 -0500 Subject: [PATCH] Modularize permanent loss mod hooks (#5948) * Modularize permanent loss mod hooks * Make RegisterBonkDamage static * Remove a couple of errant includes * Fix more errant includes --- soh/soh/Enhancements/BonkDamage.cpp | 51 ------------ soh/soh/Enhancements/CuccosToReturn.cpp | 18 ----- soh/soh/Enhancements/DampeFire.cpp | 48 ----------- .../Enhancements/Difficulty/BonkDamage.cpp | 55 +++++++++++++ .../Difficulty/CuccosToReturn.cpp | 23 ++++++ soh/soh/Enhancements/Difficulty/DampeFire.cpp | 52 ++++++++++++ .../Difficulty/PermanentLosses.cpp | 79 +++++++++++++++++++ .../SwitchTimerMultiplier.cpp | 10 ++- .../{ => Difficulty}/TreesDropSticks.cpp | 12 ++- soh/soh/Enhancements/mods.cpp | 57 ------------- 10 files changed, 224 insertions(+), 181 deletions(-) delete mode 100644 soh/soh/Enhancements/BonkDamage.cpp delete mode 100644 soh/soh/Enhancements/CuccosToReturn.cpp delete mode 100644 soh/soh/Enhancements/DampeFire.cpp create mode 100644 soh/soh/Enhancements/Difficulty/BonkDamage.cpp create mode 100644 soh/soh/Enhancements/Difficulty/CuccosToReturn.cpp create mode 100644 soh/soh/Enhancements/Difficulty/DampeFire.cpp create mode 100644 soh/soh/Enhancements/Difficulty/PermanentLosses.cpp rename soh/soh/Enhancements/{ => Difficulty}/SwitchTimerMultiplier.cpp (69%) rename soh/soh/Enhancements/{ => Difficulty}/TreesDropSticks.cpp (62%) diff --git a/soh/soh/Enhancements/BonkDamage.cpp b/soh/soh/Enhancements/BonkDamage.cpp deleted file mode 100644 index c9e5e089a..000000000 --- a/soh/soh/Enhancements/BonkDamage.cpp +++ /dev/null @@ -1,51 +0,0 @@ -#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" -#include "soh/ShipInit.hpp" -#include "./enhancementTypes.h" - -extern "C" { -#include "functions.h" -#include "macros.h" -extern PlayState* gPlayState; -extern SaveContext gSaveContext; -} - -void RegisterBonkDamage() { - COND_HOOK(OnPlayerBonk, CVarGetInteger(CVAR_ENHANCEMENT("BonkDamageMult"), BONK_DAMAGE_NONE) != BONK_DAMAGE_NONE, - [] { - uint16_t bonkDamage = 0; - switch (CVarGetInteger(CVAR_ENHANCEMENT("BonkDamageMult"), BONK_DAMAGE_NONE)) { - case BONK_DAMAGE_NONE: - return; - case BONK_DAMAGE_OHKO: - gSaveContext.health = 0; - return; - case BONK_DAMAGE_QUARTER_HEART: - bonkDamage = 4; - break; - case BONK_DAMAGE_HALF_HEART: - bonkDamage = 8; - break; - case BONK_DAMAGE_1_HEART: - bonkDamage = 16; - break; - case BONK_DAMAGE_2_HEARTS: - bonkDamage = 32; - break; - case BONK_DAMAGE_4_HEARTS: - bonkDamage = 64; - break; - case BONK_DAMAGE_8_HEARTS: - bonkDamage = 128; - break; - default: - break; - } - - Health_ChangeBy(gPlayState, -bonkDamage); - // Set invincibility to make Link flash red as a visual damage indicator. - Player* player = GET_PLAYER(gPlayState); - player->invincibilityTimer = 28; - }); -} - -static RegisterShipInitFunc initFunc(RegisterBonkDamage, { CVAR_ENHANCEMENT("BonkDamageMult") }); diff --git a/soh/soh/Enhancements/CuccosToReturn.cpp b/soh/soh/Enhancements/CuccosToReturn.cpp deleted file mode 100644 index 2de929fd3..000000000 --- a/soh/soh/Enhancements/CuccosToReturn.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" -#include "soh/ShipInit.hpp" - -extern "C" { -extern PlayState* gPlayState; -#include "src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.h" -} - -void RegisterCuccosToReturn() { - COND_VB_SHOULD(VB_SET_CUCCO_COUNT, CVarGetInteger(CVAR_ENHANCEMENT("CuccosToReturn"), 7) != 7, { - EnNiwLady* enNiwLady = va_arg(args, EnNiwLady*); - // Override starting Cucco count using setting value - enNiwLady->cuccosInPen = 7 - CVarGetInteger(CVAR_ENHANCEMENT("CuccosToReturn"), 7); - *should = false; - }); -} - -static RegisterShipInitFunc initFunc(RegisterCuccosToReturn, { CVAR_ENHANCEMENT("CuccosToReturn") }); diff --git a/soh/soh/Enhancements/DampeFire.cpp b/soh/soh/Enhancements/DampeFire.cpp deleted file mode 100644 index 1378ecb04..000000000 --- a/soh/soh/Enhancements/DampeFire.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" -#include "soh/ShipInit.hpp" -#include "soh/Enhancements/enhancementTypes.h" - -extern "C" { -extern PlayState* gPlayState; -#include "src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.h" -} - -void RegisterDampeFire() { - COND_VB_SHOULD(VB_DAMPE_DROP_FLAME, CVarGetInteger(CVAR_ENHANCEMENT("DampeDropRate"), DAMPE_NORMAL) != DAMPE_NORMAL, - { - double chance; - int cooldown = 9; - switch (CVarGetInteger(CVAR_ENHANCEMENT("DampeDropRate"), DAMPE_NORMAL)) { - case DAMPE_NONE: - *should = false; - return; - default: - case DAMPE_NORMAL: - return; - case DAMPE_JALAPENO: - chance = 0.03; - break; - case DAMPE_CHIPOTLE: - chance = 0.1; - break; - case DAMPE_SCOTCH_BONNET: - chance = 0.2; - break; - case DAMPE_GHOST_PEPPER: - chance = 0.5; - cooldown = 4; - break; - case DAMPE_INFERNO: - *should = true; - return; - } - - EnPoRelay* actor = va_arg(args, EnPoRelay*); - if (actor->actionTimer > cooldown) { - actor->actionTimer = cooldown; - } - *should = actor->actionTimer == 0 && Rand_ZeroOne() < chance; - }); -} - -static RegisterShipInitFunc initFunc(RegisterDampeFire, { CVAR_ENHANCEMENT("DampeDropRate") }); diff --git a/soh/soh/Enhancements/Difficulty/BonkDamage.cpp b/soh/soh/Enhancements/Difficulty/BonkDamage.cpp new file mode 100644 index 000000000..04618c4a3 --- /dev/null +++ b/soh/soh/Enhancements/Difficulty/BonkDamage.cpp @@ -0,0 +1,55 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" +#include "soh/Enhancements/enhancementTypes.h" + +extern "C" { +#include "functions.h" +#include "macros.h" +extern PlayState* gPlayState; +extern SaveContext gSaveContext; +} + +static constexpr BonkDamage CVAR_BONK_DAMAGE_DEFAULT = BONK_DAMAGE_NONE; +#define CVAR_BONK_DAMAGE_NAME CVAR_ENHANCEMENT("BonkDamageMult") +#define CVAR_BONK_DAMAGE_VALUE CVarGetInteger(CVAR_BONK_DAMAGE_NAME, CVAR_BONK_DAMAGE_DEFAULT) +#define CVAR_BONK_DAMAGE_SET (CVAR_BONK_DAMAGE_VALUE != CVAR_BONK_DAMAGE_DEFAULT) + +static void RegisterBonkDamage() { + COND_HOOK(OnPlayerBonk, CVAR_BONK_DAMAGE_SET, [] { + uint16_t bonkDamage = 0; + switch (CVAR_BONK_DAMAGE_VALUE) { + case BONK_DAMAGE_NONE: + return; + case BONK_DAMAGE_OHKO: + gSaveContext.health = 0; + return; + case BONK_DAMAGE_QUARTER_HEART: + bonkDamage = 4; + break; + case BONK_DAMAGE_HALF_HEART: + bonkDamage = 8; + break; + case BONK_DAMAGE_1_HEART: + bonkDamage = 16; + break; + case BONK_DAMAGE_2_HEARTS: + bonkDamage = 32; + break; + case BONK_DAMAGE_4_HEARTS: + bonkDamage = 64; + break; + case BONK_DAMAGE_8_HEARTS: + bonkDamage = 128; + break; + default: + break; + } + + Health_ChangeBy(gPlayState, -bonkDamage); + // Set invincibility to make Link flash red as a visual damage indicator. + Player* player = GET_PLAYER(gPlayState); + player->invincibilityTimer = 28; + }); +} + +static RegisterShipInitFunc initFunc(RegisterBonkDamage, { CVAR_BONK_DAMAGE_NAME }); diff --git a/soh/soh/Enhancements/Difficulty/CuccosToReturn.cpp b/soh/soh/Enhancements/Difficulty/CuccosToReturn.cpp new file mode 100644 index 000000000..f1d5a2349 --- /dev/null +++ b/soh/soh/Enhancements/Difficulty/CuccosToReturn.cpp @@ -0,0 +1,23 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +extern PlayState* gPlayState; +#include "src/overlays/actors/ovl_En_Niw_Lady/z_en_niw_lady.h" +} + +static constexpr int32_t CVAR_CUCCOS_TO_RETURN_DEFAULT = 7; +#define CVAR_CUCCOS_TO_RETURN_NAME CVAR_ENHANCEMENT("CuccosToReturn") +#define CVAR_CUCCOS_TO_RETURN_VALUE CVarGetInteger(CVAR_CUCCOS_TO_RETURN_NAME, CVAR_CUCCOS_TO_RETURN_DEFAULT) +#define CVAR_CUCCOS_TO_RETURN_SET (CVAR_CUCCOS_TO_RETURN_VALUE != CVAR_CUCCOS_TO_RETURN_DEFAULT) + +static void RegisterCuccosToReturn() { + COND_VB_SHOULD(VB_SET_CUCCO_COUNT, CVAR_CUCCOS_TO_RETURN_SET, { + EnNiwLady* enNiwLady = va_arg(args, EnNiwLady*); + // Override starting Cucco count using setting value + enNiwLady->cuccosInPen = 7 - CVAR_CUCCOS_TO_RETURN_VALUE; + *should = false; + }); +} + +static RegisterShipInitFunc initFunc(RegisterCuccosToReturn, { CVAR_CUCCOS_TO_RETURN_NAME }); diff --git a/soh/soh/Enhancements/Difficulty/DampeFire.cpp b/soh/soh/Enhancements/Difficulty/DampeFire.cpp new file mode 100644 index 000000000..13afc88f0 --- /dev/null +++ b/soh/soh/Enhancements/Difficulty/DampeFire.cpp @@ -0,0 +1,52 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" +#include "soh/Enhancements/enhancementTypes.h" + +extern "C" { +extern PlayState* gPlayState; +#include "src/overlays/actors/ovl_En_Po_Relay/z_en_po_relay.h" +} + +static constexpr DampeDropRate CVAR_DAMPE_DROP_RATE_DEFAULT = DAMPE_NORMAL; +#define CVAR_DAMPE_DROP_RATE_NAME CVAR_ENHANCEMENT("DampeDropRate") +#define CVAR_DAMPE_DROP_RATE_VALUE CVarGetInteger(CVAR_DAMPE_DROP_RATE_NAME, CVAR_DAMPE_DROP_RATE_DEFAULT) +#define CVAR_DAMPE_DROP_RATE_SET (CVAR_DAMPE_DROP_RATE_VALUE != CVAR_DAMPE_DROP_RATE_DEFAULT) + +static void RegisterDampeFire() { + COND_VB_SHOULD(VB_DAMPE_DROP_FLAME, CVAR_DAMPE_DROP_RATE_SET, { + double chance; + int cooldown = 9; + switch (CVAR_DAMPE_DROP_RATE_VALUE) { + case DAMPE_NONE: + *should = false; + return; + default: + case DAMPE_NORMAL: + return; + case DAMPE_JALAPENO: + chance = 0.03; + break; + case DAMPE_CHIPOTLE: + chance = 0.1; + break; + case DAMPE_SCOTCH_BONNET: + chance = 0.2; + break; + case DAMPE_GHOST_PEPPER: + chance = 0.5; + cooldown = 4; + break; + case DAMPE_INFERNO: + *should = true; + return; + } + + EnPoRelay* actor = va_arg(args, EnPoRelay*); + if (actor->actionTimer > cooldown) { + actor->actionTimer = cooldown; + } + *should = actor->actionTimer == 0 && Rand_ZeroOne() < chance; + }); +} + +static RegisterShipInitFunc initFunc(RegisterDampeFire, { CVAR_DAMPE_DROP_RATE_NAME }); diff --git a/soh/soh/Enhancements/Difficulty/PermanentLosses.cpp b/soh/soh/Enhancements/Difficulty/PermanentLosses.cpp new file mode 100644 index 000000000..32b00057e --- /dev/null +++ b/soh/soh/Enhancements/Difficulty/PermanentLosses.cpp @@ -0,0 +1,79 @@ +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/mods.h" +#include "soh/OTRGlobals.h" +#include "soh/SaveManager.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "functions.h" +#include "macros.h" +#include "variables.h" +#include "z64save.h" +extern SaveContext gSaveContext; +extern PlayState* gPlayState; +} + +static constexpr int32_t CVAR_PERM_HEART_LOSS_DEFAULT = 0; +#define CVAR_PERM_HEART_LOSS_NAME CVAR_ENHANCEMENT("PermanentHeartLoss") +#define CVAR_PERM_HEART_LOSS_VALUE CVarGetInteger(CVAR_PERM_HEART_LOSS_NAME, CVAR_PERM_HEART_LOSS_DEFAULT) + +static constexpr int32_t CVAR_DELETE_FILE_DEFAULT = 0; +#define CVAR_DELETE_FILE_NAME CVAR_ENHANCEMENT("DeleteFileOnDeath") +#define CVAR_DELETE_FILE_VALUE CVarGetInteger(CVAR_DELETE_FILE_NAME, CVAR_DELETE_FILE_DEFAULT) + +static bool hasAffectedHealth = false; + +void UpdatePermanentHeartLossState() { + if (!GameInteractor::IsSaveLoaded() || !hasAffectedHealth || CVAR_PERM_HEART_LOSS_VALUE) + return; + + uint8_t heartContainers = gSaveContext.ship.stats.heartContainers; // each worth 16 health + uint8_t heartPieces = gSaveContext.ship.stats.heartPieces; // each worth 4 health, but only in groups of 4 + uint8_t startingHealth = + 16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3); + + uint8_t newCapacity = startingHealth + (heartContainers * 16) + ((heartPieces - (heartPieces % 4)) * 4); + gSaveContext.healthCapacity = MAX(newCapacity, gSaveContext.healthCapacity); + gSaveContext.health = MIN(gSaveContext.health, gSaveContext.healthCapacity); + hasAffectedHealth = false; +} + +static void UpdateHealthCapacity() { + if (!GameInteractor::IsSaveLoaded()) + return; + + if (gSaveContext.healthCapacity > 16 && gSaveContext.healthCapacity - gSaveContext.health >= 16) { + gSaveContext.healthCapacity -= 16; + gSaveContext.health = MIN(gSaveContext.health, gSaveContext.healthCapacity); + hasAffectedHealth = true; + } +} + +static void DeleteFileOnDeath() { + if (!GameInteractor::IsSaveLoaded() || gPlayState == NULL) + return; + + if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) { + SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum); + hasAffectedHealth = false; + std::reinterpret_pointer_cast( + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console")) + ->Dispatch("reset"); + } +} + +static void RegisterPermanentHeartLoss() { + COND_HOOK(OnPlayerUpdate, CVAR_PERM_HEART_LOSS_VALUE, UpdateHealthCapacity); +} + +static void RegisterDeleteFileOnDeath() { + COND_HOOK(OnGameFrameUpdate, CVAR_DELETE_FILE_VALUE, DeleteFileOnDeath); +} + +static void RegisterResetAffectedHealthOnLoad() { + COND_HOOK(OnLoadGame, true, [](int16_t) { hasAffectedHealth = false; }); +} + +static RegisterShipInitFunc initFunc_PermanentHeartLoss(RegisterPermanentHeartLoss, { CVAR_PERM_HEART_LOSS_NAME }); +static RegisterShipInitFunc initFunc_DeleteFileOnDeath(RegisterDeleteFileOnDeath, { CVAR_DELETE_FILE_NAME }); +static RegisterShipInitFunc initFunc_ResetAffectedHealth(RegisterResetAffectedHealthOnLoad); diff --git a/soh/soh/Enhancements/SwitchTimerMultiplier.cpp b/soh/soh/Enhancements/Difficulty/SwitchTimerMultiplier.cpp similarity index 69% rename from soh/soh/Enhancements/SwitchTimerMultiplier.cpp rename to soh/soh/Enhancements/Difficulty/SwitchTimerMultiplier.cpp index 94982837d..4090c1f95 100644 --- a/soh/soh/Enhancements/SwitchTimerMultiplier.cpp +++ b/soh/soh/Enhancements/Difficulty/SwitchTimerMultiplier.cpp @@ -5,9 +5,13 @@ extern "C" { extern PlayState* gPlayState; } +static constexpr int32_t CVAR_SWITCH_TIMER_DEFAULT = 0; +#define CVAR_SWITCH_TIMER_NAME CVAR_ENHANCEMENT("SwitchTimerMultiplier") +#define CVAR_SWITCH_TIMER_VALUE CVarGetInteger(CVAR_SWITCH_TIMER_NAME, CVAR_SWITCH_TIMER_DEFAULT) + void RegisterSwitchTimerMultiplier() { - COND_VB_SHOULD(VB_SWITCH_TIMER_TICK, CVarGetInteger(CVAR_ENHANCEMENT("SwitchTimerMultiplier"), 0) != 0, { - int multiplier = CVarGetInteger(CVAR_ENHANCEMENT("SwitchTimerMultiplier"), 0); + COND_VB_SHOULD(VB_SWITCH_TIMER_TICK, CVAR_SWITCH_TIMER_VALUE != 0, { + int multiplier = CVAR_SWITCH_TIMER_VALUE; if (multiplier != 0) { Actor* actor = va_arg(args, Actor*); if (multiplier < -3 && actor->id == ACTOR_OBJ_SYOKUDAI) { @@ -26,4 +30,4 @@ void RegisterSwitchTimerMultiplier() { }); } -static RegisterShipInitFunc initFunc(RegisterSwitchTimerMultiplier, { CVAR_ENHANCEMENT("SwitchTimerMultiplier") }); +static RegisterShipInitFunc initFunc(RegisterSwitchTimerMultiplier, { CVAR_SWITCH_TIMER_NAME }); diff --git a/soh/soh/Enhancements/TreesDropSticks.cpp b/soh/soh/Enhancements/Difficulty/TreesDropSticks.cpp similarity index 62% rename from soh/soh/Enhancements/TreesDropSticks.cpp rename to soh/soh/Enhancements/Difficulty/TreesDropSticks.cpp index 7fdc4eb0a..9bf868977 100644 --- a/soh/soh/Enhancements/TreesDropSticks.cpp +++ b/soh/soh/Enhancements/Difficulty/TreesDropSticks.cpp @@ -7,8 +7,12 @@ extern "C" { extern PlayState* gPlayState; -void RegisterTreesDropSticks() { - COND_VB_SHOULD(VB_TREE_DROP_COLLECTIBLE, CVarGetInteger(CVAR_ENHANCEMENT("TreesDropSticks"), 0), { +static constexpr int32_t CVAR_TREES_DROP_STICKS_DEFAULT = 0; +#define CVAR_TREES_DROP_STICKS_NAME CVAR_ENHANCEMENT("TreesDropSticks") +#define CVAR_TREES_DROP_STICKS_VALUE CVarGetInteger(CVAR_TREES_DROP_STICKS_NAME, CVAR_TREES_DROP_STICKS_DEFAULT) + +static void RegisterTreesDropSticks() { + COND_VB_SHOULD(VB_TREE_DROP_COLLECTIBLE, CVAR_TREES_DROP_STICKS_VALUE, { if (INV_CONTENT(ITEM_STICK) != ITEM_NONE) { EnWood02* tree = va_arg(args, EnWood02*); Vec3f dropsSpawnPt = tree->actor.world.pos; @@ -21,11 +25,11 @@ void RegisterTreesDropSticks() { } }); - COND_VB_SHOULD(VB_PREVENT_ADULT_STICK, CVarGetInteger(CVAR_ENHANCEMENT("TreesDropSticks"), 0), { + COND_VB_SHOULD(VB_PREVENT_ADULT_STICK, CVAR_TREES_DROP_STICKS_VALUE, { if (INV_CONTENT(ITEM_STICK) != ITEM_NONE) { *should = false; } }); } -static RegisterShipInitFunc initFunc(RegisterTreesDropSticks, { CVAR_ENHANCEMENT("TreesDropSticks") }); +static RegisterShipInitFunc initFunc(RegisterTreesDropSticks, { CVAR_TREES_DROP_STICKS_NAME }); diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp index 4d45765bf..93b4ce79e 100644 --- a/soh/soh/Enhancements/mods.cpp +++ b/soh/soh/Enhancements/mods.cpp @@ -2,8 +2,6 @@ #include #include "game-interactor/GameInteractor.h" #include "tts/tts.h" -#include "soh/OTRGlobals.h" -#include "soh/SaveManager.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/boss-rush/BossRush.h" #include "soh/Enhancements/enhancementTypes.h" @@ -24,7 +22,6 @@ #include "src/overlays/actors/ovl_En_Tp/z_en_tp.h" #include "src/overlays/actors/ovl_En_Firefly/z_en_firefly.h" #include "src/overlays/actors/ovl_En_Xc/z_en_xc.h" -#include "src/overlays/actors/ovl_Fishing/z_fishing.h" #include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h" #include "src/overlays/actors/ovl_Door_Gerudo/z_door_gerudo.h" #include "src/overlays/actors/ovl_En_Elf/z_en_elf.h" @@ -140,58 +137,6 @@ void RegisterOcarinaTimeTravel() { }); } -static bool hasAffectedHealth = false; -void UpdatePermanentHeartLossState() { - if (!GameInteractor::IsSaveLoaded()) - return; - - if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) && hasAffectedHealth) { - uint8_t heartContainers = gSaveContext.ship.stats.heartContainers; // each worth 16 health - uint8_t heartPieces = gSaveContext.ship.stats.heartPieces; // each worth 4 health, but only in groups of 4 - uint8_t startingHealth = - 16 * (IS_RANDO ? (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_STARTING_HEARTS) + 1) : 3); - - uint8_t newCapacity = startingHealth + (heartContainers * 16) + ((heartPieces - (heartPieces % 4)) * 4); - gSaveContext.healthCapacity = MAX(newCapacity, gSaveContext.healthCapacity); - gSaveContext.health = MIN(gSaveContext.health, gSaveContext.healthCapacity); - hasAffectedHealth = false; - } -} - -void RegisterPermanentHeartLoss() { - GameInteractor::Instance->RegisterGameHook([](int16_t fileNum) { - hasAffectedHealth = false; - UpdatePermanentHeartLossState(); - }); - - GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger(CVAR_ENHANCEMENT("PermanentHeartLoss"), 0) || !GameInteractor::IsSaveLoaded()) - return; - - if (gSaveContext.healthCapacity > 16 && gSaveContext.healthCapacity - gSaveContext.health >= 16) { - gSaveContext.healthCapacity -= 16; - gSaveContext.health = MIN(gSaveContext.health, gSaveContext.healthCapacity); - hasAffectedHealth = true; - } - }); -}; - -void RegisterDeleteFileOnDeath() { - GameInteractor::Instance->RegisterGameHook([]() { - if (!CVarGetInteger(CVAR_ENHANCEMENT("DeleteFileOnDeath"), 0) || !GameInteractor::IsSaveLoaded() || - gPlayState == NULL) - return; - - if (gPlayState->gameOverCtx.state == GAMEOVER_DEATH_MENU && gPlayState->pauseCtx.state == 9) { - SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum); - hasAffectedHealth = false; - std::reinterpret_pointer_cast( - Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console")) - ->Dispatch("reset"); - } - }); -} - bool IsHyperBossesActive() { return CVarGetInteger(CVAR_ENHANCEMENT("HyperBosses"), 0) || (IS_BOSS_RUSH && @@ -622,8 +567,6 @@ void InitMods() { TimeSaverRegisterHooks(); RegisterTTS(); RegisterOcarinaTimeTravel(); - RegisterPermanentHeartLoss(); - RegisterDeleteFileOnDeath(); RegisterHyperBosses(); UpdateHyperEnemiesState(); RegisterEnemyDefeatCounts();