Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Convert End of Cycle enhancements to ShipInit #945

Merged
merged 3 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion mm/2s2h/Enhancements/Cycle/Cycle.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#ifndef CYCLE_H
#define CYCLE_H

void RegisterEndOfCycleSaveHooks();
void RegisterKeepExpressMail();

#endif // CYCLE_H
143 changes: 80 additions & 63 deletions mm/2s2h/Enhancements/Cycle/EndOfCycle.cpp
Original file line number Diff line number Diff line change
@@ -1,103 +1,120 @@
#include <libultraship/libultraship.h>
#include "2s2h/GameInteractor/GameInteractor.h"
#include "2s2h/ShipInit.hpp"

extern "C" {
#include <variables.h>
#include <overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h>
}

#define CVAR_NAME_RUPEES "gEnhancements.Cycle.DoNotResetRupees"
#define CVAR_RUPEES CVarGetInteger(CVAR_NAME_RUPEES, 0)
#define CVAR_NAME_CONSUME "gEnhancements.Cycle.DoNotResetConsumables"
#define CVAR_CONSUME CVarGetInteger(CVAR_NAME_CONSUME, 0)
#define CVAR_NAME_BOTTLE "gEnhancements.Cycle.DoNotResetBottleContent"
#define CVAR_BOTTLE CVarGetInteger(CVAR_NAME_BOTTLE, 0)
#define CVAR_NAME_SWORD "gEnhancements.Cycle.DoNotResetRazorSword"
#define CVAR_SWORD CVarGetInteger(CVAR_NAME_SWORD, 0)
#define CVAR_NAME_TIME "gEnhancements.Cycle.DoNotResetTimeSpeed"
#define CVAR_TIME CVarGetInteger(CVAR_NAME_TIME, 0)

SaveInfo saveInfoCopy;
ShipSaveInfo shipSaveInfoCopy;
s32 timeSpeedOffsetCopy = 0;

void RegisterEndOfCycleSaveHooks() {
GameInteractor::Instance->RegisterGameHook<GameInteractor::BeforeEndOfCycleSave>([]() {
COND_HOOK(BeforeEndOfCycleSave, true, []() {
memcpy(&saveInfoCopy, &gSaveContext.save.saveInfo, sizeof(SaveInfo));
memcpy(&shipSaveInfoCopy, &gSaveContext.save.shipSaveInfo, sizeof(ShipSaveInfo));
timeSpeedOffsetCopy = gSaveContext.save.timeSpeedOffset;
});

GameInteractor::Instance->RegisterGameHook<GameInteractor::AfterEndOfCycleSave>([]() {
if (CVarGetInteger("gEnhancements.Cycle.DoNotResetRupees", 0)) {
gSaveContext.save.saveInfo.playerData.rupees = saveInfoCopy.playerData.rupees;
}
COND_HOOK(AfterEndOfCycleSave, CVAR_RUPEES, []() {
gSaveContext.save.saveInfo.playerData.rupees = saveInfoCopy.playerData.rupees;
CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_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];
}
COND_HOOK(AfterEndOfCycleSave, CVAR_CONSUME, []() {
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_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_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];
}
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];
}
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)) {
int stolenBottles = (((saveInfoCopy.stolenItems & 0xFF000000) >> 0x18) == ITEM_BOTTLE) +
(((saveInfoCopy.stolenItems & 0x00FF0000) >> 0x10) == ITEM_BOTTLE);
CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_BOMB_AMMO);
CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_NUT_AMMO);
CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_STICK_AMMO);
CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_ARROW_AMMO);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice touch to add these!

});

COND_HOOK(AfterEndOfCycleSave, CVAR_BOTTLE, []() {
int stolenBottles = (((saveInfoCopy.stolenItems & 0xFF000000) >> 0x18) == ITEM_BOTTLE) +
(((saveInfoCopy.stolenItems & 0x00FF0000) >> 0x10) == ITEM_BOTTLE);

// Replace bottles back, accounting for any stolen bottles
for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_6; i++) {
gSaveContext.save.saveInfo.inventory.items[i] = saveInfoCopy.inventory.items[i];
// Replace bottles back, accounting for any stolen bottles
for (int i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_6; i++) {
gSaveContext.save.saveInfo.inventory.items[i] = saveInfoCopy.inventory.items[i];

if (stolenBottles > 0 && saveInfoCopy.inventory.items[i] == ITEM_NONE) {
stolenBottles--;
gSaveContext.save.saveInfo.inventory.items[i] = ITEM_BOTTLE;
}
if (stolenBottles > 0 && saveInfoCopy.inventory.items[i] == ITEM_NONE) {
stolenBottles--;
gSaveContext.save.saveInfo.inventory.items[i] = ITEM_BOTTLE;
}
}

// Set back button equips to the correct bottle type
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.equips.buttonItems[0][j]);
}
// Set back button equips to the correct bottle type
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.equips.buttonItems[0][j]);
}
for (int j = EQUIP_SLOT_D_RIGHT; j <= EQUIP_SLOT_D_UP; j++) {
if (DPAD_GET_CUR_FORM_BTN_ITEM(j) == ITEM_BOTTLE) {
DPAD_SET_CUR_FORM_BTN_ITEM(j, shipSaveInfoCopy.dpadEquips.dpadItems[0][j]);
}
}
for (int j = EQUIP_SLOT_D_RIGHT; j <= EQUIP_SLOT_D_UP; j++) {
if (DPAD_GET_CUR_FORM_BTN_ITEM(j) == ITEM_BOTTLE) {
DPAD_SET_CUR_FORM_BTN_ITEM(j, shipSaveInfoCopy.dpadEquips.dpadItems[0][j]);
}
}
});

