Skip to content

Commit

Permalink
Tweaks to autosaves and pause saves to always persist them, along wit…
Browse files Browse the repository at this point in the history
…h preventing saves when it's too early or late in the game (#616)
  • Loading branch information
garrettjoecox authored May 31, 2024
1 parent 8ac7dc6 commit 464c55f
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 21 deletions.
12 changes: 6 additions & 6 deletions mm/2s2h/BenGui/BenMenuBar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -437,14 +437,14 @@ void DrawEnhancementsMenu() {
UIWidgets::CVarCheckbox(
"Pause Menu Save", "gEnhancements.Saving.PauseSave",
{ .tooltip = "Re-introduce the pause menu save system. Pressing B in the pause menu will give you the "
"option to create an Owl Save from your current location.\n\nWhen loading back into the "
"game, you will be placed either at the entrance of the dungeon you saved in, or in South "
"Clock Town." });
"option to create a persistent Owl Save from your current location.\n\nWhen loading back "
"into the game, you will be placed either at the entrance of the dungeon you saved in, or "
"in South Clock Town." });
if (UIWidgets::CVarCheckbox(
"Autosave", "gEnhancements.Saving.Autosave",
{ .tooltip = "Automatically create owl saves on the chosen interval.\n\nWhen loading back into the "
"game, you will be placed either at the entrance of the dungeon you saved in, or in "
"South Clock Town." })) {
{ .tooltip = "Automatically create a persistent Owl Save on the chosen interval.\n\nWhen loading "
"back into the game, you will be placed either at the entrance of the dungeon you "
"saved in, or in South Clock Town." })) {
RegisterAutosave();
}
UIWidgets::CVarSliderInt("Autosave Interval (minutes): %d", "gEnhancements.Saving.AutosaveInterval", 1, 60,
Expand Down
50 changes: 43 additions & 7 deletions mm/2s2h/Enhancements/Saving/SavingEnhancements.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ static uint32_t autosaveGameStateUpdateHookId = 0;
static uint32_t autosaveGameStateDrawFinishHookId = 0;

// Used for saving through Autosaves and Pause Menu saves.
extern "C" int32_t GetSaveEntrance(PlayState* play) {
switch (play->sceneId) {
extern "C" int SavingEnhancements_GetSaveEntrance() {
switch (gPlayState->sceneId) {
// Woodfall Temple + Odolwa
case SCENE_MITURIN:
case SCENE_MITURIN_BS:
Expand All @@ -40,6 +40,43 @@ extern "C" int32_t GetSaveEntrance(PlayState* play) {
}
}

extern "C" bool SavingEnhancements_CanSave() {
// Game State
if (gPlayState == NULL || GET_PLAYER(gPlayState) == NULL) {
return false;
}

// Owl saving available
if (!gSaveContext.flashSaveAvailable || gSaveContext.fileNum == 255) {
return false;
}

// Not in a blocking cutscene
if (Player_InBlockingCsMode(gPlayState, GET_PLAYER(gPlayState))) {
return false;
}

// Not in the middle of dialog
if (gPlayState->msgCtx.msgMode != 0) {
return false;
}

// Hasn't gotten to clock town yet
if (gPlayState->sceneId == SCENE_SPOT00 || gPlayState->sceneId == SCENE_LOST_WOODS ||
gPlayState->sceneId == SCENE_OPENINGDAN) {
return false;
}

// Can't save once you've gone to the moon
if (gPlayState->sceneId == SCENE_SOUGEN || gPlayState->sceneId == SCENE_LAST_LINK ||
gPlayState->sceneId == SCENE_LAST_DEKU || gPlayState->sceneId == SCENE_LAST_GORON ||
gPlayState->sceneId == SCENE_LAST_ZORA || gPlayState->sceneId == SCENE_LAST_BS) {
return false;
}

return true;
}

void DeleteOwlSave() {
// Remove Owl Save on time cycle reset, needed when persisting owl saves and/or when
// creating owl saves without the player being send back to the file select screen.
Expand Down Expand Up @@ -82,17 +119,15 @@ void HandleAutoSave() {
}

// If owl save available to create, do it and reset the interval.
if (gSaveContext.flashSaveAvailable && gSaveContext.fileNum != 255 &&
!Player_InBlockingCsMode(gPlayState, player) && gPlayState->pauseCtx.state == 0 &&
gPlayState->msgCtx.msgMode == 0) {
if (SavingEnhancements_CanSave() && gPlayState->pauseCtx.state == 0) {

// Reset timestamp, set icon timer to show autosave icon for 5 seconds (100 frames)
lastSaveTimestamp = GetUnixTimestamp();
iconTimer = 100;

// Create owl save
gSaveContext.save.isOwlSave = true;
gSaveContext.save.shipSaveInfo.pauseSaveEntrance = GetSaveEntrance(gPlayState);
gSaveContext.save.shipSaveInfo.pauseSaveEntrance = SavingEnhancements_GetSaveEntrance();
Play_SaveCycleSceneFlags(&gPlayState->state);
gSaveContext.save.saveInfo.playerData.savedSceneId = gPlayState->sceneId;
func_8014546C(&gPlayState->sramCtx);
Expand All @@ -106,7 +141,8 @@ void HandleAutoSave() {

void RegisterSavingEnhancements() {
REGISTER_VB_SHOULD(GI_VB_DELETE_OWL_SAVE, {
if (CVarGetInteger("gEnhancements.Saving.PersistentOwlSaves", 0)) {
if (CVarGetInteger("gEnhancements.Saving.PersistentOwlSaves", 0) ||
gSaveContext.save.shipSaveInfo.pauseSaveEntrance != -1) {
*should = false;
}
});
Expand Down
11 changes: 11 additions & 0 deletions mm/2s2h/Enhancements/Saving/SavingEnhancements.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,15 @@
void RegisterSavingEnhancements();
void RegisterAutosave();

#ifdef __cplusplus
extern "C" {
#endif

int SavingEnhancements_GetSaveEntrance();
bool SavingEnhancements_CanSave();

#ifdef __cplusplus
}
#endif

#endif // SAVING_ENHANCEMENTS_H
4 changes: 0 additions & 4 deletions mm/include/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -1365,10 +1365,6 @@ void osSpTaskYield(void);
void osViSetXScale(f32 value);
void osViSetYScale(f32 value);
// #endregion
// #region 2S2H [Enhancements]
// [Autosaves & Pause Menu Saves]
int32_t GetSaveEntrance(PlayState* play);
// #endregion

void Regs_InitData(PlayState* play);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "archives/item_name_static/item_name_static.h"
#include "archives/map_name_static/map_name_static.h"
#include "2s2h/Enhancements/FrameInterpolation/FrameInterpolation.h"
#include "2s2h/Enhancements/Saving/SavingEnhancements.h"

#include "2s2h_assets.h"

Expand Down Expand Up @@ -3377,7 +3378,7 @@ void KaleidoScope_Update(PlayState* play) {
if (!pauseCtx->itemDescriptionOn &&
(CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B))) {
Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0)) {
if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0) && SavingEnhancements_CanSave()) {
if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
pauseCtx->state = PAUSE_STATE_SAVEPROMPT;
Audio_PlaySfx_MessageDecide();
Expand Down Expand Up @@ -3418,7 +3419,7 @@ void KaleidoScope_Update(PlayState* play) {
// Abort having the player play the song and close the pause menu
AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF);
Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0)) {
if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0) && SavingEnhancements_CanSave()) {
if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
pauseCtx->state = PAUSE_STATE_SAVEPROMPT;
Audio_PlaySfx_MessageDecide();
Expand Down Expand Up @@ -3461,7 +3462,7 @@ void KaleidoScope_Update(PlayState* play) {
if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B)) {
AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF);
Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0)) {
if (CVarGetInteger("gEnhancements.Saving.PauseSave", 0) && SavingEnhancements_CanSave()) {
if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
pauseCtx->state = PAUSE_STATE_SAVEPROMPT;
Audio_PlaySfx_MessageDecide();
Expand Down Expand Up @@ -3518,7 +3519,7 @@ void KaleidoScope_Update(PlayState* play) {
// 2S2H [Enhancement] Eventually we might allow them to load from their last entrance,
// but we need to first identify and fix edge cases where that doesn't work properly
// like grottos and cutscenes
gSaveContext.save.shipSaveInfo.pauseSaveEntrance = GetSaveEntrance(play);
gSaveContext.save.shipSaveInfo.pauseSaveEntrance = SavingEnhancements_GetSaveEntrance();
}
Play_SaveCycleSceneFlags(&play->state);
gSaveContext.save.saveInfo.playerData.savedSceneId = play->sceneId;
Expand Down

0 comments on commit 464c55f

Please sign in to comment.