mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-02-07 02:40:30 -05:00
Implement GameInteractor & move CrowdControl and console commands to it (#2358)
* Begin GameInteractor * Basic skeleton of PoC * WIP * First 2 CC effects transitioned to GameInteractor * Prepare GameInteractor classes for CrowdControl * More effects & replace chaosEffects with GameInteractor * CC connection fixes & all CC effects (enemy spawns still borked) * First couple of build error fixes * Fix build * Proper enemy spawning * Clean up old CC code * Extract link size/invisibility into GameInteractor * Small fix/cleanup * Suggestions for PR * Address PR comment * Addressed more comments & small adjustments * Fix crash when spawning enemies * Remove Remove() * Move checks into Apply() and move CC and some console commands to it * Use inheritance to abstract check on application * Rename prefix Actions with RawAction * Make Remove return a Result * Fix issue with compilation * debugconsole -> GameInteractionEffects progress * Add State in GI * Unify some Effects * Port more debug console items * Remove state modifyiers from raw actions * Port over last raw action / state in console * Adjust some types * Consolidate link size modifier effect * Adjust more types * Define category strings in CC * Clean up remaining non defined strings * Fix bug in timed effects * Rename old pack * CC fixes * Translate GI enum function * Console cleanup/fixes/consistency Co-authored-by: David Chavez <david@dcvz.io>
This commit is contained in:
parent
ec4cee787c
commit
170a9103f9
@ -258,6 +258,12 @@ set(Header_Files__soh__Enhancements__item_tables
|
||||
|
||||
source_group("Header Files\\soh\\Enhancements\\item-tables" FILES ${Header_Files__soh__Enhancements__item_tables})
|
||||
|
||||
set(Header_Files__soh__Enhancements__game_interactor
|
||||
"soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
"soh/Enhancements/game-interactor/GameInteractionEffect.h"
|
||||
)
|
||||
source_group("Header Files\\soh\\Enhancements\\game-interactor" FILES ${Header_Files__soh__Enhancements__game_interactor})
|
||||
|
||||
if (BUILD_CROWD_CONTROL)
|
||||
set(Header_Files__soh__Enhancements__crowd_control
|
||||
"soh/Enhancements/crowd-control/CrowdControl.h"
|
||||
@ -603,6 +609,14 @@ set(Source_Files__soh__Enhancements__item_tables
|
||||
|
||||
source_group("Source Files\\soh\\Enhancements\\item-tables" FILES ${Source_Files__soh__Enhancements__item_tables})
|
||||
|
||||
set(Source_Files__soh__Enhancements__game_interactor
|
||||
"soh/Enhancements/game-interactor/GameInteractor.cpp"
|
||||
"soh/Enhancements/game-interactor/GameInteractor_RawAction.cpp"
|
||||
"soh/Enhancements/game-interactor/GameInteractor_State.cpp"
|
||||
"soh/Enhancements/game-interactor/GameInteractionEffect.cpp"
|
||||
)
|
||||
source_group("Source Files\\soh\\Enhancements\\game-interactor" FILES ${Source_Files__soh__Enhancements__game_interactor})
|
||||
|
||||
if (BUILD_CROWD_CONTROL)
|
||||
set(Source_Files__soh__Enhancements__crowd_control
|
||||
"soh/Enhancements/crowd-control/CrowdControl.cpp"
|
||||
@ -1821,6 +1835,7 @@ set(ALL_FILES
|
||||
${Header_Files__soh__Enhancements__randomizer__3drando}
|
||||
${Header_Files__soh__Enhancements__item_tables}
|
||||
${Header_Files__soh__Enhancements__custom_message}
|
||||
${Header_Files__soh__Enhancements__game_interactor}
|
||||
${Header_Files__soh__Enhancements__crowd_control}
|
||||
${Source_Files__soh}
|
||||
${Source_Files__soh__Enhancements}
|
||||
@ -1834,6 +1849,7 @@ set(ALL_FILES
|
||||
${Source_Files__soh__Enhancements__randomizer__3drando__location_access}
|
||||
${Source_Files__soh__Enhancements__item_tables}
|
||||
${Source_Files__soh__Enhancements__custom_message}
|
||||
${Source_Files__soh__Enhancements__game_interactor}
|
||||
${Source_Files__soh__Enhancements__crowd_control}
|
||||
${Source_Files__src__boot}
|
||||
${Source_Files__src__buffers}
|
||||
|
@ -1079,8 +1079,6 @@ void Interface_SetDoAction(PlayState* play, u16 action);
|
||||
void Interface_SetNaviCall(PlayState* play, u16 naviCallState);
|
||||
void Interface_LoadActionLabelB(PlayState* play, u16 action);
|
||||
s32 Health_ChangeBy(PlayState* play, s16 healthChange);
|
||||
void Health_GiveHearts(s16 hearts);
|
||||
void Health_RemoveHearts(s16 hearts);
|
||||
void Rupees_ChangeBy(s16 rupeeChange);
|
||||
void Inventory_ChangeAmmo(s16 item, s16 ammoChange);
|
||||
void Magic_Fill(PlayState* play);
|
||||
|
@ -17,10 +17,6 @@ extern "C" {
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
#include "../debugconsole.h"
|
||||
|
||||
#define CMD_EXECUTE SohImGui::GetConsole()->Dispatch
|
||||
|
||||
#define EFFECT_HIGH_GRAVITY "high_gravity"
|
||||
#define EFFECT_LOW_GRAVITY "low_gravity"
|
||||
#define EFFECT_DAMAGE_MULTIPLIER "damage_multiplier"
|
||||
@ -52,6 +48,7 @@ extern PlayState* gPlayState;
|
||||
#define EFFECT_INCREASE_SPEED "increase_speed"
|
||||
#define EFFECT_DECREASE_SPEED "decrease_speed"
|
||||
#define EFFECT_NO_Z_TARGETING "no_z"
|
||||
#define EFFECT_GIVE_DEKU_SHIELD "give_dekushield"
|
||||
|
||||
#define EFFECT_SPAWN_WALLMASTER "spawn_wallmaster"
|
||||
#define EFFECT_SPAWN_ARWING "spawn_arwing"
|
||||
@ -66,6 +63,18 @@ extern PlayState* gPlayState;
|
||||
#define EFFECT_SPAWN_LIKE_LIKE "spawn_likelike"
|
||||
#define EFFECT_SPAWN_CUCCO_STORM "cucco_storm"
|
||||
|
||||
#define EFFECT_CAT_UI "ui"
|
||||
#define EFFECT_CAT_GRAVITY "gravity"
|
||||
#define EFFECT_CAT_LINK_SIZE "link_size"
|
||||
#define EFFECT_CAT_PACIFIST "pacifist"
|
||||
#define EFFECT_CAT_NO_Z "no_z"
|
||||
#define EFFECT_CAT_WEATHER "weather"
|
||||
#define EFFECT_CAT_REVERSE_CONTROLS "reverse_controls"
|
||||
#define EFFECT_CAT_BOOTS "boots"
|
||||
#define EFFECT_CAT_SPEED "speed"
|
||||
#define EFFECT_CAT_DAMAGE_TAKEN "damage_taken"
|
||||
#define EFFECT_CAT_SPAWN_ENEMY "spawn_enemy"
|
||||
#define EFFECT_CAT_NONE "none"
|
||||
|
||||
void CrowdControl::Init() {
|
||||
SDLNet_Init();
|
||||
@ -142,34 +151,29 @@ void CrowdControl::ListenToServer() {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If effect is a one off run, let's execute
|
||||
// If effect is not a timed effect, execute and return result.
|
||||
if (!incomingEffect->timeRemaining) {
|
||||
EffectResult result =
|
||||
ExecuteEffect(incomingEffect->type.c_str(), incomingEffect->value, false);
|
||||
EffectResult result = CrowdControl::ExecuteEffect(incomingEffect);
|
||||
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining, result);
|
||||
} else {
|
||||
// check if a conflicting event is already active
|
||||
// If another timed effect is already active that conflicts with the incoming effect.
|
||||
bool isConflictingEffectActive = false;
|
||||
for (Effect* pack : activeEffects) {
|
||||
if (pack != incomingEffect && pack->category == incomingEffect->category &&
|
||||
pack->id < incomingEffect->id) {
|
||||
for (Effect* effect : activeEffects) {
|
||||
if (effect != incomingEffect && effect->category == incomingEffect->category && effect->id < incomingEffect->id) {
|
||||
isConflictingEffectActive = true;
|
||||
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining,
|
||||
EffectResult::Retry);
|
||||
|
||||
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining, EffectResult::Retry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// check if effect can be executed
|
||||
EffectResult result =
|
||||
ExecuteEffect(incomingEffect->type.c_str(), incomingEffect->value, true);
|
||||
if (result == EffectResult::Retry || result == EffectResult::Failure) {
|
||||
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining, result);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isConflictingEffectActive) {
|
||||
// Check if effect can be applied, if it can't, let CC know.
|
||||
EffectResult result = CrowdControl::CanApplyEffect(incomingEffect);
|
||||
if (result == EffectResult::Retry || result == EffectResult::Failure) {
|
||||
EmitMessage(tcpsock, incomingEffect->id, incomingEffect->timeRemaining, result);
|
||||
continue;
|
||||
}
|
||||
|
||||
activeEffectsMutex.lock();
|
||||
activeEffects.push_back(incomingEffect);
|
||||
activeEffectsMutex.unlock();
|
||||
@ -187,27 +191,31 @@ void CrowdControl::ListenToServer() {
|
||||
|
||||
void CrowdControl::ProcessActiveEffects() {
|
||||
while (isEnabled) {
|
||||
// we only want to send events when status changes, on start we send Success,
|
||||
// if it fails at some point, we send Pause, and when it starts to succeed again we send Success.
|
||||
// We only want to send events when status changes, on start we send Success.
|
||||
// If it fails at some point, we send Pause, and when it starts to succeed again we send Success.
|
||||
// CC uses this to pause the timer on the overlay.
|
||||
activeEffectsMutex.lock();
|
||||
auto it = activeEffects.begin();
|
||||
|
||||
while (it != activeEffects.end()) {
|
||||
Effect *effect = *it;
|
||||
EffectResult result = ExecuteEffect(effect->type.c_str(), effect->value, false);
|
||||
EffectResult result = CrowdControl::ExecuteEffect(effect);
|
||||
|
||||
if (result == EffectResult::Success) {
|
||||
// If time remaining has reached 0, we have finished the effect
|
||||
// If time remaining has reached 0, we have finished the effect.
|
||||
if (effect->timeRemaining <= 0) {
|
||||
it = activeEffects.erase(std::remove(activeEffects.begin(), activeEffects.end(), effect),
|
||||
activeEffects.end());
|
||||
RemoveEffect(effect->type.c_str());
|
||||
|
||||
GameInteractor::RemoveEffect(effect->giEffect);
|
||||
delete effect;
|
||||
} else {
|
||||
// If we have a success after previously being paused, fire Resume event
|
||||
// If we have a success after previously being paused, tell CC to resume timer.
|
||||
if (effect->isPaused) {
|
||||
effect->isPaused = false;
|
||||
EmitMessage(tcpsock, effect->id, effect->timeRemaining, EffectResult::Resumed);
|
||||
// If not paused before, subtract time from the timer and send a Success event if
|
||||
// the result is different from the last time this was ran.
|
||||
// Timed events are put on a thread that runs once per second.
|
||||
} else {
|
||||
effect->timeRemaining -= 1000;
|
||||
if (result != effect->lastExecutionResult) {
|
||||
@ -215,7 +223,6 @@ void CrowdControl::ProcessActiveEffects() {
|
||||
EmitMessage(tcpsock, effect->id, effect->timeRemaining, EffectResult::Success);
|
||||
}
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
} else { // Timed effects only do Success or Retry
|
||||
@ -223,7 +230,6 @@ void CrowdControl::ProcessActiveEffects() {
|
||||
effect->isPaused = true;
|
||||
EmitMessage(tcpsock, effect->id, effect->timeRemaining, EffectResult::Paused);
|
||||
}
|
||||
|
||||
it++;
|
||||
}
|
||||
}
|
||||
@ -260,328 +266,224 @@ CrowdControl::Effect* CrowdControl::ParseMessage(char payload[512]) {
|
||||
effect->lastExecutionResult = EffectResult::Initiate;
|
||||
effect->id = dataReceived["id"];
|
||||
auto parameters = dataReceived["parameters"];
|
||||
if (parameters.size() > 0) {
|
||||
effect->value = dataReceived["parameters"][0];
|
||||
}
|
||||
effect->type = dataReceived["code"].get<std::string>();
|
||||
auto effectName = dataReceived["code"].get<std::string>();
|
||||
|
||||
if (effect->type == EFFECT_HIGH_GRAVITY || effect->type == EFFECT_LOW_GRAVITY) {
|
||||
effect->category = "gravity";
|
||||
effect->timeRemaining = 30000;
|
||||
} else if (effect->type == EFFECT_DAMAGE_MULTIPLIER || effect->type == EFFECT_DEFENSE_MULTIPLIER) {
|
||||
effect->category = "defense";
|
||||
effect->timeRemaining = 30000;
|
||||
} else if (effect->type == EFFECT_GIANT_LINK || effect->type == EFFECT_MINISH_LINK ||
|
||||
effect->type == EFFECT_INVISIBLE_LINK || effect->type == EFFECT_PAPER_LINK) {
|
||||
effect->category = "link_size";
|
||||
effect->timeRemaining = 30000;
|
||||
} else if (effect->type == EFFECT_FREEZE || effect->type == EFFECT_DAMAGE || effect->type == EFFECT_HEAL ||
|
||||
effect->type == EFFECT_KNOCKBACK || effect->type == EFFECT_ELECTROCUTE ||
|
||||
effect->type == EFFECT_BURN || effect->type == EFFECT_KILL) {
|
||||
effect->category = "link_damage";
|
||||
} else if (effect->type == EFFECT_HOVER_BOOTS || effect->type == EFFECT_IRON_BOOTS) {
|
||||
effect->category = "boots";
|
||||
effect->timeRemaining = 30000;
|
||||
} else if (effect->type == EFFECT_ADD_HEART_CONTAINER || effect->type == EFFECT_REMOVE_HEART_CONTAINER) {
|
||||
effect->category = "heart_container";
|
||||
} else if (effect->type == EFFECT_NO_UI) {
|
||||
effect->category = "ui";
|
||||
if (parameters.size() > 0) {
|
||||
effect->value[0] = dataReceived["parameters"][0];
|
||||
}
|
||||
|
||||
// Assign GameInteractionEffect + values to CC effect.
|
||||
// Categories are mostly used for checking for conflicting timed effects.
|
||||
if (effectName == EFFECT_ADD_HEART_CONTAINER) {
|
||||
effect->giEffect = new GameInteractionEffect::ModifyHeartContainers();
|
||||
effect->giEffect->parameter = 1;
|
||||
} else if (effectName == EFFECT_REMOVE_HEART_CONTAINER) {
|
||||
effect->giEffect = new GameInteractionEffect::ModifyHeartContainers();
|
||||
effect->giEffect->parameter = -1;
|
||||
} else if (effectName == EFFECT_FILL_MAGIC) {
|
||||
effect->giEffect = new GameInteractionEffect::FillMagic();
|
||||
} else if (effectName == EFFECT_EMPTY_MAGIC) {
|
||||
effect->giEffect = new GameInteractionEffect::EmptyMagic();
|
||||
} else if (effectName == EFFECT_ADD_RUPEES) {
|
||||
effect->giEffect = new GameInteractionEffect::ModifyRupees();
|
||||
} else if (effectName == EFFECT_REMOVE_RUPEES) {
|
||||
effect->giEffect = new GameInteractionEffect::ModifyRupees();
|
||||
effect->paramMultiplier = -1;
|
||||
} else if (effectName == EFFECT_NO_UI) {
|
||||
effect->category = EFFECT_CAT_UI;
|
||||
effect->timeRemaining = 60000;
|
||||
} else if (effect->type == EFFECT_FILL_MAGIC || effect->type == EFFECT_EMPTY_MAGIC) {
|
||||
effect->category = "magic";
|
||||
} else if (effect->type == EFFECT_OHKO) {
|
||||
effect->category = "ohko";
|
||||
effect->giEffect = new GameInteractionEffect::NoUI();
|
||||
} else if (effectName == EFFECT_HIGH_GRAVITY) {
|
||||
effect->category = EFFECT_CAT_GRAVITY;
|
||||
effect->timeRemaining = 30000;
|
||||
} else if (effect->type == EFFECT_PACIFIST) {
|
||||
effect->category = "pacifist";
|
||||
effect->giEffect = new GameInteractionEffect::ModifyGravity();
|
||||
effect->giEffect->parameter = GI_GRAVITY_LEVEL_HEAVY;
|
||||
} else if (effectName == EFFECT_LOW_GRAVITY) {
|
||||
effect->category = EFFECT_CAT_GRAVITY;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::ModifyGravity();
|
||||
effect->giEffect->parameter = GI_GRAVITY_LEVEL_LIGHT;
|
||||
} else if (effectName == EFFECT_KILL) {
|
||||
effect->giEffect = new GameInteractionEffect::SetPlayerHealth();
|
||||
effect->value[0] = 0;
|
||||
} else if (effectName == EFFECT_FREEZE) {
|
||||
effect->giEffect = new GameInteractionEffect::FreezePlayer();
|
||||
} else if (effectName == EFFECT_BURN) {
|
||||
effect->giEffect = new GameInteractionEffect::BurnPlayer();
|
||||
} else if (effectName == EFFECT_ELECTROCUTE) {
|
||||
effect->giEffect = new GameInteractionEffect::ElectrocutePlayer();
|
||||
} else if (effectName == EFFECT_KNOCKBACK) {
|
||||
effect->giEffect = new GameInteractionEffect::KnockbackPlayer();
|
||||
} else if (effectName == EFFECT_HEAL) {
|
||||
effect->giEffect = new GameInteractionEffect::ModifyHealth();
|
||||
} else if (effectName == EFFECT_DAMAGE) {
|
||||
effect->giEffect = new GameInteractionEffect::ModifyHealth();
|
||||
effect->paramMultiplier = -1;
|
||||
} else if (effectName == EFFECT_GIANT_LINK) {
|
||||
effect->category = EFFECT_CAT_LINK_SIZE;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
|
||||
effect->giEffect->parameter = GI_LINK_SIZE_GIANT;
|
||||
} else if (effectName == EFFECT_MINISH_LINK) {
|
||||
effect->category = EFFECT_CAT_LINK_SIZE;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
|
||||
effect->giEffect->parameter = GI_LINK_SIZE_MINISH;
|
||||
} else if (effectName == EFFECT_PAPER_LINK) {
|
||||
effect->category = EFFECT_CAT_LINK_SIZE;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::ModifyLinkSize();
|
||||
effect->giEffect->parameter = GI_LINK_SIZE_PAPER;
|
||||
} else if (effectName == EFFECT_INVISIBLE_LINK) {
|
||||
effect->category = EFFECT_CAT_LINK_SIZE;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::InvisibleLink();
|
||||
} else if (effectName == EFFECT_PACIFIST) {
|
||||
effect->category = EFFECT_CAT_PACIFIST;
|
||||
effect->timeRemaining = 15000;
|
||||
} else if (effect->type == EFFECT_RAINSTORM) {
|
||||
effect->category = "weather";
|
||||
effect->giEffect = new GameInteractionEffect::PacifistMode();
|
||||
} else if (effectName == EFFECT_NO_Z_TARGETING) {
|
||||
effect->category = EFFECT_CAT_NO_Z;
|
||||
effect->timeRemaining = 30000;
|
||||
} else if (effect->type == EFFECT_REVERSE_CONTROLS) {
|
||||
effect->category = "controls";
|
||||
effect->giEffect = new GameInteractionEffect::DisableZTargeting();
|
||||
} else if (effectName == EFFECT_RAINSTORM) {
|
||||
effect->category = EFFECT_CAT_WEATHER;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::WeatherRainstorm();
|
||||
} else if (effectName == EFFECT_REVERSE_CONTROLS) {
|
||||
effect->category = EFFECT_CAT_REVERSE_CONTROLS;
|
||||
effect->timeRemaining = 60000;
|
||||
} else if (effect->type == EFFECT_ADD_RUPEES || effect->type == EFFECT_REMOVE_RUPEES) {
|
||||
effect->category = "rupees";
|
||||
} else if (effect->type == EFFECT_INCREASE_SPEED || effect->type == EFFECT_DECREASE_SPEED) {
|
||||
effect->category = "speed";
|
||||
effect->giEffect = new GameInteractionEffect::ReverseControls();
|
||||
} else if (effectName == EFFECT_IRON_BOOTS) {
|
||||
effect->category = EFFECT_CAT_BOOTS;
|
||||
effect->timeRemaining = 30000;
|
||||
} else if (effect->type == EFFECT_NO_Z_TARGETING) {
|
||||
effect->category = "no_z";
|
||||
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
|
||||
effect->giEffect->parameter = PLAYER_BOOTS_IRON;
|
||||
} else if (effectName == EFFECT_HOVER_BOOTS) {
|
||||
effect->category = EFFECT_CAT_BOOTS;
|
||||
effect->timeRemaining = 30000;
|
||||
} else if (effect->type == EFFECT_SPAWN_WALLMASTER || effect->type == EFFECT_SPAWN_ARWING ||
|
||||
effect->type == EFFECT_SPAWN_DARK_LINK || effect->type == EFFECT_SPAWN_STALFOS ||
|
||||
effect->type == EFFECT_SPAWN_WOLFOS || effect->type == EFFECT_SPAWN_FREEZARD ||
|
||||
effect->type == EFFECT_SPAWN_KEESE || effect->type == EFFECT_SPAWN_ICE_KEESE ||
|
||||
effect->type == EFFECT_SPAWN_FIRE_KEESE || effect->type == EFFECT_SPAWN_TEKTITE ||
|
||||
effect->type == EFFECT_SPAWN_LIKE_LIKE || effect->type == EFFECT_SPAWN_CUCCO_STORM) {
|
||||
effect->category = "spawn";
|
||||
} else {
|
||||
effect->category = "none";
|
||||
effect->timeRemaining = 0;
|
||||
effect->giEffect = new GameInteractionEffect::ForceEquipBoots();
|
||||
effect->giEffect->parameter = PLAYER_BOOTS_HOVER;;
|
||||
} else if (effectName == EFFECT_GIVE_DEKU_SHIELD) {
|
||||
effect->giEffect = new GameInteractionEffect::GiveDekuShield();
|
||||
} else if (effectName == EFFECT_INCREASE_SPEED) {
|
||||
effect->category = EFFECT_CAT_SPEED;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier();
|
||||
effect->giEffect->parameter = 2;
|
||||
} else if (effectName == EFFECT_DECREASE_SPEED) {
|
||||
effect->category = EFFECT_CAT_SPEED;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::ModifyRunSpeedModifier();
|
||||
effect->giEffect->parameter = -2;
|
||||
} else if (effectName == EFFECT_OHKO) {
|
||||
effect->category = EFFECT_CAT_DAMAGE_TAKEN;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::OneHitKO();
|
||||
} else if (effectName == EFFECT_DAMAGE_MULTIPLIER) {
|
||||
effect->category = EFFECT_CAT_DAMAGE_TAKEN;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::ModifyDefenseModifier();
|
||||
effect->paramMultiplier = -1;
|
||||
} else if (effectName == EFFECT_DEFENSE_MULTIPLIER) {
|
||||
effect->category = EFFECT_CAT_DAMAGE_TAKEN;
|
||||
effect->timeRemaining = 30000;
|
||||
effect->giEffect = new GameInteractionEffect::ModifyDefenseModifier();
|
||||
} else if (effectName == EFFECT_SPAWN_CUCCO_STORM) {
|
||||
effect->giEffect = new GameInteractionEffect::SpawnCuccoStorm();
|
||||
} else if (effectName == EFFECT_SPAWN_WALLMASTER) {
|
||||
effect->value[0] = ACTOR_EN_WALLMAS;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_ARWING) {
|
||||
effect->value[0] = ACTOR_EN_CLEAR_TAG;
|
||||
// Parameter for no cutscene Arwing
|
||||
effect->value[1] = 1;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_DARK_LINK) {
|
||||
effect->value[0] = ACTOR_EN_TORCH2;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_STALFOS) {
|
||||
effect->value[0] = ACTOR_EN_TEST;
|
||||
// Parameter for gravity-obeying Stalfos
|
||||
effect->value[1] = 2;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_WOLFOS) {
|
||||
effect->value[0] = ACTOR_EN_WF;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_FREEZARD) {
|
||||
effect->value[0] = ACTOR_EN_FZ;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_KEESE) {
|
||||
effect->value[0] = ACTOR_EN_FIREFLY;
|
||||
// Parameter for normal keese
|
||||
effect->value[1] = 2;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_ICE_KEESE) {
|
||||
effect->value[0] = ACTOR_EN_FIREFLY;
|
||||
// Parameter for ice keese
|
||||
effect->value[1] = 4;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_FIRE_KEESE) {
|
||||
effect->value[0] = ACTOR_EN_FIREFLY;
|
||||
// Parameter for fire keese
|
||||
effect->value[1] = 1;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_TEKTITE) {
|
||||
effect->value[0] = ACTOR_EN_TITE;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
} else if (effectName == EFFECT_SPAWN_LIKE_LIKE) {
|
||||
effect->value[0] = ACTOR_EN_RR;
|
||||
effect->category = EFFECT_CAT_SPAWN_ENEMY;
|
||||
}
|
||||
|
||||
// If no value is specifically set, default to using whatever CC sends us.
|
||||
// Values are used for various things depending on the effect, but they
|
||||
// usually represent the "amount" of an effect. Amount of hearts healed,
|
||||
// strength of knockback, etc.
|
||||
if (effect->giEffect != NULL) {
|
||||
if (!effect->giEffect->parameter && effect->value[0]) {
|
||||
effect->giEffect->parameter = effect->value[0] * effect->paramMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
if (effect->category == "") {
|
||||
effect->category = EFFECT_CAT_NONE;
|
||||
}
|
||||
|
||||
return effect;
|
||||
}
|
||||
|
||||
CrowdControl::EffectResult CrowdControl::ExecuteEffect(std::string effectId, uint32_t value, bool dryRun) {
|
||||
// Don't execute effect and don't advance timer when the player is not in a proper loaded savefile
|
||||
// and when they're busy dying.
|
||||
if (gPlayState == NULL || gPlayState->gameOverCtx.state > 0 || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) {
|
||||
return EffectResult::Retry;
|
||||
CrowdControl::EffectResult CrowdControl::ExecuteEffect(Effect* effect) {
|
||||
GameInteractionEffectQueryResult giResult;
|
||||
if (effect->category == EFFECT_CAT_SPAWN_ENEMY) {
|
||||
giResult = GameInteractor::RawAction::SpawnEnemyWithOffset(effect->value[0], effect->value[1]);
|
||||
} else {
|
||||
giResult = GameInteractor::ApplyEffect(effect->giEffect);
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
|
||||
if (player != NULL) {
|
||||
if (effectId == EFFECT_ADD_HEART_CONTAINER) {
|
||||
if (gSaveContext.healthCapacity >= 0x140) {
|
||||
return EffectResult::Failure;
|
||||
}
|
||||
|
||||
if (dryRun == 0) CMD_EXECUTE(EFFECT_ADD_HEART_CONTAINER);
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_REMOVE_HEART_CONTAINER) {
|
||||
if ((gSaveContext.healthCapacity - 0x10) <= 0) {
|
||||
return EffectResult::Failure;
|
||||
}
|
||||
|
||||
if (dryRun == 0) CMD_EXECUTE(EFFECT_REMOVE_HEART_CONTAINER);
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_FILL_MAGIC) {
|
||||
if (!gSaveContext.isMagicAcquired) {
|
||||
return EffectResult::Failure;
|
||||
}
|
||||
|
||||
if (gSaveContext.magic >= (gSaveContext.isDoubleMagicAcquired + 1) + 0x30) {
|
||||
return EffectResult::Failure;
|
||||
}
|
||||
|
||||
if (dryRun == 0) CMD_EXECUTE(EFFECT_FILL_MAGIC);
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_EMPTY_MAGIC) {
|
||||
if (!gSaveContext.isMagicAcquired || gSaveContext.magic <= 0) {
|
||||
return EffectResult::Failure;
|
||||
}
|
||||
|
||||
if (dryRun == 0) CMD_EXECUTE(EFFECT_EMPTY_MAGIC);
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_ADD_RUPEES) {
|
||||
if (dryRun == 0) CMD_EXECUTE(fmt::format("update_rupees {}", value));
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_REMOVE_RUPEES) {
|
||||
if (gSaveContext.rupees - value < 0) {
|
||||
return EffectResult::Failure;
|
||||
}
|
||||
|
||||
if (dryRun == 0) CMD_EXECUTE(fmt::format("update_rupees -{}", value));
|
||||
return EffectResult::Success;
|
||||
}
|
||||
}
|
||||
|
||||
if (player != NULL && !Player_InBlockingCsMode(gPlayState, player) && gPlayState->pauseCtx.state == 0
|
||||
&& gPlayState->msgCtx.msgMode == 0) {
|
||||
if (effectId == EFFECT_HIGH_GRAVITY) {
|
||||
if (dryRun == 0) CMD_EXECUTE("gravity 2");
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_LOW_GRAVITY) {
|
||||
if (dryRun == 0) CMD_EXECUTE("gravity 0");
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_KILL
|
||||
|| effectId == EFFECT_FREEZE
|
||||
|| effectId == EFFECT_BURN
|
||||
|| effectId == EFFECT_ELECTROCUTE
|
||||
|| effectId == EFFECT_SPAWN_CUCCO_STORM
|
||||
) {
|
||||
if (PlayerGrounded(player)) {
|
||||
if (dryRun == 0) CMD_EXECUTE(fmt::format("{}", effectId));
|
||||
return EffectResult::Success;
|
||||
}
|
||||
return EffectResult::Failure;
|
||||
} else if (effectId == EFFECT_HEAL
|
||||
|| effectId == EFFECT_KNOCKBACK
|
||||
) {
|
||||
if (dryRun == 0) CMD_EXECUTE(fmt::format("{} {}", effectId, value));
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_GIANT_LINK
|
||||
|| effectId == EFFECT_MINISH_LINK
|
||||
|| effectId == EFFECT_NO_UI
|
||||
|| effectId == EFFECT_INVISIBLE_LINK
|
||||
|| effectId == EFFECT_PAPER_LINK
|
||||
|| effectId == EFFECT_NO_Z_TARGETING
|
||||
|| effectId == EFFECT_OHKO
|
||||
|| effectId == EFFECT_PACIFIST
|
||||
|| effectId == EFFECT_RAINSTORM
|
||||
) {
|
||||
if (dryRun == 0) CMD_EXECUTE(fmt::format("{} 1", effectId));
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_REVERSE_CONTROLS) {
|
||||
if (dryRun == 0) CMD_EXECUTE("reverse_controls 1");
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_IRON_BOOTS) {
|
||||
if (dryRun == 0) CMD_EXECUTE("boots iron");
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_HOVER_BOOTS) {
|
||||
if (dryRun == 0) CMD_EXECUTE("boots hover");
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == "give_dekushield") {
|
||||
if (dryRun == 0) CMD_EXECUTE("givedekushield");
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_SPAWN_WALLMASTER
|
||||
|| effectId == EFFECT_SPAWN_ARWING
|
||||
|| effectId == EFFECT_SPAWN_DARK_LINK
|
||||
|| effectId == EFFECT_SPAWN_STALFOS
|
||||
|| effectId == EFFECT_SPAWN_WOLFOS
|
||||
|| effectId == EFFECT_SPAWN_FREEZARD
|
||||
|| effectId == EFFECT_SPAWN_KEESE
|
||||
|| effectId == EFFECT_SPAWN_ICE_KEESE
|
||||
|| effectId == EFFECT_SPAWN_FIRE_KEESE
|
||||
|| effectId == EFFECT_SPAWN_TEKTITE
|
||||
|| effectId == EFFECT_SPAWN_LIKE_LIKE
|
||||
) {
|
||||
if (dryRun == 0) {
|
||||
if (CrowdControl::SpawnEnemy(effectId)) {
|
||||
return EffectResult::Success;
|
||||
} else {
|
||||
return EffectResult::Failure;
|
||||
}
|
||||
}
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_INCREASE_SPEED) {
|
||||
if (dryRun == 0) CMD_EXECUTE("speed_modifier 2");
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_DECREASE_SPEED) {
|
||||
if (dryRun == 0) CMD_EXECUTE("speed_modifier -2");
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_DAMAGE_MULTIPLIER) {
|
||||
if (dryRun == 0) CMD_EXECUTE(fmt::format("defense_modifier -{}", value));
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_DEFENSE_MULTIPLIER) {
|
||||
if (dryRun == 0) CMD_EXECUTE(fmt::format("defense_modifier {}", value));
|
||||
return EffectResult::Success;
|
||||
} else if (effectId == EFFECT_DAMAGE) {
|
||||
if ((gSaveContext.health - (16 * value)) <= 0) {
|
||||
return EffectResult::Failure;
|
||||
}
|
||||
|
||||
if (dryRun == 0) CMD_EXECUTE(fmt::format("{} {}", effectId, value));
|
||||
return EffectResult::Success;
|
||||
}
|
||||
}
|
||||
|
||||
return EffectResult::Retry;
|
||||
return TranslateGiEnum(giResult);
|
||||
}
|
||||
|
||||
bool CrowdControl::SpawnEnemy(std::string effectId) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
|
||||
int enemyId = 0;
|
||||
int enemyParams = 0;
|
||||
float posXOffset = 0;
|
||||
float posYOffset = 0;
|
||||
float posZOffset = 0;
|
||||
|
||||
if (effectId == EFFECT_SPAWN_WALLMASTER) {
|
||||
enemyId = 17;
|
||||
} else if (effectId == EFFECT_SPAWN_ARWING) {
|
||||
// Don't allow Arwings in certain areas because they cause issues.
|
||||
// Locations: King dodongo room, Morpha room, Twinrova room, Ganondorf room, Fishing pond, Ganon's room
|
||||
// TODO: Swap this to disabling the option in CC options menu instead.
|
||||
if (gPlayState->sceneNum == SCENE_DDAN_BOSS || gPlayState->sceneNum == SCENE_MIZUSIN_BS ||
|
||||
gPlayState->sceneNum == SCENE_JYASINBOSS || gPlayState->sceneNum == SCENE_GANON_BOSS ||
|
||||
gPlayState->sceneNum == SCENE_TURIBORI || gPlayState->sceneNum == SCENE_GANON_DEMO) {
|
||||
return 0;
|
||||
}
|
||||
enemyId = 315;
|
||||
enemyParams = 1;
|
||||
posYOffset = 100;
|
||||
} else if (effectId == EFFECT_SPAWN_DARK_LINK) {
|
||||
enemyId = 51;
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (effectId == EFFECT_SPAWN_STALFOS) {
|
||||
enemyId = 2;
|
||||
enemyParams = 2;
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (effectId == EFFECT_SPAWN_WOLFOS) {
|
||||
enemyId = 431;
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (effectId == EFFECT_SPAWN_FREEZARD) {
|
||||
enemyId = 289;
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (effectId == EFFECT_SPAWN_KEESE) {
|
||||
enemyId = 19;
|
||||
enemyParams = 2;
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (effectId == EFFECT_SPAWN_ICE_KEESE) {
|
||||
enemyId = 19;
|
||||
enemyParams = 4;
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (effectId == EFFECT_SPAWN_FIRE_KEESE) {
|
||||
enemyId = 19;
|
||||
enemyParams = 1;
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (effectId == EFFECT_SPAWN_TEKTITE) {
|
||||
enemyId = 27;
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (effectId == EFFECT_SPAWN_LIKE_LIKE) {
|
||||
enemyId = 221;
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
}
|
||||
|
||||
return Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, player->actor.world.pos.x + posXOffset,
|
||||
player->actor.world.pos.y + posYOffset, player->actor.world.pos.z + posZOffset, 0, 0, 0, enemyParams, 0);
|
||||
/// Checks if effect can be applied -- should not be used to check for spawn enemy effects.
|
||||
CrowdControl::EffectResult CrowdControl::CanApplyEffect(Effect* effect) {
|
||||
assert(effect->category != EFFECT_CAT_SPAWN_ENEMY);
|
||||
GameInteractionEffectQueryResult giResult = GameInteractor::CanApplyEffect(effect->giEffect);
|
||||
|
||||
return TranslateGiEnum(giResult);
|
||||
}
|
||||
|
||||
void CrowdControl::RemoveEffect(std::string effectId) {
|
||||
if (gPlayState == NULL) {
|
||||
return;
|
||||
CrowdControl::EffectResult CrowdControl::TranslateGiEnum(GameInteractionEffectQueryResult giResult) {
|
||||
// Translate GameInteractor result into CC's own enums.
|
||||
EffectResult result;
|
||||
if (giResult == GameInteractionEffectQueryResult::Possible) {
|
||||
result = EffectResult::Success;
|
||||
} else if (giResult == GameInteractionEffectQueryResult::TemporarilyNotPossible) {
|
||||
result = EffectResult::Retry;
|
||||
} else {
|
||||
result = EffectResult::Failure;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
|
||||
if (player != NULL) {
|
||||
if (effectId == EFFECT_GIANT_LINK
|
||||
|| effectId == EFFECT_MINISH_LINK
|
||||
|| effectId == EFFECT_NO_UI
|
||||
|| effectId == EFFECT_INVISIBLE_LINK
|
||||
|| effectId == EFFECT_PAPER_LINK
|
||||
|| effectId == EFFECT_NO_Z_TARGETING
|
||||
|| effectId == EFFECT_OHKO
|
||||
|| effectId == EFFECT_PACIFIST
|
||||
|| effectId == EFFECT_RAINSTORM
|
||||
) {
|
||||
CMD_EXECUTE(fmt::format("{} 0", effectId));
|
||||
return;
|
||||
} else if (effectId == EFFECT_IRON_BOOTS || effectId == EFFECT_HOVER_BOOTS) {
|
||||
CMD_EXECUTE("boots kokiri");
|
||||
return;
|
||||
} else if (effectId == EFFECT_HIGH_GRAVITY || effectId == EFFECT_LOW_GRAVITY) {
|
||||
CMD_EXECUTE("gravity 1");
|
||||
return;
|
||||
} else if (effectId == EFFECT_REVERSE_CONTROLS) {
|
||||
CMD_EXECUTE("reverse_controls 0");
|
||||
return;
|
||||
} else if (effectId == EFFECT_INCREASE_SPEED
|
||||
|| effectId == EFFECT_DECREASE_SPEED
|
||||
) {
|
||||
CMD_EXECUTE("speed_modifier 0");
|
||||
return;
|
||||
} else if (effectId == EFFECT_DAMAGE_MULTIPLIER
|
||||
|| effectId == EFFECT_DEFENSE_MULTIPLIER
|
||||
) {
|
||||
CMD_EXECUTE("defense_modifier 0");
|
||||
return;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include <chrono>
|
||||
#include <future>
|
||||
|
||||
#include "../game-interactor/GameInteractor.h"
|
||||
|
||||
class CrowdControl {
|
||||
private:
|
||||
enum EffectResult {
|
||||
@ -61,10 +63,11 @@ class CrowdControl {
|
||||
|
||||
typedef struct Effect {
|
||||
uint32_t id;
|
||||
std::string type;
|
||||
uint32_t value;
|
||||
uint32_t value[2];
|
||||
std::string category;
|
||||
long timeRemaining;
|
||||
GameInteractionEffectBase *giEffect;
|
||||
int32_t paramMultiplier = 1;
|
||||
|
||||
// Metadata used while executing (only for timed effects)
|
||||
bool isPaused;
|
||||
@ -88,12 +91,11 @@ class CrowdControl {
|
||||
void ListenToServer();
|
||||
void ProcessActiveEffects();
|
||||
|
||||
void EmitMessage(TCPsocket socket, uint32_t eventId, long timeRemaining,
|
||||
CrowdControl::EffectResult status);
|
||||
void EmitMessage(TCPsocket socket, uint32_t eventId, long timeRemaining, EffectResult status);
|
||||
Effect* ParseMessage(char payload[512]);
|
||||
EffectResult ExecuteEffect(std::string effectId, uint32_t value, bool dryRun);
|
||||
void RemoveEffect(std::string effectId);
|
||||
bool SpawnEnemy(std::string effectId);
|
||||
EffectResult ExecuteEffect(Effect* effect);
|
||||
EffectResult CanApplyEffect(Effect *effect);
|
||||
EffectResult TranslateGiEnum(GameInteractionEffectQueryResult giResult);
|
||||
|
||||
public:
|
||||
static CrowdControl* Instance;
|
||||
|
@ -8,10 +8,10 @@
|
||||
#include <string>
|
||||
#include "soh/OTRGlobals.h"
|
||||
#include <soh/Enhancements/item-tables/ItemTableManager.h>
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
|
||||
#include "soh/Enhancements/sfx-editor/SfxEditor.h"
|
||||
|
||||
|
||||
#define Path _Path
|
||||
#define PATH_HACK
|
||||
#include <Utils/StringHelper.h>
|
||||
@ -30,24 +30,9 @@ extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
#include <libultraship/bridge.h>
|
||||
#include "overlays/actors/ovl_En_Niw/z_en_niw.h"
|
||||
|
||||
#define CMD_REGISTER SohImGui::GetConsole()->AddCommand
|
||||
|
||||
uint32_t chaosEffectNoUI;
|
||||
uint32_t chaosEffectGiantLink;
|
||||
uint32_t chaosEffectMinishLink;
|
||||
uint32_t chaosEffectPaperLink;
|
||||
uint32_t chaosEffectResetLinkScale;
|
||||
uint32_t chaosEffectInvisibleLink;
|
||||
uint32_t chaosEffectOneHitKO;
|
||||
uint32_t chaosEffectPacifistMode;
|
||||
int32_t chaosEffectDefenseModifier;
|
||||
uint32_t chaosEffectNoZ;
|
||||
uint32_t chaosEffectReverseControls;
|
||||
uint32_t chaosEffectGravityLevel = GRAVITY_LEVEL_NORMAL;
|
||||
int32_t chaosEffectSpeedModifier;
|
||||
|
||||
static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
if ((args.size() != 9) && (args.size() != 3) && (args.size() != 6)) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("Not enough arguments passed to actorspawn");
|
||||
@ -98,21 +83,28 @@ static bool ActorSpawnHandler(std::shared_ptr<Ship::Console> Console, const std:
|
||||
}
|
||||
|
||||
static bool GiveDekuShieldHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&) {
|
||||
// Give Deku Shield to the player, and automatically equip it when they're child and have no shield currently equiped.
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Item_Give(gPlayState, ITEM_SHIELD_DEKU);
|
||||
if (LINK_IS_CHILD && player->currentShield == PLAYER_SHIELD_NONE) {
|
||||
player->currentShield = PLAYER_SHIELD_DEKU;
|
||||
Inventory_ChangeEquipment(EQUIP_SHIELD, PLAYER_SHIELD_DEKU);
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::GiveDekuShield();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Gave Deku Shield.");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not give Deku Shield.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Gave Deku Shield");
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static bool KillPlayerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&) {
|
||||
gSaveContext.health = 0;
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?");
|
||||
return CMD_SUCCESS;
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::SetPlayerHealth();
|
||||
effect->parameter = 0;
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] You've met with a terrible fate, haven't you?");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not kill player.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -120,7 +112,6 @@ static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
int health;
|
||||
|
||||
try {
|
||||
@ -132,13 +123,19 @@ static bool SetPlayerHealthHandler(std::shared_ptr<Ship::Console> Console, const
|
||||
|
||||
if (health < 0) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Health value must be a positive integer");
|
||||
return CMD_SUCCESS;
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
gSaveContext.health = health * 0x10;
|
||||
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Player health updated to %d", health);
|
||||
return CMD_SUCCESS;
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::SetPlayerHealth();
|
||||
effect->parameter = health;
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Player health updated to %d", health);
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not set player health.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool LoadSceneHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>&) {
|
||||
@ -168,7 +165,7 @@ static bool RupeeHandler(std::shared_ptr<Ship::Console> Console, const std::vect
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
gSaveContext.rupees = rupeeAmount;
|
||||
gSaveContext.rupees = rupeeAmount;
|
||||
|
||||
SohImGui::GetConsole()->SendInfoMessage("Set rupee count to %u", rupeeAmount);
|
||||
return CMD_SUCCESS;
|
||||
@ -501,7 +498,7 @@ static bool StateSlotSelectHandler(std::shared_ptr<Ship::Console> Console, const
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
int slot;
|
||||
uint8_t slot;
|
||||
|
||||
try {
|
||||
slot = std::stoi(args[1], nullptr, 10);
|
||||
@ -526,19 +523,26 @@ static bool InvisibleHandler(std::shared_ptr<Ship::Console> Console, const std::
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
chaosEffectInvisibleLink = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
if (!chaosEffectInvisibleLink) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
player->actor.shape.shadowDraw = ActorShadow_DrawFeet;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Invisible value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::InvisibleLink();
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Invisible Link %s", state ? "enabled" : "disabled");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not %s Invisible Link.",
|
||||
state ? "enable" : "disable");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool GiantLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -546,21 +550,27 @@ static bool GiantLinkHandler(std::shared_ptr<Ship::Console> Console, const std::
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
chaosEffectGiantLink = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
if (chaosEffectGiantLink) {
|
||||
chaosEffectPaperLink = 0;
|
||||
chaosEffectMinishLink = 0;
|
||||
} else {
|
||||
chaosEffectResetLinkScale = 1;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Giant value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyLinkSize();
|
||||
effect->parameter = GI_LINK_SIZE_GIANT;
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Giant Link %s", state ? "enabled" : "disabled");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not %s Giant Link.",
|
||||
state ? "enable" : "disable");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool MinishLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -568,37 +578,89 @@ static bool MinishLinkHandler(std::shared_ptr<Ship::Console> Console, const std:
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
chaosEffectMinishLink = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
if (chaosEffectMinishLink) {
|
||||
chaosEffectPaperLink = 0;
|
||||
chaosEffectGiantLink = 0;
|
||||
} else {
|
||||
chaosEffectResetLinkScale = 1;
|
||||
}
|
||||
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Minish value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyLinkSize();
|
||||
effect->parameter = GI_LINK_SIZE_MINISH;
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Minish Link %s", state ? "enabled" : "disabled");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not %s Minish Link.",
|
||||
state ? "enable" : "disable");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool AddHeartContainerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
if (gSaveContext.healthCapacity >= 0x140)
|
||||
if (args.size() != 2) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
int hearts;
|
||||
|
||||
Health_GiveHearts(1);
|
||||
return CMD_SUCCESS;
|
||||
try {
|
||||
hearts = std::stoi(args[1]);
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Hearts value must be an integer.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
if (hearts < 0) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Hearts value must be a positive integer");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyHeartContainers();
|
||||
effect->parameter = hearts;
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Added %d heart containers", hearts);
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not add heart containers.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RemoveHeartContainerHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
if ((gSaveContext.healthCapacity - 0x10) < 3)
|
||||
if (args.size() != 2) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
int hearts;
|
||||
|
||||
Health_RemoveHearts(1);
|
||||
return CMD_SUCCESS;
|
||||
try {
|
||||
hearts = std::stoi(args[1]);
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Hearts value must be an integer.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
if (hearts < 0) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Hearts value must be a positive integer");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyHeartContainers();
|
||||
effect->parameter = -hearts;
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Removed %d heart containers", hearts);
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not remove heart containers.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool GravityHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -607,11 +669,21 @@ static bool GravityHandler(std::shared_ptr<Ship::Console> Console, const std::ve
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyGravity();
|
||||
|
||||
try {
|
||||
chaosEffectGravityLevel = Ship::Math::clamp(std::stoi(args[1], nullptr, 10), GRAVITY_LEVEL_LIGHT, GRAVITY_LEVEL_HEAVY);
|
||||
return CMD_SUCCESS;
|
||||
effect->parameter = Ship::Math::clamp(std::stoi(args[1], nullptr, 10), GI_GRAVITY_LEVEL_LIGHT, GI_GRAVITY_LEVEL_HEAVY);
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Minish value must be a number.");
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Gravity value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Updated gravity.");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not update gravity.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
@ -621,19 +693,40 @@ static bool NoUIHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
chaosEffectNoUI = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] No UI value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::NoUI();
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] No UI %s", state ? "enabled" : "disabled");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not %s No UI.",
|
||||
state ? "enable" : "disable");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool FreezeHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
gSaveContext.pendingIceTrapCount++;
|
||||
return CMD_SUCCESS;
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::FreezePlayer();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Player frozen");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not freeze player.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool DefenseModifierHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -641,14 +734,23 @@ static bool DefenseModifierHandler(std::shared_ptr<Ship::Console> Console, const
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyDefenseModifier();
|
||||
|
||||
try {
|
||||
chaosEffectDefenseModifier = std::stoi(args[1], nullptr, 10);
|
||||
return CMD_SUCCESS;
|
||||
effect->parameter = std::stoi(args[1], nullptr, 10);
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Defense modifier value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Defense modifier set to %d", effect->parameter);
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not set defense modifier.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool DamageHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -656,6 +758,7 @@ static bool DamageHandler(std::shared_ptr<Ship::Console> Console, const std::vec
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyHealth();
|
||||
|
||||
try {
|
||||
int value = std::stoi(args[1], nullptr, 10);
|
||||
@ -664,17 +767,20 @@ static bool DamageHandler(std::shared_ptr<Ship::Console> Console, const std::vec
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
|
||||
Health_ChangeBy(gPlayState, -value * 0x10);
|
||||
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
|
||||
player->invincibilityTimer = 28;
|
||||
|
||||
return CMD_SUCCESS;
|
||||
effect->parameter = -value;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Damage value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Player damaged");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not damage player.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool HealHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -682,6 +788,7 @@ static bool HealHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyHealth();
|
||||
|
||||
try {
|
||||
int value = std::stoi(args[1], nullptr, 10);
|
||||
@ -690,22 +797,46 @@ static bool HealHandler(std::shared_ptr<Ship::Console> Console, const std::vecto
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
Health_ChangeBy(gPlayState, value * 0x10);
|
||||
return CMD_SUCCESS;
|
||||
effect->parameter = value;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Heal value must be a number.");
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Damage value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Player healed");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not heal player.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool FillMagicHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
Magic_Fill(gPlayState);
|
||||
return CMD_SUCCESS;
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::FillMagic();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Magic filled");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not fill magic.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool EmptyMagicHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
gSaveContext.magic = 0;
|
||||
return CMD_SUCCESS;
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::EmptyMagic();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Magic emptied");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not empty magic.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool NoZHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -713,14 +844,27 @@ static bool NoZHandler(std::shared_ptr<Ship::Console> Console, const std::vector
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
chaosEffectNoZ = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] NoZ value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::DisableZTargeting();
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] NoZ " + std::string(state ? "enabled" : "disabled"));
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not " +
|
||||
std::string(state ? "enable" : "disable") + " NoZ.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool OneHitKOHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -728,14 +872,27 @@ static bool OneHitKOHandler(std::shared_ptr<Ship::Console> Console, const std::v
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
chaosEffectOneHitKO = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] One-hit KO value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::OneHitKO();
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] One-hit KO " + std::string(state ? "enabled" : "disabled"));
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not " +
|
||||
std::string(state ? "enable" : "disable") + " One-hit KO.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool PacifistHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -743,17 +900,27 @@ static bool PacifistHandler(std::shared_ptr<Ship::Console> Console, const std::v
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
chaosEffectPacifistMode = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
// Force interface to update to make the buttons transparent
|
||||
gSaveContext.unk_13E8 = 50;
|
||||
Interface_Update(gPlayState);
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Pacifist value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::PacifistMode();
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Pacifist " + std::string(state ? "enabled" : "disabled"));
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not " +
|
||||
std::string(state ? "enable" : "disable") + " Pacifist.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool PaperLinkHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -761,20 +928,28 @@ static bool PaperLinkHandler(std::shared_ptr<Ship::Console> Console, const std::
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
chaosEffectPaperLink = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
if (chaosEffectPaperLink) {
|
||||
chaosEffectMinishLink = 0;
|
||||
chaosEffectGiantLink = 0;
|
||||
} else {
|
||||
chaosEffectResetLinkScale = 1;
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Paper Link value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyLinkSize();
|
||||
effect->parameter = GI_LINK_SIZE_PAPER;
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Paper Link " + std::string(state ? "enabled" : "disabled"));
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not " +
|
||||
std::string(state ? "enable" : "disable") + " Paper Link.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool RainstormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -782,40 +957,25 @@ static bool RainstormHandler(std::shared_ptr<Ship::Console> Console, const std::
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
uint32_t rainstorm = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
if (rainstorm) {
|
||||
gPlayState->envCtx.unk_F2[0] = 20; // rain intensity target
|
||||
gPlayState->envCtx.gloomySkyMode = 1; // start gloomy sky
|
||||
if ((gWeatherMode != 0) || gPlayState->envCtx.unk_17 != 0) {
|
||||
gPlayState->envCtx.unk_DE = 1;
|
||||
}
|
||||
gPlayState->envCtx.lightningMode = LIGHTNING_MODE_ON;
|
||||
Environment_PlayStormNatureAmbience(gPlayState);
|
||||
} else {
|
||||
gPlayState->envCtx.unk_F2[0] = 0;
|
||||
if (gPlayState->csCtx.state == CS_STATE_IDLE) {
|
||||
Environment_StopStormNatureAmbience(gPlayState);
|
||||
} else if (func_800FA0B4(SEQ_PLAYER_BGM_MAIN) == NA_BGM_NATURE_AMBIENCE) {
|
||||
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_LIGHTNING, CHANNEL_IO_PORT_1, 0);
|
||||
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_RAIN, CHANNEL_IO_PORT_1, 0);
|
||||
}
|
||||
osSyncPrintf("\n\n\nE_wether_flg=[%d]", gWeatherMode);
|
||||
osSyncPrintf("\nrain_evt_trg=[%d]\n\n", gPlayState->envCtx.gloomySkyMode);
|
||||
if (gWeatherMode == 0 && (gPlayState->envCtx.gloomySkyMode == 1)) {
|
||||
gPlayState->envCtx.gloomySkyMode = 2; // end gloomy sky
|
||||
} else {
|
||||
gPlayState->envCtx.gloomySkyMode = 0;
|
||||
gPlayState->envCtx.unk_DE = 0;
|
||||
}
|
||||
gPlayState->envCtx.lightningMode = LIGHTNING_MODE_LAST;
|
||||
}
|
||||
|
||||
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] rainstorm value must be a number.");
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Rainstorm value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::WeatherRainstorm();
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Rainstorm " + std::string(state ? "enabled" : "disabled"));
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not " +
|
||||
std::string(state ? "enable" : "disable") + " Rainstorm.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
@ -825,14 +985,28 @@ static bool ReverseControlsHandler(std::shared_ptr<Ship::Console> Console, const
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
uint8_t state;
|
||||
|
||||
try {
|
||||
chaosEffectReverseControls = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
return CMD_SUCCESS;
|
||||
state = std::stoi(args[1], nullptr, 10) == 0 ? 0 : 1;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Reverse controls value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ReverseControls();
|
||||
GameInteractionEffectQueryResult result =
|
||||
state ? GameInteractor::ApplyEffect(effect) : GameInteractor::RemoveEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Reverse controls " +
|
||||
std::string(state ? "enabled" : "disabled"));
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not " +
|
||||
std::string(state ? "enable" : "disable") + " Reverse controls.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool UpdateRupeesHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -840,15 +1014,23 @@ static bool UpdateRupeesHandler(std::shared_ptr<Ship::Console> Console, const st
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyRupees();
|
||||
|
||||
try {
|
||||
int value = std::stoi(args[1], nullptr, 10);
|
||||
Rupees_ChangeBy(value);
|
||||
return CMD_SUCCESS;
|
||||
effect->parameter = std::stoi(args[1], nullptr, 10);
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Rupee value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Rupees updated");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not update rupees.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool SpeedModifierHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -856,14 +1038,23 @@ static bool SpeedModifierHandler(std::shared_ptr<Ship::Console> Console, const s
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ModifyRunSpeedModifier();
|
||||
|
||||
try {
|
||||
chaosEffectSpeedModifier = std::stoi(args[1], nullptr, 10);
|
||||
return CMD_SUCCESS;
|
||||
effect->parameter = std::stoi(args[1], nullptr, 10);
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Speed modifier value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Speed modifier updated");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not update speed modifier.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
const static std::map<std::string, uint16_t> boots {
|
||||
@ -884,12 +1075,17 @@ static bool BootsHandler(std::shared_ptr<Ship::Console> Console, const std::vect
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
player->currentBoots = it->second;
|
||||
Inventory_ChangeEquipment(EQUIP_BOOTS, it->second + 1);
|
||||
Player_SetBootData(gPlayState, player);
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ForceEquipBoots();
|
||||
effect->parameter = it->second;
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Boots updated");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not update boots.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool KnockbackHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
@ -897,6 +1093,7 @@ static bool KnockbackHandler(std::shared_ptr<Ship::Console> Console, const std::
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Unexpected arguments passed");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::KnockbackPlayer();
|
||||
|
||||
try {
|
||||
int value = std::stoi(args[1], nullptr, 10);
|
||||
@ -905,45 +1102,59 @@ static bool KnockbackHandler(std::shared_ptr<Ship::Console> Console, const std::
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
func_8002F71C(gPlayState, &player->actor, value * 5, player->actor.world.rot.y + 0x8000, value * 5);
|
||||
|
||||
return CMD_SUCCESS;
|
||||
effect->parameter = value;
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
SohImGui::GetConsole()->SendErrorMessage("[SOH] Knockback value must be a number.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Knockback applied");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not apply knockback.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ElectrocuteHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
if (PlayerGrounded(player)) {
|
||||
func_80837C0C(gPlayState, player, 4, 0, 0, 0, 0);
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::ElectrocutePlayer();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
return CMD_FAILED;
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Electrocuted player");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not electrocute player.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool BurnHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
if (PlayerGrounded(player)) {
|
||||
for (int i = 0; i < 18; i++) {
|
||||
player->flameTimers[i] = Rand_S16Offset(0, 200);
|
||||
}
|
||||
player->isBurning = true;
|
||||
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::BurnPlayer();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Burned player");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not burn player.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
return CMD_SUCCESS;
|
||||
}
|
||||
|
||||
static bool CuccoStormHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
EnNiw* cucco = (EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_NIW, player->actor.world.pos.x,
|
||||
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, 0, 0);
|
||||
cucco->actionFunc = func_80AB70A0_nocutscene;
|
||||
return CMD_SUCCESS;
|
||||
GameInteractionEffectBase* effect = new GameInteractionEffect::SpawnCuccoStorm();
|
||||
GameInteractionEffectQueryResult result = GameInteractor::ApplyEffect(effect);
|
||||
|
||||
if (result == GameInteractionEffectQueryResult::Possible) {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Spawned cucco storm");
|
||||
return CMD_SUCCESS;
|
||||
} else {
|
||||
SohImGui::GetConsole()->SendInfoMessage("[SOH] Command failed: Could not spawn cucco storm.");
|
||||
return CMD_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CosmeticsHandler(std::shared_ptr<Ship::Console> Console, const std::vector<std::string>& args) {
|
||||
|
@ -2,30 +2,4 @@
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#define GRAVITY_LEVEL_NORMAL 1.0f
|
||||
#define GRAVITY_LEVEL_LIGHT 0.0f
|
||||
#define GRAVITY_LEVEL_HEAVY 2.0f
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// bools are exported as uint32_t for compatibility with C code
|
||||
extern uint32_t chaosEffectNoUI;
|
||||
extern uint32_t chaosEffectGiantLink;
|
||||
extern uint32_t chaosEffectMinishLink;
|
||||
extern uint32_t chaosEffectPaperLink;
|
||||
extern uint32_t chaosEffectResetLinkScale;
|
||||
extern uint32_t chaosEffectInvisibleLink;
|
||||
extern uint32_t chaosEffectOneHitKO;
|
||||
extern uint32_t chaosEffectPacifistMode;
|
||||
extern int32_t chaosEffectDefenseModifier;
|
||||
extern uint32_t chaosEffectNoZ;
|
||||
extern uint32_t chaosEffectReverseControls;
|
||||
|
||||
extern uint32_t chaosEffectGravityLevel;
|
||||
extern int32_t chaosEffectSpeedModifier;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
void DebugConsole_Init(void);
|
||||
|
399
soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp
Normal file
399
soh/soh/Enhancements/game-interactor/GameInteractionEffect.cpp
Normal file
@ -0,0 +1,399 @@
|
||||
/*
|
||||
GameInteractionEffects is used in conjunction with GameInteractor.
|
||||
|
||||
It's intended to be used in places that want to interact with the game
|
||||
while having checks built-in for if said effect is able to be executed.
|
||||
|
||||
Effects that can last for a certain amount of time (timed effects)
|
||||
have functions to both enable and disable said effect.
|
||||
*/
|
||||
|
||||
#include "GameInteractionEffect.h"
|
||||
#include "GameInteractor.h"
|
||||
#include <libultraship/bridge.h>
|
||||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
#include "variables.h"
|
||||
#include "functions.h"
|
||||
#include "macros.h"
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult GameInteractionEffectBase::Apply() {
|
||||
GameInteractionEffectQueryResult result = CanBeApplied();
|
||||
if (result != GameInteractionEffectQueryResult::Possible) {
|
||||
return result;
|
||||
}
|
||||
|
||||
_Apply();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// For most effects, CanBeRemoved is the same as CanBeApplied. When its not: please override `CanBeRemoved`.
|
||||
GameInteractionEffectQueryResult GameInteractionEffectBase::CanBeRemoved() {
|
||||
return CanBeApplied();
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult GameInteractionEffectBase::Remove() {
|
||||
GameInteractionEffectQueryResult result = CanBeRemoved();
|
||||
if (result != GameInteractionEffectQueryResult::Possible) {
|
||||
return result;
|
||||
}
|
||||
|
||||
_Remove();
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace GameInteractionEffect {
|
||||
|
||||
// MARK: - ModifyHeartContainers
|
||||
GameInteractionEffectQueryResult ModifyHeartContainers::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else if (
|
||||
(parameter > 0 && (gSaveContext.healthCapacity + (parameter * 0x10) > 0x140)) ||
|
||||
(parameter < 0 && (gSaveContext.healthCapacity + (parameter * 0x10) < 0x10))
|
||||
) {
|
||||
return GameInteractionEffectQueryResult::NotPossible;
|
||||
}
|
||||
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
|
||||
void ModifyHeartContainers::_Apply() {
|
||||
GameInteractor::RawAction::AddOrRemoveHealthContainers(parameter);
|
||||
}
|
||||
|
||||
// MARK: - FillMagic
|
||||
GameInteractionEffectQueryResult FillMagic::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else if (!gSaveContext.isMagicAcquired || gSaveContext.magic >= ((gSaveContext.isDoubleMagicAcquired + 1) * 48)) {
|
||||
return GameInteractionEffectQueryResult::NotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void FillMagic::_Apply() {
|
||||
GameInteractor::RawAction::AddOrRemoveMagic(96);
|
||||
}
|
||||
|
||||
// MARK: - EmptyMagic
|
||||
GameInteractionEffectQueryResult EmptyMagic::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else if (!gSaveContext.isMagicAcquired || gSaveContext.magic <= 0) {
|
||||
return GameInteractionEffectQueryResult::NotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void EmptyMagic::_Apply() {
|
||||
GameInteractor::RawAction::AddOrRemoveMagic(-96);
|
||||
}
|
||||
|
||||
// MARK: - ModifyRupees
|
||||
GameInteractionEffectQueryResult ModifyRupees::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else if (
|
||||
(parameter < 0 && gSaveContext.rupees <= 0) ||
|
||||
(parameter > 0 && gSaveContext.rupees >= CUR_CAPACITY(UPG_WALLET))
|
||||
) {
|
||||
return GameInteractionEffectQueryResult::NotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void ModifyRupees::_Apply() {
|
||||
Rupees_ChangeBy(parameter);
|
||||
}
|
||||
|
||||
// MARK: - NoUI
|
||||
GameInteractionEffectQueryResult NoUI::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void NoUI::_Apply() {
|
||||
GameInteractor::State::NoUIActive = 1;
|
||||
}
|
||||
void NoUI::_Remove() {
|
||||
GameInteractor::State::NoUIActive = 0;
|
||||
}
|
||||
|
||||
// MARK: - ModifyGravity
|
||||
GameInteractionEffectQueryResult ModifyGravity::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void ModifyGravity::_Apply() {
|
||||
GameInteractor::State::GravityLevel = (GIGravityLevel)parameter;
|
||||
}
|
||||
void ModifyGravity::_Remove() {
|
||||
GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL;
|
||||
}
|
||||
|
||||
// MARK: - ModifyHealth
|
||||
GameInteractionEffectQueryResult ModifyHealth::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else if (
|
||||
(parameter > 0 && gSaveContext.health == gSaveContext.healthCapacity)
|
||||
|| (parameter < 0 && (gSaveContext.health + (16 * parameter) <= 0))
|
||||
) {
|
||||
return GameInteractionEffectQueryResult::NotPossible;
|
||||
}
|
||||
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
void ModifyHealth::_Apply() {
|
||||
GameInteractor::RawAction::HealOrDamagePlayer(parameter);
|
||||
}
|
||||
|
||||
// MARK: - SetPlayerHealth
|
||||
GameInteractionEffectQueryResult SetPlayerHealth::CanBeApplied() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void SetPlayerHealth::_Apply() {
|
||||
GameInteractor::RawAction::SetPlayerHealth(parameter);
|
||||
}
|
||||
|
||||
// MARK: - FreezePlayer
|
||||
GameInteractionEffectQueryResult FreezePlayer::CanBeApplied() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void FreezePlayer::_Apply() {
|
||||
GameInteractor::RawAction::FreezePlayer();
|
||||
}
|
||||
|
||||
// MARK: - BurnPlayer
|
||||
GameInteractionEffectQueryResult BurnPlayer::CanBeApplied() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void BurnPlayer::_Apply() {
|
||||
GameInteractor::RawAction::BurnPlayer();
|
||||
}
|
||||
|
||||
// MARK: - ElectrocutePlayer
|
||||
GameInteractionEffectQueryResult ElectrocutePlayer::CanBeApplied() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused() || !PlayerGrounded(player)) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void ElectrocutePlayer::_Apply() {
|
||||
GameInteractor::RawAction::ElectrocutePlayer();
|
||||
}
|
||||
|
||||
// MARK: - KnockbackPlayer
|
||||
GameInteractionEffectQueryResult KnockbackPlayer::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void KnockbackPlayer::_Apply() {
|
||||
GameInteractor::RawAction::KnockbackPlayer(parameter);
|
||||
}
|
||||
|
||||
// MARK: - ModifyLinkSize
|
||||
GameInteractionEffectQueryResult ModifyLinkSize::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void ModifyLinkSize::_Apply() {
|
||||
GameInteractor::State::LinkSize = (GILinkSize)parameter;
|
||||
}
|
||||
void ModifyLinkSize::_Remove() {
|
||||
GameInteractor::State::LinkSize = GI_LINK_SIZE_NORMAL;
|
||||
}
|
||||
|
||||
// MARK: - InvisibleLink
|
||||
GameInteractionEffectQueryResult InvisibleLink::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void InvisibleLink::_Apply() {
|
||||
GameInteractor::RawAction::SetLinkInvisibility(true);
|
||||
}
|
||||
void InvisibleLink::_Remove() {
|
||||
GameInteractor::RawAction::SetLinkInvisibility(false);
|
||||
}
|
||||
|
||||
// MARK: - PacifistMode
|
||||
GameInteractionEffectQueryResult PacifistMode::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void PacifistMode::_Apply() {
|
||||
GameInteractor::State::SetPacifistMode(true);
|
||||
}
|
||||
void PacifistMode::_Remove() {
|
||||
GameInteractor::State::SetPacifistMode(false);
|
||||
}
|
||||
|
||||
// MARK: - DisableZTargeting
|
||||
GameInteractionEffectQueryResult DisableZTargeting::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void DisableZTargeting::_Apply() {
|
||||
GameInteractor::State::DisableZTargetingActive = 1;
|
||||
}
|
||||
void DisableZTargeting::_Remove() {
|
||||
GameInteractor::State::DisableZTargetingActive = 0;
|
||||
}
|
||||
|
||||
// MARK: - WeatherRainstorm
|
||||
GameInteractionEffectQueryResult WeatherRainstorm::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void WeatherRainstorm::_Apply() {
|
||||
GameInteractor::RawAction::SetWeatherStorm(true);
|
||||
}
|
||||
void WeatherRainstorm::_Remove() {
|
||||
GameInteractor::RawAction::SetWeatherStorm(false);
|
||||
}
|
||||
|
||||
// MARK: - ReverseControls
|
||||
GameInteractionEffectQueryResult ReverseControls::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void ReverseControls::_Apply() {
|
||||
GameInteractor::State::ReverseControlsActive = 1;
|
||||
}
|
||||
void ReverseControls::_Remove() {
|
||||
GameInteractor::State::ReverseControlsActive = 0;
|
||||
}
|
||||
|
||||
// MARK: - ForceEquipBoots
|
||||
GameInteractionEffectQueryResult ForceEquipBoots::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void ForceEquipBoots::_Apply() {
|
||||
GameInteractor::RawAction::ForceEquipBoots(parameter);
|
||||
}
|
||||
void ForceEquipBoots::_Remove() {
|
||||
GameInteractor::RawAction::ForceEquipBoots(PLAYER_BOOTS_KOKIRI);
|
||||
}
|
||||
|
||||
// MARK: - ModifyRunSpeedModifier
|
||||
GameInteractionEffectQueryResult ModifyRunSpeedModifier::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void ModifyRunSpeedModifier::_Apply() {
|
||||
GameInteractor::State::RunSpeedModifier = parameter;
|
||||
}
|
||||
void ModifyRunSpeedModifier::_Remove() {
|
||||
GameInteractor::State::RunSpeedModifier = 0;
|
||||
}
|
||||
|
||||
// MARK: - OneHitKO
|
||||
GameInteractionEffectQueryResult OneHitKO::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void OneHitKO::_Apply() {
|
||||
GameInteractor::State::OneHitKOActive = 1;
|
||||
}
|
||||
void OneHitKO::_Remove() {
|
||||
GameInteractor::State::OneHitKOActive = 0;
|
||||
}
|
||||
|
||||
// MARK: - IncreaseDamageTaken
|
||||
GameInteractionEffectQueryResult ModifyDefenseModifier::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void ModifyDefenseModifier::_Apply() {
|
||||
GameInteractor::State::DefenseModifier = parameter;
|
||||
}
|
||||
void ModifyDefenseModifier::_Remove() {
|
||||
GameInteractor::State::DefenseModifier = 0;
|
||||
}
|
||||
|
||||
// MARK: - GiveDekuShield
|
||||
GameInteractionEffectQueryResult GiveDekuShield::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else if ((Item_CheckObtainability(ITEM_SHIELD_DEKU) != ITEM_NONE)) {
|
||||
return GameInteractionEffectQueryResult::NotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void GiveDekuShield::_Apply() {
|
||||
GameInteractor::RawAction::GiveDekuShield();
|
||||
}
|
||||
|
||||
// MARK: - SpawnCuccoStorm
|
||||
GameInteractionEffectQueryResult SpawnCuccoStorm::CanBeApplied() {
|
||||
if (!GameInteractor::IsSaveLoaded() || GameInteractor::IsGameplayPaused()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
} else {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
}
|
||||
void SpawnCuccoStorm::_Apply() {
|
||||
GameInteractor::RawAction::SpawnCuccoStorm();
|
||||
}
|
||||
}
|
162
soh/soh/Enhancements/game-interactor/GameInteractionEffect.h
Normal file
162
soh/soh/Enhancements/game-interactor/GameInteractionEffect.h
Normal file
@ -0,0 +1,162 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef GameInteractionEffect_h
|
||||
#define GameInteractionEffect_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
enum GameInteractionEffectQueryResult {
|
||||
Possible = 0x00,
|
||||
TemporarilyNotPossible = 0x01,
|
||||
NotPossible = 0xFF
|
||||
};
|
||||
|
||||
class GameInteractionEffectBase {
|
||||
public:
|
||||
virtual GameInteractionEffectQueryResult CanBeApplied() = 0;
|
||||
virtual GameInteractionEffectQueryResult CanBeRemoved();
|
||||
GameInteractionEffectQueryResult Apply();
|
||||
GameInteractionEffectQueryResult Remove();
|
||||
int32_t parameter;
|
||||
protected:
|
||||
virtual void _Apply() = 0;
|
||||
virtual void _Remove() {};
|
||||
};
|
||||
|
||||
namespace GameInteractionEffect {
|
||||
class ModifyHeartContainers: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class FillMagic: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class EmptyMagic: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class ModifyRupees: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class NoUI: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class ModifyGravity: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class ModifyHealth: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class SetPlayerHealth: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class FreezePlayer: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class BurnPlayer: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class ElectrocutePlayer: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class KnockbackPlayer: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class ModifyLinkSize: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class InvisibleLink : public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class PacifistMode : public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class DisableZTargeting: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class WeatherRainstorm: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class ReverseControls: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class ForceEquipBoots: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class ModifyRunSpeedModifier: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class OneHitKO : public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class ModifyDefenseModifier: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
void _Remove() override;
|
||||
};
|
||||
|
||||
class GiveDekuShield: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
|
||||
class SpawnCuccoStorm: public GameInteractionEffectBase {
|
||||
GameInteractionEffectQueryResult CanBeApplied() override;
|
||||
void _Apply() override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif /* __cplusplus */
|
||||
#endif /* GameInteractionEffect_h */
|
55
soh/soh/Enhancements/game-interactor/GameInteractor.cpp
Normal file
55
soh/soh/Enhancements/game-interactor/GameInteractor.cpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
GameInteractor is meant to be used for interacting with the game (yup...).
|
||||
It exposes functions that directly modify, add or remove game related elements.
|
||||
|
||||
GameInteractionEffects.cpp is used when code that needs these
|
||||
functions also need a check wether a command can be run or not.
|
||||
|
||||
If these checks need to happen wherever GameInteractor functions are needed, the
|
||||
GameInteractor functions can be called directly.
|
||||
*/
|
||||
|
||||
#include "GameInteractor.h"
|
||||
#include <libultraship/bridge.h>
|
||||
|
||||
extern "C" {
|
||||
#include "variables.h"
|
||||
#include "macros.h"
|
||||
#include "functions.h"
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
#include "overlays/actors/ovl_En_Niw/z_en_niw.h"
|
||||
|
||||
// MARK: - Effects
|
||||
|
||||
GameInteractionEffectQueryResult GameInteractor::CanApplyEffect(GameInteractionEffectBase* effect) {
|
||||
return effect->CanBeApplied();
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult GameInteractor::ApplyEffect(GameInteractionEffectBase* effect) {
|
||||
return effect->Apply();
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult GameInteractor::RemoveEffect(GameInteractionEffectBase* effect) {
|
||||
return effect->Remove();
|
||||
}
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
bool GameInteractor::IsSaveLoaded() {
|
||||
Player* player;
|
||||
if (gPlayState != NULL) {
|
||||
player = GET_PLAYER(gPlayState);
|
||||
}
|
||||
return (gPlayState == NULL || player == NULL || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2) ? false : true;
|
||||
}
|
||||
|
||||
bool GameInteractor::IsGameplayPaused() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
return (Player_InBlockingCsMode(gPlayState, player) || gPlayState->pauseCtx.state != 0 || gPlayState->msgCtx.msgMode != 0) ? true : false;
|
||||
}
|
||||
|
||||
bool GameInteractor::CanSpawnEnemy() {
|
||||
return GameInteractor::IsSaveLoaded() && !GameInteractor::IsGameplayPaused();
|
||||
}
|
94
soh/soh/Enhancements/game-interactor/GameInteractor.h
Normal file
94
soh/soh/Enhancements/game-interactor/GameInteractor.h
Normal file
@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef GameInteractor_h
|
||||
#define GameInteractor_h
|
||||
|
||||
#include "GameInteractionEffect.h"
|
||||
|
||||
typedef enum {
|
||||
/* 0x00 */ GI_LINK_SIZE_NORMAL,
|
||||
/* 0x01 */ GI_LINK_SIZE_GIANT,
|
||||
/* 0x02 */ GI_LINK_SIZE_MINISH,
|
||||
/* 0x03 */ GI_LINK_SIZE_PAPER,
|
||||
} GILinkSize;
|
||||
|
||||
typedef enum {
|
||||
/* 0x00 */ GI_GRAVITY_LEVEL_LIGHT,
|
||||
/* 0x01 */ GI_GRAVITY_LEVEL_NORMAL,
|
||||
/* 0x02 */ GI_GRAVITY_LEVEL_HEAVY,
|
||||
} GIGravityLevel;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
uint8_t GameInteractor_NoUIActive();
|
||||
GILinkSize GameInteractor_LinkSize();
|
||||
uint8_t GameInteractor_InvisibleLinkActive();
|
||||
uint8_t GameInteractor_ResetLinkScale();
|
||||
uint8_t GameInteractor_OneHitKOActive();
|
||||
uint8_t GameInteractor_PacifistModeActive();
|
||||
uint8_t GameInteractor_DisableZTargetingActive();
|
||||
uint8_t GameInteractor_ReverseControlsActive();
|
||||
int32_t GameInteractor_DefenseModifier();
|
||||
int32_t GameInteractor_RunSpeedModifier();
|
||||
GIGravityLevel GameInteractor_GravityLevel();
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
class GameInteractor {
|
||||
public:
|
||||
static GameInteractor* Instance;
|
||||
|
||||
// Gsme State
|
||||
class State {
|
||||
public:
|
||||
static bool NoUIActive;
|
||||
static GILinkSize LinkSize;
|
||||
static bool InvisibleLinkActive;
|
||||
static bool OneHitKOActive;
|
||||
static bool PacifistModeActive;
|
||||
static bool DisableZTargetingActive;
|
||||
static bool ReverseControlsActive;
|
||||
static int32_t DefenseModifier;
|
||||
static int32_t RunSpeedModifier;
|
||||
static GIGravityLevel GravityLevel;
|
||||
|
||||
static void SetPacifistMode(bool active);
|
||||
};
|
||||
|
||||
// Effects
|
||||
static GameInteractionEffectQueryResult CanApplyEffect(GameInteractionEffectBase* effect);
|
||||
static GameInteractionEffectQueryResult ApplyEffect(GameInteractionEffectBase* effect);
|
||||
static GameInteractionEffectQueryResult RemoveEffect(GameInteractionEffectBase* effect);
|
||||
|
||||
// Helpers
|
||||
static bool IsSaveLoaded();
|
||||
static bool IsGameplayPaused();
|
||||
static bool CanSpawnEnemy();
|
||||
|
||||
class RawAction {
|
||||
public:
|
||||
static void AddOrRemoveHealthContainers(int16_t amount);
|
||||
static void AddOrRemoveMagic(int8_t amount);
|
||||
static void HealOrDamagePlayer(int16_t hearts);
|
||||
static void SetPlayerHealth(int16_t hearts);
|
||||
static void SetLinkInvisibility(bool active);
|
||||
static void SetWeatherStorm(bool active);
|
||||
static void ForceEquipBoots(int8_t boots);
|
||||
static void FreezePlayer();
|
||||
static void BurnPlayer();
|
||||
static void ElectrocutePlayer();
|
||||
static void KnockbackPlayer(float strength);
|
||||
static void GiveDekuShield();
|
||||
static void SpawnCuccoStorm();
|
||||
static void ForceInterfaceUpdate();
|
||||
|
||||
static GameInteractionEffectQueryResult SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams);
|
||||
};
|
||||
};
|
||||
|
||||
#endif /* __cplusplus */
|
||||
#endif /* GameInteractor_h */
|
@ -0,0 +1,199 @@
|
||||
#include "GameInteractor.h"
|
||||
#include <libultraship/bridge.h>
|
||||
|
||||
extern "C" {
|
||||
#include "variables.h"
|
||||
#include "macros.h"
|
||||
#include "functions.h"
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
#include "overlays/actors/ovl_En_Niw/z_en_niw.h"
|
||||
|
||||
void GameInteractor::RawAction::AddOrRemoveHealthContainers(int16_t amount) {
|
||||
gSaveContext.healthCapacity += amount * 0x10;
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::AddOrRemoveMagic(int8_t amount) {
|
||||
// Full single magic = 48
|
||||
// Full double magic = 96
|
||||
int8_t currentMagicCapacity = (gSaveContext.isDoubleMagicAcquired + 1) * 48;
|
||||
|
||||
if (gSaveContext.isMagicAcquired) {
|
||||
gSaveContext.prevMagicState = gSaveContext.magicState;
|
||||
if (amount > 0) {
|
||||
if (gSaveContext.magic + amount > currentMagicCapacity) {
|
||||
gSaveContext.magicFillTarget = currentMagicCapacity;
|
||||
} else {
|
||||
gSaveContext.magicFillTarget = gSaveContext.magic + amount;
|
||||
}
|
||||
gSaveContext.magicState = MAGIC_STATE_FILL;
|
||||
} else if (amount < 0) {
|
||||
if (gSaveContext.magic + amount < 0) {
|
||||
gSaveContext.magic = 0;
|
||||
} else {
|
||||
gSaveContext.magic += amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::HealOrDamagePlayer(int16_t hearts) {
|
||||
if (hearts > 0) {
|
||||
Health_ChangeBy(gPlayState, hearts * 0x10);
|
||||
} else if (hearts < 0) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Health_ChangeBy(gPlayState, hearts * 0x10);
|
||||
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
|
||||
player->invincibilityTimer = 28;
|
||||
}
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::SetPlayerHealth(int16_t hearts) {
|
||||
gSaveContext.health = hearts * 0x10;
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::SetLinkInvisibility(bool active) {
|
||||
GameInteractor::State::InvisibleLinkActive = active;
|
||||
if (!active) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
player->actor.shape.shadowDraw = ActorShadow_DrawFeet;
|
||||
}
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::SetWeatherStorm(bool active) {
|
||||
if (active) {
|
||||
gPlayState->envCtx.unk_F2[0] = 20; // rain intensity target
|
||||
gPlayState->envCtx.gloomySkyMode = 1; // start gloomy sky
|
||||
if ((gWeatherMode != 0) || gPlayState->envCtx.unk_17 != 0) {
|
||||
gPlayState->envCtx.unk_DE = 1;
|
||||
}
|
||||
gPlayState->envCtx.lightningMode = LIGHTNING_MODE_ON;
|
||||
Environment_PlayStormNatureAmbience(gPlayState);
|
||||
} else {
|
||||
gPlayState->envCtx.unk_F2[0] = 0;
|
||||
if (gPlayState->csCtx.state == CS_STATE_IDLE) {
|
||||
Environment_StopStormNatureAmbience(gPlayState);
|
||||
} else if (func_800FA0B4(SEQ_PLAYER_BGM_MAIN) == NA_BGM_NATURE_AMBIENCE) {
|
||||
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_LIGHTNING, CHANNEL_IO_PORT_1, 0);
|
||||
Audio_SetNatureAmbienceChannelIO(NATURE_CHANNEL_RAIN, CHANNEL_IO_PORT_1, 0);
|
||||
}
|
||||
osSyncPrintf("\n\n\nE_wether_flg=[%d]", gWeatherMode);
|
||||
osSyncPrintf("\nrain_evt_trg=[%d]\n\n", gPlayState->envCtx.gloomySkyMode);
|
||||
if (gWeatherMode == 0 && (gPlayState->envCtx.gloomySkyMode == 1)) {
|
||||
gPlayState->envCtx.gloomySkyMode = 2; // end gloomy sky
|
||||
} else {
|
||||
gPlayState->envCtx.gloomySkyMode = 0;
|
||||
gPlayState->envCtx.unk_DE = 0;
|
||||
}
|
||||
gPlayState->envCtx.lightningMode = LIGHTNING_MODE_LAST;
|
||||
}
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::ForceEquipBoots(int8_t boots) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
player->currentBoots = boots;
|
||||
Inventory_ChangeEquipment(EQUIP_BOOTS, boots + 1);
|
||||
Player_SetBootData(gPlayState, player);
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::FreezePlayer() {
|
||||
gSaveContext.pendingIceTrapCount++;
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::BurnPlayer() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
for (int i = 0; i < 18; i++) {
|
||||
player->flameTimers[i] = Rand_S16Offset(0, 200);
|
||||
}
|
||||
player->isBurning = true;
|
||||
func_80837C0C(gPlayState, player, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::ElectrocutePlayer() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
func_80837C0C(gPlayState, player, 4, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::KnockbackPlayer(float strength) {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
func_8002F71C(gPlayState, &player->actor, strength * 5, player->actor.world.rot.y + 0x8000, strength * 5);
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::GiveDekuShield() {
|
||||
// Give Deku Shield to the player, and automatically equip it when they're child and have no shield currently equiped.
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
Item_Give(gPlayState, ITEM_SHIELD_DEKU);
|
||||
if (LINK_IS_CHILD && player->currentShield == PLAYER_SHIELD_NONE) {
|
||||
player->currentShield = PLAYER_SHIELD_DEKU;
|
||||
Inventory_ChangeEquipment(EQUIP_SHIELD, PLAYER_SHIELD_DEKU);
|
||||
}
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::SpawnCuccoStorm() {
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
EnNiw* cucco = (EnNiw*)Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_NIW, player->actor.world.pos.x,
|
||||
player->actor.world.pos.y + 2200, player->actor.world.pos.z, 0, 0, 0, 0, 0);
|
||||
cucco->actionFunc = func_80AB70A0_nocutscene;
|
||||
}
|
||||
|
||||
void GameInteractor::RawAction::ForceInterfaceUpdate() {
|
||||
gSaveContext.unk_13E8 = 50;
|
||||
Interface_Update(gPlayState);
|
||||
}
|
||||
|
||||
GameInteractionEffectQueryResult GameInteractor::RawAction::SpawnEnemyWithOffset(uint32_t enemyId, int32_t enemyParams) {
|
||||
|
||||
if (!GameInteractor::CanSpawnEnemy()) {
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
}
|
||||
|
||||
Player* player = GET_PLAYER(gPlayState);
|
||||
|
||||
float posXOffset = 0;
|
||||
float posYOffset = 0;
|
||||
float posZOffset = 0;
|
||||
|
||||
if (enemyId == ACTOR_EN_WALLMAS) {
|
||||
|
||||
} else if (enemyId == ACTOR_EN_CLEAR_TAG) {
|
||||
// Don't allow Arwings in certain areas because they cause issues.
|
||||
// Locations: King dodongo room, Morpha room, Twinrova room, Ganondorf room, Fishing pond, Ganon's room
|
||||
// TODO: Swap this to disabling the option in CC options menu instead.
|
||||
if (gPlayState->sceneNum == SCENE_DDAN_BOSS || gPlayState->sceneNum == SCENE_MIZUSIN_BS ||
|
||||
gPlayState->sceneNum == SCENE_JYASINBOSS || gPlayState->sceneNum == SCENE_GANON_BOSS ||
|
||||
gPlayState->sceneNum == SCENE_TURIBORI || gPlayState->sceneNum == SCENE_GANON_DEMO) {
|
||||
return GameInteractionEffectQueryResult::NotPossible;
|
||||
}
|
||||
posYOffset = 100;
|
||||
} else if (enemyId == ACTOR_EN_TORCH2) {
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (enemyId == ACTOR_EN_TEST) {
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (enemyId == ACTOR_EN_WF) {
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (enemyId == ACTOR_EN_FZ) {
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (enemyId == ACTOR_EN_FIREFLY) {
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (enemyId == ACTOR_EN_TITE) {
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
} else if (enemyId == ACTOR_EN_RR) {
|
||||
posXOffset = 75;
|
||||
posYOffset = 50;
|
||||
}
|
||||
|
||||
if (Actor_Spawn(&gPlayState->actorCtx, gPlayState, enemyId, player->actor.world.pos.x + posXOffset,
|
||||
player->actor.world.pos.y + posYOffset, player->actor.world.pos.z + posZOffset, 0, 0, 0,
|
||||
enemyParams, 0) != NULL) {
|
||||
return GameInteractionEffectQueryResult::Possible;
|
||||
}
|
||||
|
||||
return GameInteractionEffectQueryResult::TemporarilyNotPossible;
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
#include "GameInteractor.h"
|
||||
|
||||
// MARK: - State Definitions
|
||||
|
||||
bool GameInteractor::State::NoUIActive = 0;
|
||||
GILinkSize GameInteractor::State::LinkSize = GI_LINK_SIZE_NORMAL;
|
||||
bool GameInteractor::State::InvisibleLinkActive = 0;
|
||||
bool GameInteractor::State::OneHitKOActive = 0;
|
||||
bool GameInteractor::State::PacifistModeActive = 0;
|
||||
bool GameInteractor::State::DisableZTargetingActive = 0;
|
||||
bool GameInteractor::State::ReverseControlsActive = 0;
|
||||
int32_t GameInteractor::State::DefenseModifier = 0;
|
||||
int32_t GameInteractor::State::RunSpeedModifier = 0;
|
||||
GIGravityLevel GameInteractor::State::GravityLevel = GI_GRAVITY_LEVEL_NORMAL;
|
||||
|
||||
void GameInteractor::State::SetPacifistMode(bool active) {
|
||||
PacifistModeActive = active;
|
||||
// Force interface update to update the button's transparency.
|
||||
GameInteractor::RawAction::ForceInterfaceUpdate();
|
||||
}
|
||||
|
||||
// MARK: C - Bridge
|
||||
|
||||
// MARK: - GameInteractor::State::NoUIActive
|
||||
uint8_t GameInteractor_NoUIActive() {
|
||||
return GameInteractor::State::NoUIActive;
|
||||
}
|
||||
|
||||
// MARK: - GameInteractor::State::LinkSize
|
||||
GILinkSize GameInteractor_LinkSize() {
|
||||
return GameInteractor::State::LinkSize;
|
||||
}
|
||||
|
||||
// MARK: - GameInteractor::State::InvisibleLinkActive
|
||||
uint8_t GameInteractor_InvisibleLinkActive() {
|
||||
return GameInteractor::State::InvisibleLinkActive;
|
||||
}
|
||||
|
||||
void GameInteractor_SetInvisibleLinkActive(uint8_t active) {
|
||||
GameInteractor::State::InvisibleLinkActive = active;
|
||||
}
|
||||
|
||||
// MARK: - GameInteractor::State::OneHitKOActive
|
||||
uint8_t GameInteractor_OneHitKOActive() {
|
||||
return GameInteractor::State::OneHitKOActive;
|
||||
}
|
||||
|
||||
// MARK: - GameInteractor::State::PacifistModeActive
|
||||
uint8_t GameInteractor_PacifistModeActive() {
|
||||
return GameInteractor::State::PacifistModeActive;
|
||||
}
|
||||
|
||||
// MARK: - GameInteractor::State::DisableZTargetingActive
|
||||
uint8_t GameInteractor_DisableZTargetingActive() {
|
||||
return GameInteractor::State::DisableZTargetingActive;
|
||||
}
|
||||
|
||||
// MARK: - GameInteractor::State::DisableCameraRotationActive
|
||||
uint8_t GameInteractor_ReverseControlsActive() {
|
||||
return GameInteractor::State::ReverseControlsActive;
|
||||
}
|
||||
|
||||
// MARK: - GameInteractor::State::DisableCameraRotationActive
|
||||
int32_t GameInteractor_DefenseModifier() {
|
||||
return GameInteractor::State::DefenseModifier;
|
||||
}
|
||||
|
||||
// MARK: - GameInteractor::State::DisableCameraRotationActive
|
||||
int32_t GameInteractor_RunSpeedModifier() {
|
||||
return GameInteractor::State::RunSpeedModifier;
|
||||
}
|
||||
|
||||
// MARK: - GameInteractor::State::DisableCameraRotationActive
|
||||
GIGravityLevel GameInteractor_GravityLevel() {
|
||||
return GameInteractor::State::GravityLevel;
|
||||
}
|
@ -71,6 +71,7 @@
|
||||
CrowdControl* CrowdControl::Instance;
|
||||
#endif
|
||||
|
||||
#include "Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "libultraship/libultraship.h"
|
||||
|
||||
// Resource Types/Factories
|
||||
@ -104,6 +105,7 @@ OTRGlobals* OTRGlobals::Instance;
|
||||
SaveManager* SaveManager::Instance;
|
||||
CustomMessageManager* CustomMessageManager::Instance;
|
||||
ItemTableManager* ItemTableManager::Instance;
|
||||
GameInteractor* GameInteractor::Instance;
|
||||
|
||||
OTRGlobals::OTRGlobals() {
|
||||
std::vector<std::string> OTRFiles;
|
||||
@ -471,6 +473,7 @@ extern "C" void InitOTR() {
|
||||
SaveManager::Instance = new SaveManager();
|
||||
CustomMessageManager::Instance = new CustomMessageManager();
|
||||
ItemTableManager::Instance = new ItemTableManager();
|
||||
GameInteractor::Instance = new GameInteractor();
|
||||
|
||||
clearMtx = (uintptr_t)&gMtxClear;
|
||||
OTRMessage_Init();
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "global.h"
|
||||
#include "vt.h"
|
||||
|
||||
#include "soh/Enhancements/debugconsole.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
|
||||
//#include <string.h>
|
||||
|
||||
@ -229,11 +229,11 @@ void PadMgr_ProcessInputs(PadMgr* padMgr) {
|
||||
case 0:
|
||||
input->cur = *padnow1;
|
||||
|
||||
if (chaosEffectNoZ) {
|
||||
if (GameInteractor_DisableZTargetingActive()) {
|
||||
input->cur.button &= ~(BTN_Z);
|
||||
}
|
||||
|
||||
if (chaosEffectReverseControls) {
|
||||
if (GameInteractor_ReverseControlsActive()) {
|
||||
if (input->cur.stick_x == -128) {
|
||||
input->cur.stick_x = 127;
|
||||
} else {
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include "soh/Enhancements/debugconsole.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
|
||||
|
||||
static uint16_t _doActionTexWidth, _doActionTexHeight = -1;
|
||||
@ -939,7 +939,7 @@ void func_80083108(PlayState* play) {
|
||||
Interface_ChangeAlpha(50);
|
||||
}
|
||||
} else if (msgCtx->msgMode == MSGMODE_NONE) {
|
||||
if (chaosEffectPacifistMode) {
|
||||
if (GameInteractor_PacifistModeActive()) {
|
||||
gSaveContext.buttonStatus[0] = gSaveContext.buttonStatus[1] = gSaveContext.buttonStatus[2] =
|
||||
gSaveContext.buttonStatus[3] = gSaveContext.buttonStatus[5] = gSaveContext.buttonStatus[6] =
|
||||
gSaveContext.buttonStatus[7] = gSaveContext.buttonStatus[8] = BTN_DISABLED;
|
||||
@ -3074,7 +3074,7 @@ s32 Health_ChangeBy(PlayState* play, s16 healthChange) {
|
||||
}
|
||||
|
||||
// If one-hit ko mode is on, any damage kills you and you cannot gain health.
|
||||
if (chaosEffectOneHitKO) {
|
||||
if (GameInteractor_OneHitKOActive()) {
|
||||
if (healthChange < 0) {
|
||||
gSaveContext.health = 0;
|
||||
}
|
||||
@ -3091,11 +3091,12 @@ s32 Health_ChangeBy(PlayState* play, s16 healthChange) {
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
if (chaosEffectDefenseModifier != 0 && healthChange < 0) {
|
||||
if (chaosEffectDefenseModifier > 0) {
|
||||
healthChange /= chaosEffectDefenseModifier;
|
||||
int32_t giDefenseModifier = GameInteractor_DefenseModifier();
|
||||
if (giDefenseModifier != 0 && healthChange < 0) {
|
||||
if (giDefenseModifier > 0) {
|
||||
healthChange /= giDefenseModifier;
|
||||
} else {
|
||||
healthChange *= abs(chaosEffectDefenseModifier);
|
||||
healthChange *= abs(giDefenseModifier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3129,14 +3130,6 @@ s32 Health_ChangeBy(PlayState* play, s16 healthChange) {
|
||||
}
|
||||
}
|
||||
|
||||
void Health_GiveHearts(s16 hearts) {
|
||||
gSaveContext.healthCapacity += hearts * 0x10;
|
||||
}
|
||||
|
||||
void Health_RemoveHearts(s16 hearts) {
|
||||
gSaveContext.healthCapacity -= hearts * 0x10;
|
||||
}
|
||||
|
||||
void Rupees_ChangeBy(s16 rupeeChange) {
|
||||
gSaveContext.rupeeAccumulator += rupeeChange;
|
||||
|
||||
@ -4968,7 +4961,7 @@ void Interface_Draw(PlayState* play) {
|
||||
s16 svar6;
|
||||
bool fullUi = !CVarGetInteger("gMinimalUI", 0) || !R_MINIMAP_DISABLED || play->pauseCtx.state != 0;
|
||||
|
||||
if (chaosEffectNoUI) {
|
||||
if (GameInteractor_NoUIActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "objects/object_triforce_spot/object_triforce_spot.h"
|
||||
#include "overlays/actors/ovl_Demo_Effect/z_demo_effect.h"
|
||||
|
||||
#include "soh/Enhancements/debugconsole.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
|
||||
typedef struct {
|
||||
/* 0x00 */ u8 flag;
|
||||
@ -1050,7 +1050,7 @@ s32 func_80090014(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s
|
||||
}
|
||||
}
|
||||
|
||||
if (chaosEffectInvisibleLink) {
|
||||
if (GameInteractor_InvisibleLinkActive()) {
|
||||
this->actor.shape.shadowDraw = NULL;
|
||||
*dList = NULL;
|
||||
}
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "textures/icon_item_24_static/icon_item_24_static.h"
|
||||
#include <soh/Enhancements/custom-message/CustomMessageTypes.h>
|
||||
#include "soh/Enhancements/item-tables/ItemTableTypes.h"
|
||||
#include "soh/Enhancements/debugconsole.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/randomizer/randomizer_entrance.h"
|
||||
|
||||
typedef enum {
|
||||
@ -6080,11 +6080,12 @@ void func_8083DFE0(Player* this, f32* arg1, s16* arg2) {
|
||||
if (this->swordState == 0) {
|
||||
float maxSpeed = R_RUN_SPEED_LIMIT / 100.0f;
|
||||
|
||||
if (chaosEffectSpeedModifier != 0) {
|
||||
if (chaosEffectSpeedModifier > 0) {
|
||||
maxSpeed *= chaosEffectSpeedModifier;
|
||||
int32_t giSpeedModifier = GameInteractor_RunSpeedModifier();
|
||||
if (giSpeedModifier != 0) {
|
||||
if (giSpeedModifier > 0) {
|
||||
maxSpeed *= giSpeedModifier;
|
||||
} else {
|
||||
maxSpeed /= abs(chaosEffectSpeedModifier);
|
||||
maxSpeed /= abs(giSpeedModifier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7717,11 +7718,12 @@ void func_80842180(Player* this, PlayState* play) {
|
||||
func_80837268(this, &sp2C, &sp2A, 0.018f, play);
|
||||
|
||||
if (!func_8083C484(this, &sp2C, &sp2A)) {
|
||||
if (chaosEffectSpeedModifier != 0) {
|
||||
if (chaosEffectSpeedModifier > 0) {
|
||||
sp2C *= chaosEffectSpeedModifier;
|
||||
int32_t giSpeedModifier = GameInteractor_RunSpeedModifier();
|
||||
if (giSpeedModifier != 0) {
|
||||
if (giSpeedModifier > 0) {
|
||||
sp2C *= giSpeedModifier;
|
||||
} else {
|
||||
sp2C /= abs(chaosEffectSpeedModifier);
|
||||
sp2C /= abs(giSpeedModifier);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10993,37 +10995,39 @@ void Player_Update(Actor* thisx, PlayState* play) {
|
||||
MREG(54) = this->actor.world.pos.z;
|
||||
MREG(55) = this->actor.world.rot.y;
|
||||
|
||||
if (chaosEffectGiantLink) {
|
||||
this->actor.scale.x = 0.02f;
|
||||
this->actor.scale.y = 0.02f;
|
||||
this->actor.scale.z = 0.02f;
|
||||
switch (GameInteractor_LinkSize()) {
|
||||
case GI_LINK_SIZE_GIANT:
|
||||
this->actor.scale.x = 0.02f;
|
||||
this->actor.scale.y = 0.02f;
|
||||
this->actor.scale.z = 0.02f;
|
||||
break;
|
||||
case GI_LINK_SIZE_MINISH:
|
||||
this->actor.scale.x = 0.001f;
|
||||
this->actor.scale.y = 0.001f;
|
||||
this->actor.scale.z = 0.001f;
|
||||
break;
|
||||
case GI_LINK_SIZE_PAPER:
|
||||
this->actor.scale.x = 0.001f;
|
||||
this->actor.scale.y = 0.01f;
|
||||
this->actor.scale.z = 0.01f;
|
||||
break;
|
||||
case GI_LINK_SIZE_NORMAL:
|
||||
default:
|
||||
this->actor.scale.x = 0.01f;
|
||||
this->actor.scale.y = 0.01f;
|
||||
this->actor.scale.z = 0.01f;
|
||||
break;
|
||||
}
|
||||
|
||||
if (chaosEffectMinishLink) {
|
||||
this->actor.scale.x = 0.001f;
|
||||
this->actor.scale.y = 0.001f;
|
||||
this->actor.scale.z = 0.001f;
|
||||
}
|
||||
|
||||
if (chaosEffectPaperLink) {
|
||||
this->actor.scale.x = 0.001f;
|
||||
this->actor.scale.y = 0.01f;
|
||||
this->actor.scale.z = 0.01f;
|
||||
}
|
||||
|
||||
if (chaosEffectResetLinkScale) {
|
||||
this->actor.scale.x = 0.01f;
|
||||
this->actor.scale.y = 0.01f;
|
||||
this->actor.scale.z = 0.01f;
|
||||
chaosEffectResetLinkScale = 0;
|
||||
}
|
||||
|
||||
if (chaosEffectGravityLevel == GRAVITY_LEVEL_HEAVY) {
|
||||
this->actor.gravity = -4.0f;
|
||||
}
|
||||
|
||||
if (chaosEffectGravityLevel == GRAVITY_LEVEL_LIGHT) {
|
||||
this->actor.gravity = -0.3f;
|
||||
switch (GameInteractor_GravityLevel()) {
|
||||
case GI_GRAVITY_LEVEL_HEAVY:
|
||||
this->actor.gravity = -4.0f;
|
||||
break;
|
||||
case GI_GRAVITY_LEVEL_LIGHT:
|
||||
this->actor.gravity = -0.3f;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user