Tweaks to autosaves and pause saves to always persist them, along with preventing saves when it's too early or late in the game (#616)

This commit is contained in:
Garrett Cox
2024-05-30 23:20:29 -04:00
committed by GitHub
parent 8ac7dc6b7d
commit 464c55fcbb
5 changed files with 65 additions and 21 deletions
+6 -6
View File
@@ -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,
@@ -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:
@@ -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.
@@ -82,9 +119,7 @@ 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();
@@ -92,7 +127,7 @@ void HandleAutoSave() {
// 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);
@@ -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;
}
});
@@ -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
View File
@@ -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);
@@ -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"
@@ -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();
@@ -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();
@@ -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();
@@ -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;