Modularize permanent loss mod hooks (#5948)
* Modularize permanent loss mod hooks * Make RegisterBonkDamage static * Remove a couple of errant includes * Fix more errant includes
This commit is contained in:
@@ -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") });
|
||||
@@ -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") });
|
||||
@@ -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") });
|
||||
55
soh/soh/Enhancements/Difficulty/BonkDamage.cpp
Normal file
55
soh/soh/Enhancements/Difficulty/BonkDamage.cpp
Normal file
@@ -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 });
|
||||
23
soh/soh/Enhancements/Difficulty/CuccosToReturn.cpp
Normal file
23
soh/soh/Enhancements/Difficulty/CuccosToReturn.cpp
Normal file
@@ -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 });
|
||||
52
soh/soh/Enhancements/Difficulty/DampeFire.cpp
Normal file
52
soh/soh/Enhancements/Difficulty/DampeFire.cpp
Normal file
@@ -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 });
|
||||
79
soh/soh/Enhancements/Difficulty/PermanentLosses.cpp
Normal file
79
soh/soh/Enhancements/Difficulty/PermanentLosses.cpp
Normal file
@@ -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::ConsoleWindow>(
|
||||
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);
|
||||
@@ -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 });
|
||||
@@ -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 });
|
||||
@@ -2,8 +2,6 @@
|
||||
#include <libultraship/bridge.h>
|
||||
#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<GameInteractor::OnLoadGame>([](int16_t fileNum) {
|
||||
hasAffectedHealth = false;
|
||||
UpdatePermanentHeartLossState();
|
||||
});
|
||||
|
||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
||||
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<GameInteractor::OnGameFrameUpdate>([]() {
|
||||
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::ConsoleWindow>(
|
||||
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();
|
||||
|
||||
Reference in New Issue
Block a user