ADD: Reset Cycle enhancements (#233)

* ADD: Reset Cycle enhancements

TODO/ Using hooks

* FIX: Typo

* Convert to hooks

TODO: Complete Pictobox

* TWEAK: alignment style and whitespaces

* REM: Pictobox attempts

* FIX: oopsie on merge dev

* TWEAK: Review suggestion with memcpy

* Tweak typo

* loop fix

* Try: Fix linux compilation ??

* include 2
This commit is contained in:
PurpleHato
2024-05-22 09:05:03 -05:00
committed by Garrett Cox
parent 8253bd27f7
commit 1e45e51884
8 changed files with 116 additions and 0 deletions
+17
View File
@@ -291,6 +291,23 @@ extern std::shared_ptr<HudEditorWindow> mHudEditorWindow;
void DrawEnhancementsMenu() {
if (UIWidgets::BeginMenu("Enhancements")) {
if (UIWidgets::BeginMenu("Cycle")) {
UIWidgets::CVarCheckbox("Do no reset Bottle content", "gEnhancements.Cycle.DoNotResetBottleContent", {
.tooltip = "Playing the Song Of Time will not reset the bottles' content."
});
UIWidgets::CVarCheckbox("Do no reset Consumables", "gEnhancements.Cycle.DoNotResetConsumables", {
.tooltip = "Playing the Song Of Time will not reset the consumables."
});
UIWidgets::CVarCheckbox("Do no reset Razor Sword", "gEnhancements.Cycle.DoNotResetRazorSword", {
.tooltip = "Playing the Song Of Time will not reset the Sword back to Kokiri Sword."
});
UIWidgets::CVarCheckbox("Do no reset Rupees", "gEnhancements.Cycle.DoNotResetRupees", {
.tooltip = "Playing the Song Of Time will not reset the your rupees."
});
ImGui::EndMenu();
}
if (UIWidgets::BeginMenu("Masks")) {
UIWidgets::CVarCheckbox("Fierce Deity's Mask Anywhere", "gEnhancements.Masks.FierceDeitysAnywhere", {
.tooltip = "Allow using Fierce Deity's mask outside of boss rooms."
+73
View File
@@ -0,0 +1,73 @@
#include <libultraship/libultraship.h>
#include "Enhancements/GameInteractor/GameInteractor.h"
extern "C" {
#include <variables.h>
#include <overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h>
}
SaveInfo saveInfoCopy;
void RegisterEndOfCycleSaveHooks() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::BeforeEndOfCycleSave>([]() {
memcpy(&saveInfoCopy, &gSaveContext.save.saveInfo, sizeof(SaveInfo));
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::AfterEndOfCycleSave>([]() {
if (CVarGetInteger("gEnhancements.Cycle.DoNotResetRupees", 0)) {
gSaveContext.save.saveInfo.playerData.rupees = saveInfoCopy.playerData.rupees;
}
if (CVarGetInteger("gEnhancements.Cycle.DoNotResetConsumables", 0)) {
if (INV_CONTENT(ITEM_BOMB) == ITEM_BOMB) {
INV_CONTENT(ITEM_BOMB) = saveInfoCopy.inventory.items[ITEM_BOMB];
AMMO(ITEM_BOMB) = saveInfoCopy.inventory.ammo[ITEM_BOMB];
}
if (INV_CONTENT(ITEM_DEKU_NUT) == ITEM_DEKU_NUT) {
INV_CONTENT(ITEM_DEKU_NUT) = saveInfoCopy.inventory.items[ITEM_DEKU_NUT];
AMMO(ITEM_DEKU_NUT) = saveInfoCopy.inventory.ammo[ITEM_DEKU_NUT];
}
if (INV_CONTENT(ITEM_DEKU_STICK) == ITEM_DEKU_STICK) {
INV_CONTENT(ITEM_DEKU_STICK) = saveInfoCopy.inventory.items[ITEM_DEKU_STICK];
AMMO(ITEM_DEKU_STICK) = saveInfoCopy.inventory.ammo[ITEM_DEKU_STICK];
}
if (INV_CONTENT(ITEM_BOW) == ITEM_BOW) {
INV_CONTENT(ITEM_BOW) = saveInfoCopy.inventory.items[ITEM_BOW];
AMMO(ITEM_BOW) = saveInfoCopy.inventory.ammo[ITEM_BOW];
}
for (int i = 0; i < ITEM_NUM_SLOTS; i++) {
if (gAmmoItems[i] != ITEM_NONE) {
if ((gSaveContext.save.saveInfo.inventory.items[i] != ITEM_NONE) && (i != SLOT_PICTOGRAPH_BOX)) {
gSaveContext.save.saveInfo.inventory.items[i] = saveInfoCopy.inventory.items[i];
gSaveContext.save.saveInfo.inventory.ammo[i] = saveInfoCopy.inventory.ammo[i];
}
}
}
}
if (CVarGetInteger("gEnhancements.Cycle.DoNotResetBottleContent", 0)) {
for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_6; i++) {
for (int j = EQUIP_SLOT_C_LEFT; j <= EQUIP_SLOT_C_RIGHT; j++) {
if (GET_CUR_FORM_BTN_ITEM(j) == ITEM_BOTTLE) {
SET_CUR_FORM_BTN_ITEM(j, saveInfoCopy.inventory.items[i]);
}
}
gSaveContext.save.saveInfo.inventory.items[i] = saveInfoCopy.inventory.items[i];
}
}
if (CVarGetInteger("gEnhancements.Cycle.DoNotResetRazorSword", 0) &&
((saveInfoCopy.equips.equipment & gEquipMasks[EQUIP_TYPE_SWORD]) >>
gEquipShifts[EQUIP_TYPE_SWORD]) == EQUIP_VALUE_SWORD_RAZOR) {
SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_RAZOR);
CUR_FORM_EQUIP(EQUIP_SLOT_B) = ITEM_SWORD_RAZOR;
}
});
}
+6
View File
@@ -0,0 +1,6 @@
#ifndef CYCLES_END_H
#define CYCLES_END_H
void RegisterEndOfCycleSaveHooks();
#endif // CYCLES_END_H
+3
View File
@@ -5,6 +5,9 @@ void InitEnhancements() {
RegisterInfiniteCheats();
RegisterMoonJumpOnL();
// Cycle
RegisterEndOfCycleSaveHooks();
// Masks
RegisterFierceDeityAnywhere();
+1
View File
@@ -3,6 +3,7 @@
#include "Cheats/MoonJump.h"
#include "Cheats/Infinite.h"
#include "Cycle/EndOfCycle.h"
#include "Masks/FierceDeityAnywhere.h"
#include "TimeSavers/TimeSavers.h"
@@ -18,6 +18,14 @@ void GameInteractor_ExecuteOnGameStateUpdate() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnGameStateUpdate>();
}
void GameInteractor_ExecuteBeforeEndOfCycleSave() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::BeforeEndOfCycleSave>();
}
void GameInteractor_ExecuteAfterEndOfCycleSave() {
GameInteractor::Instance->ExecuteHooks<GameInteractor::AfterEndOfCycleSave>();
}
void GameInteractor_ExecuteOnSceneInit(s16 sceneId, s8 spawnNum) {
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnSceneInit>(sceneId, spawnNum);
GameInteractor::Instance->ExecuteHooksForID<GameInteractor::OnSceneInit>(sceneId, sceneId, spawnNum);
@@ -209,6 +209,8 @@ public:
DEFINE_HOOK(OnGameStateMainFinish, ());
DEFINE_HOOK(OnGameStateDrawFinish, ());
DEFINE_HOOK(OnGameStateUpdate, ());
DEFINE_HOOK(BeforeEndOfCycleSave, ());
DEFINE_HOOK(AfterEndOfCycleSave, ());
DEFINE_HOOK(OnSceneInit, (s8 sceneId, s8 spawnNum));
DEFINE_HOOK(OnRoomInit, (s8 sceneId, s8 roomNum));
@@ -240,6 +242,8 @@ extern "C" {
void GameInteractor_ExecuteOnGameStateMainFinish();
void GameInteractor_ExecuteOnGameStateDrawFinish();
void GameInteractor_ExecuteOnGameStateUpdate();
void GameInteractor_ExecuteBeforeEndOfCycleSave();
void GameInteractor_ExecuteAfterEndOfCycleSave();
void GameInteractor_ExecuteOnSceneInit(s16 sceneId, s8 spawnNum);
void GameInteractor_ExecuteOnRoomInit(s16 sceneId, s8 roomNum);
+4
View File
@@ -4,6 +4,8 @@
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
#include <string.h>
#include "Enhancements/GameInteractor/GameInteractor.h"
void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages);
void func_80147314(SramContext* sramCtx, s32 fileNum);
void func_80147414(SramContext* sramCtx, s32 fileNum, s32 arg2);
@@ -426,6 +428,7 @@ void Sram_ClearFlagsAtDawnOfTheFirstDay(void) {
* Used by Song of Time (when clicking "Yes") and (indirectly) by the "Dawn of the New Day" cutscene
*/
void Sram_SaveEndOfCycle(PlayState* play) {
GameInteractor_ExecuteBeforeEndOfCycleSave();
s16 sceneId;
s32 j;
s32 i;
@@ -648,6 +651,7 @@ void Sram_SaveEndOfCycle(PlayState* play) {
gSaveContext.rupeeAccumulator = 0;
Horse_ResetHorseData(play);
GameInteractor_ExecuteAfterEndOfCycleSave();
}
void Sram_IncrementDay(void) {