Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean mods.cpp #5103

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions soh/soh/Enhancements/DifficultyOptions/BonkDamage.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/Enhancements/enhancementTypes.h"
#include "soh/ShipInit.hpp"

extern "C" {
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
#include "functions.h"
#include "macros.h"
}

#define CVAR_BONK_DAMAGE_NAME CVAR_ENHANCEMENT("BonkDamageMult")
#define CVAR_BONK_DAMAGE_DEFAULT BONK_DAMAGE_NONE
#define CVAR_BONK_DAMAGE_VALUE CVarGetInteger(CVAR_BONK_DAMAGE_NAME, CVAR_BONK_DAMAGE_DEFAULT)

void OnPlayerBonkDamage() {
uint8_t bonkOption = CVAR_BONK_DAMAGE_VALUE;
if (bonkOption == BONK_DAMAGE_NONE) {
return;
}

if (bonkOption == BONK_DAMAGE_OHKO) {
gSaveContext.health = 0;
return;
}

uint16_t bonkDamage = 0;
switch (bonkOption) {
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;
}

void RegisterBonkDamage() {
COND_HOOK(OnPlayerBonk, CVAR_BONK_DAMAGE_VALUE, OnPlayerBonkDamage);
}

static RegisterShipInitFunc initFunc(RegisterBonkDamage, { CVAR_BONK_DAMAGE_NAME });
34 changes: 34 additions & 0 deletions soh/soh/Enhancements/DifficultyOptions/DeleteFileOnDeath.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/SaveManager.h"
#include "soh/ShipInit.hpp"

extern "C" {
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
#include "macros.h"
}

#define CVAR_DELETE_FILE_ON_DEATH_NAME CVAR_ENHANCEMENT("DeleteFileOnDeath")
#define CVAR_DELETE_FILE_ON_DEATH_DEFAULT 0
#define CVAR_DELETE_FILE_ON_DEATH_VALUE CVarGetInteger(CVAR_DELETE_FILE_ON_DEATH_NAME, CVAR_DELETE_FILE_ON_DEATH_DEFAULT)

void OnGameFrameUpdateDeleteFileOnDeath() {
if (
!GameInteractor::IsSaveLoaded() ||
gPlayState == NULL ||
gPlayState->gameOverCtx.state != GAMEOVER_DEATH_MENU ||
gPlayState->pauseCtx.state != 9
) {
return;
}

SaveManager::Instance->DeleteZeldaFile(gSaveContext.fileNum);
std::reinterpret_pointer_cast<Ship::ConsoleWindow>(Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console"))->Dispatch("reset");
}

void RegisterDeleteFileOnDeath() {
COND_HOOK(OnGameFrameUpdate, CVAR_DELETE_FILE_ON_DEATH_VALUE, OnGameFrameUpdateDeleteFileOnDeath);
}

static RegisterShipInitFunc initFunc(RegisterDeleteFileOnDeath, { CVAR_DELETE_FILE_ON_DEATH_NAME });
37 changes: 37 additions & 0 deletions soh/soh/Enhancements/DifficultyOptions/HurtContainerMode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"

extern "C" {
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
#include "macros.h"
}

#define CVAR_BONK_DAMAGE_NAME CVAR_ENHANCEMENT("HurtContainer")
#define CVAR_BONK_DAMAGE_DEFAULT 0
#define CVAR_BONK_DAMAGE_VALUE CVarGetInteger(CVAR_BONK_DAMAGE_NAME, CVAR_BONK_DAMAGE_DEFAULT)

void OnLoadGameHurtContainerMode(int32_t _fileNum) {
static bool hurtEnabled = false;
if (hurtEnabled == CVAR_BONK_DAMAGE_VALUE) {
return;
}

hurtEnabled = CVAR_BONK_DAMAGE_VALUE;
uint16_t getHeartPieces = gSaveContext.ship.stats.heartPieces / 4;
uint16_t getHeartContainers = gSaveContext.ship.stats.heartContainers;

if (hurtEnabled) {
gSaveContext.healthCapacity = 320 - ((getHeartPieces + getHeartContainers) * 16);
} else {
gSaveContext.healthCapacity = 48 + ((getHeartPieces + getHeartContainers) * 16);
}
}

void RegisterHurtContainerMode() {
COND_HOOK(OnLoadGame, true, OnLoadGameHurtContainerMode);
OnLoadGameHurtContainerMode(0);
}

static RegisterShipInitFunc initFunc(RegisterHurtContainerMode, { CVAR_BONK_DAMAGE_NAME });
64 changes: 64 additions & 0 deletions soh/soh/Enhancements/DifficultyOptions/HyperBosses.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"

extern "C" {
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
#include "functions.h"
#include "macros.h"
}

#define CVAR_HYPER_BOSSES_NAME CVAR_ENHANCEMENT("HyperBosses")
#define CVAR_HYPER_BOSSES_DEFAULT 0
#define CVAR_HYPER_BOSSES_VALUE CVarGetInteger(CVAR_HYPER_BOSSES_NAME, CVAR_HYPER_BOSSES_DEFAULT)

bool IsHyperBossesActive() {
return CVAR_HYPER_BOSSES_VALUE ||
(IS_BOSS_RUSH && gSaveContext.ship.quest.data.bossRush.options[BR_OPTIONS_HYPERBOSSES] == BR_CHOICE_HYPERBOSSES_YES);
}

void OnActorUpdateHyperBosses(void* refActor) {
// Run the update function a second time to make bosses move and act twice as fast.
Player* player = GET_PLAYER(gPlayState);
Actor* actor = static_cast<Actor*>(refActor);

uint8_t isBossActor =
actor->id == ACTOR_BOSS_GOMA || // Gohma
actor->id == ACTOR_BOSS_DODONGO || // King Dodongo
actor->id == ACTOR_EN_BDFIRE || // King Dodongo Fire Breath
actor->id == ACTOR_BOSS_VA || // Barinade
actor->id == ACTOR_BOSS_GANONDROF || // Phantom Ganon
actor->id == ACTOR_EN_FHG_FIRE || // Phantom Ganon/Ganondorf Energy Ball/Thunder
actor->id == ACTOR_EN_FHG || // Phantom Ganon's Horse
actor->id == ACTOR_BOSS_FD || actor->id == ACTOR_BOSS_FD2 || // Volvagia (grounded/flying)
actor->id == ACTOR_EN_VB_BALL || // Volvagia Rocks
actor->id == ACTOR_BOSS_MO || // Morpha
actor->id == ACTOR_BOSS_SST || // Bongo Bongo
actor->id == ACTOR_BOSS_TW || // Twinrova
actor->id == ACTOR_BOSS_GANON || // Ganondorf
actor->id == ACTOR_BOSS_GANON2; // Ganon

// Don't apply during cutscenes because it causes weird behaviour and/or crashes on some bosses.
if (IsHyperBossesActive() && isBossActor && !Player_InBlockingCsMode(gPlayState, player)) {
// Barinade needs to be updated in sequence to avoid unintended behaviour.
if (actor->id == ACTOR_BOSS_VA) {
// params -1 is BOSSVA_BODY
if (actor->params == -1) {
Actor* actorList = gPlayState->actorCtx.actorLists[ACTORCAT_BOSS].head;
while (actorList != NULL) {
GameInteractor::RawAction::UpdateActor(actorList);
actorList = actorList->next;
}
}
} else {
GameInteractor::RawAction::UpdateActor(actor);
}
}
}

void RegisterHyperBosses() {
COND_HOOK(OnActorUpdate, IsHyperBossesActive(), OnActorUpdateHyperBosses);
}

static RegisterShipInitFunc initFunc(RegisterHyperBosses, { CVAR_HYPER_BOSSES_NAME });
34 changes: 34 additions & 0 deletions soh/soh/Enhancements/DifficultyOptions/HyperEnemies.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"

extern "C" {
extern PlayState* gPlayState;
#include "functions.h"
#include "macros.h"
}

#define CVAR_HYPER_ENEMIES_NAME CVAR_ENHANCEMENT("HyperEnemies")
#define CVAR_HYPER_ENEMIES_DEFAULT 0
#define CVAR_HYPER_ENEMIES_VALUE CVarGetInteger(CVAR_HYPER_ENEMIES_NAME, CVAR_HYPER_ENEMIES_DEFAULT)

void OnActorUpdateHyperEnemies(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<Actor*>(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);
}
}

void RegisterHyperEnemies() {
COND_HOOK(OnActorUpdate, CVAR_HYPER_ENEMIES_VALUE, OnActorUpdateHyperEnemies);
}

static RegisterShipInitFunc initFunc(RegisterHyperEnemies, { CVAR_HYPER_ENEMIES_NAME });
55 changes: 55 additions & 0 deletions soh/soh/Enhancements/DifficultyOptions/PermanentHeartLoss.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
#include "soh/OTRGlobals.h"

extern "C" {
extern SaveContext gSaveContext;
#include "macros.h"
}

#define CVAR_PERMANENT_HEART_LOSS_NAME CVAR_ENHANCEMENT("PermanentHeartLoss")
#define CVAR_PERMANENT_HEART_LOSS_DEFAULT 0
#define CVAR_PERMANENT_HEART_LOSS_VALUE CVarGetInteger(CVAR_PERMANENT_HEART_LOSS_NAME, CVAR_PERMANENT_HEART_LOSS_DEFAULT)

static bool hasAffectedHealth = false;

void UpdatePermanentHeartLossState() {
if (!GameInteractor::IsSaveLoaded()) return;

if (!CVAR_PERMANENT_HEART_LOSS_VALUE && 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 OnPlayerUpdatePermanentHeartLoss() {
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;
}
}

void OnLoadGamePermanentHeartLoss(int16_t fileNum) {
hasAffectedHealth = false;
UpdatePermanentHeartLossState();
}

void RegisterPermanentHeartLoss() {
COND_HOOK(OnLoadGame, CVAR_PERMANENT_HEART_LOSS_VALUE, OnLoadGamePermanentHeartLoss);
COND_HOOK(OnPlayerUpdate, CVAR_PERMANENT_HEART_LOSS_VALUE, OnPlayerUpdatePermanentHeartLoss);
UpdatePermanentHeartLossState();
}

static RegisterShipInitFunc initFunc(RegisterPermanentHeartLoss, { CVAR_PERMANENT_HEART_LOSS_NAME });
68 changes: 68 additions & 0 deletions soh/soh/Enhancements/ExtraModes/MirrorMode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#include <libultraship/bridge.h>
#include "soh/Enhancements/cosmetics/authenticGfxPatches.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/Enhancements/randomizer/context.h"
#include "soh/Enhancements/enhancementTypes.h"
#include "soh/ResourceManagerHelpers.h"
#include "soh/ShipInit.hpp"

extern "C" {
extern SaveContext gSaveContext;
extern PlayState* gPlayState;
#include "macros.h"
}

#define CVAR_MIRRORED_WORLD_MODE_NAME CVAR_ENHANCEMENT("MirroredWorldMode")
#define CVAR_MIRRORED_WORLD_MODE_DEFAULT MIRRORED_WORLD_OFF
#define CVAR_MIRRORED_WORLD_MODE_VALUE CVarGetInteger(CVAR_MIRRORED_WORLD_MODE_NAME, CVAR_MIRRORED_WORLD_MODE_DEFAULT)

#define CVAR_MIRRORED_WORLD_NAME CVAR_ENHANCEMENT("MirroredWorld")
#define CVAR_MIRRORED_WORLD_DEFAULT false
#define CVAR_MIRRORED_WORLD_VALUE CVarGetInteger(CVAR_MIRRORED_WORLD_NAME, CVAR_MIRRORED_WORLD_DEFAULT)

void OnSceneInitMirrorMode(s32 sceneNum) {
static bool prevMirroredWorld = false;
bool nextMirroredWorld = false;

s16 mirroredMode = CVAR_MIRRORED_WORLD_MODE_VALUE;
s16 inDungeon = (sceneNum >= SCENE_DEKU_TREE && sceneNum <= SCENE_INSIDE_GANONS_CASTLE_COLLAPSE && sceneNum != SCENE_THIEVES_HIDEOUT) ||
(sceneNum >= SCENE_DEKU_TREE_BOSS && sceneNum <= SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) ||
(sceneNum == SCENE_GANON_BOSS);

if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
u32 seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(seed);
}

bool randomMirror = Random(0, 2) == 1;

if (
mirroredMode == MIRRORED_WORLD_ALWAYS ||
((mirroredMode == MIRRORED_WORLD_RANDOM || mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) && randomMirror) ||
// Dungeon modes
(inDungeon && (mirroredMode == MIRRORED_WORLD_DUNGEONS_All ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_VANILLA && !ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
(mirroredMode == MIRRORED_WORLD_DUNGEONS_MQ && ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) && randomMirror)))
) {
nextMirroredWorld = true;
CVarSetInteger(CVAR_MIRRORED_WORLD_NAME, true);
} else {
nextMirroredWorld = false;
CVarClear(CVAR_MIRRORED_WORLD_NAME);
}

if (prevMirroredWorld != nextMirroredWorld) {
prevMirroredWorld = nextMirroredWorld;
ApplyMirrorWorldGfxPatches();
}
}

void RegisterMirrorMode() {
COND_HOOK(OnSceneInit, CVAR_MIRRORED_WORLD_MODE_VALUE, OnSceneInitMirrorMode);
if (gPlayState != NULL) {
OnSceneInitMirrorMode(gPlayState->sceneNum);
}
}

static RegisterShipInitFunc initFunc(RegisterMirrorMode, { CVAR_MIRRORED_WORLD_MODE_NAME });
Loading
Loading