if (CVarGetInteger("gEnhancements.Cycle.DoNotResetRazorSword", 0)) {
u8 curSword =
(saveInfoCopy.equips.equipment & gEquipMasks[EQUIP_TYPE_SWORD]) >> gEquipShifts[EQUIP_TYPE_SWORD];

// Check for razor sword equipped, stolen, or turned into the smithy
if (curSword == EQUIP_VALUE_SWORD_RAZOR ||
(curSword == EQUIP_VALUE_SWORD_NONE &&
((saveInfoCopy.permanentSceneFlags[SCENE_KAJIYA].unk_14 & 4) ||
(((saveInfoCopy.stolenItems & 0xFF000000) >> 0x18) == ITEM_SWORD_RAZOR) ||
(((saveInfoCopy.stolenItems & 0x00FF0000) >> 0x10) == ITEM_SWORD_RAZOR)))) {
COND_HOOK(AfterEndOfCycleSave, CVAR_SWORD, []() {
u8 curSword = (saveInfoCopy.equips.equipment & gEquipMasks[EQUIP_TYPE_SWORD]) >> gEquipShifts[EQUIP_TYPE_SWORD];

SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_RAZOR);
BUTTON_ITEM_EQUIP(0, EQUIP_SLOT_B) = ITEM_SWORD_RAZOR;
}
}
// Check for razor sword equipped, stolen, or turned into the smithy
if (curSword == EQUIP_VALUE_SWORD_RAZOR ||
(curSword == EQUIP_VALUE_SWORD_NONE &&
((saveInfoCopy.permanentSceneFlags[SCENE_KAJIYA].unk_14 & 4) ||
(((saveInfoCopy.stolenItems & 0xFF000000) >> 0x18) == ITEM_SWORD_RAZOR) ||
(((saveInfoCopy.stolenItems & 0x00FF0000) >> 0x10) == ITEM_SWORD_RAZOR)))) {

if (CVarGetInteger("gEnhancements.Cycle.DoNotResetTimeSpeed", 0)) {
gSaveContext.save.timeSpeedOffset = timeSpeedOffsetCopy;
SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_RAZOR);
BUTTON_ITEM_EQUIP(0, EQUIP_SLOT_B) = ITEM_SWORD_RAZOR;
}
});

COND_HOOK(AfterEndOfCycleSave, CVAR_TIME, []() { gSaveContext.save.timeSpeedOffset = timeSpeedOffsetCopy; });
}

static RegisterShipInitFunc initFunc(RegisterEndOfCycleSaveHooks,
{ CVAR_NAME_RUPEES, CVAR_NAME_CONSUME, CVAR_NAME_BOTTLE, CVAR_NAME_SWORD,
CVAR_NAME_TIME });
1 change: 0 additions & 1 deletion mm/2s2h/Enhancements/Enhancements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

void InitEnhancements() {
// Cycle & Saving
RegisterEndOfCycleSaveHooks();
RegisterSavingEnhancements();
RegisterAutosave();
RegisterKeepExpressMail();
Expand Down
8 changes: 8 additions & 0 deletions mm/src/overlays/actors/ovl_En_Test6/z_en_test6.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ void EnTest6_Init(Actor* thisx, PlayState* play2);
void EnTest6_Destroy(Actor* thisx, PlayState* play2);
void EnTest6_Update(Actor* thisx, PlayState* play);
void EnTest6_Draw(Actor* thisx, PlayState* play);
void EnTest6_Reset(void);

struct SoTCsAmmoDrops;

Expand Down Expand Up @@ -61,6 +62,7 @@ ActorInit En_Test6_InitVars = {
/**/ EnTest6_Destroy,
/**/ EnTest6_Update,
/**/ EnTest6_Draw,
/**/ EnTest6_Reset,
};

CutsceneData sDoubleSoTCsCamData[] = {
Expand Down Expand Up @@ -1442,3 +1444,9 @@ void EnTest6_Draw(Actor* thisx, PlayState* play) {
}
}
}

void EnTest6_Reset(void) {
for (int i = 0; i < ARRAY_COUNT(sSoTCsAmmoDrops); i++) {
sSoTCsAmmoDrops[i].type = SOTCS_AMMO_DROP_NONE;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good find!

}
}
Loading