mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-02-24 14:51:46 -05:00
Autosave Overhaul (#5022)
* Autosave interval based * Move to save on soft reset, remove adjustable interval * Use new BeforeExitGame hook to prevent non-existent data problems * Fix check tracker crash, remove BeforeExitGame hook * update comment
This commit is contained in:
parent
dbf7fcf775
commit
668040562f
@ -1073,7 +1073,6 @@ uint16_t Interface_DrawTextLine(GraphicsContext* gfx, char text[], int16_t x, in
|
|||||||
u8 Item_Give(PlayState* play, u8 item);
|
u8 Item_Give(PlayState* play, u8 item);
|
||||||
u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry);
|
u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry);
|
||||||
u8 Item_CheckObtainability(u8 item);
|
u8 Item_CheckObtainability(u8 item);
|
||||||
void PerformAutosave(PlayState* play, u8 item);
|
|
||||||
void Inventory_DeleteItem(u16 item, u16 invSlot);
|
void Inventory_DeleteItem(u16 item, u16 invSlot);
|
||||||
s32 Inventory_ReplaceItem(PlayState* play, u16 oldItem, u16 newItem);
|
s32 Inventory_ReplaceItem(PlayState* play, u16 oldItem, u16 newItem);
|
||||||
s32 Inventory_HasEmptyBottle(void);
|
s32 Inventory_HasEmptyBottle(void);
|
||||||
|
78
soh/soh/Enhancements/Autosave.cpp
Normal file
78
soh/soh/Enhancements/Autosave.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include <libultraship/bridge.h>
|
||||||
|
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||||
|
#include "soh/Notification/Notification.h"
|
||||||
|
#include "soh/ShipInit.hpp"
|
||||||
|
#include "soh/SaveManager.h"
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
extern PlayState* gPlayState;
|
||||||
|
#include "functions.h"
|
||||||
|
#include "variables.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t lastSaveTimestamp = GetUnixTimestamp();
|
||||||
|
|
||||||
|
#define CVAR_AUTOSAVE_NAME CVAR_ENHANCEMENT("Autosave")
|
||||||
|
#define CVAR_AUTOSAVE_DEFAULT AUTOSAVE_OFF
|
||||||
|
#define CVAR_AUTOSAVE_VALUE CVarGetInteger(CVAR_AUTOSAVE_NAME, CVAR_AUTOSAVE_DEFAULT)
|
||||||
|
#define THREE_MINUTES_IN_UNIX 3 * 60000
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AUTOSAVE_OFF,
|
||||||
|
AUTOSAVE_ON,
|
||||||
|
} AutosaveOptions;
|
||||||
|
|
||||||
|
bool Autosave_CanSave() {
|
||||||
|
|
||||||
|
// Don't save when in title screen
|
||||||
|
// Don't save the first 60 frames to not save the magic meter when it's still in the animation of filling it.
|
||||||
|
// Don't save in Ganon's fight and chamber of sages because of master sword and remember save location issues.
|
||||||
|
if (!GameInteractor::IsSaveLoaded(true) || gPlayState->gameplayFrames < 60 ||
|
||||||
|
gPlayState->sceneNum == SCENE_GANON_BOSS || gPlayState->sceneNum == SCENE_CHAMBER_OF_THE_SAGES) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Autosave_PerformSave() {
|
||||||
|
Play_PerformSave(gPlayState);
|
||||||
|
|
||||||
|
// Send notification
|
||||||
|
Notification::Emit({
|
||||||
|
.message = "Game autosaved",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Autosave_IntervalSave() {
|
||||||
|
// Check if the interval has passed in minutes.
|
||||||
|
uint64_t currentTimestamp = GetUnixTimestamp();
|
||||||
|
if ((currentTimestamp - lastSaveTimestamp) < THREE_MINUTES_IN_UNIX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If save available to create, do it and reset the interval.
|
||||||
|
// Interval gets extra check for being paused to avoid rare issues like bypassing shop
|
||||||
|
// rupees draining after buying an item. Since the interval can just retry until it
|
||||||
|
// passes, it can use more conditions without hampering the player experience.
|
||||||
|
if (Autosave_CanSave() && !GameInteractor::IsGameplayPaused()) {
|
||||||
|
|
||||||
|
// Reset timestamp, set icon timer to show autosave icon for 5 seconds (100 frames)
|
||||||
|
lastSaveTimestamp = currentTimestamp;
|
||||||
|
|
||||||
|
Autosave_PerformSave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Autosave_SoftResetSave() {
|
||||||
|
if (Autosave_CanSave()) {
|
||||||
|
Autosave_PerformSave();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegisterAutosave() {
|
||||||
|
COND_HOOK(GameInteractor::OnGameFrameUpdate, CVAR_AUTOSAVE_VALUE, Autosave_IntervalSave);
|
||||||
|
COND_HOOK(GameInteractor::OnExitGame, CVAR_AUTOSAVE_VALUE, [](int32_t fileNum) { Autosave_SoftResetSave(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
static RegisterShipInitFunc initFunc(RegisterAutosave, { CVAR_AUTOSAVE_NAME });
|
4
soh/soh/Enhancements/Autosave.h
Normal file
4
soh/soh/Enhancements/Autosave.h
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
typedef enum {
|
||||||
|
AUTOSAVE_OFF,
|
||||||
|
AUTOSAVE_ON,
|
||||||
|
} AutosaveOptions;
|
@ -208,7 +208,6 @@ static bool ResetHandler(std::shared_ptr<Ship::Console> Console, std::vector<std
|
|||||||
ERROR_MESSAGE("gGameState == nullptr");
|
ERROR_MESSAGE("gGameState == nullptr");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SET_NEXT_GAMESTATE(gGameState, TitleSetup_Init, GameState);
|
SET_NEXT_GAMESTATE(gGameState, TitleSetup_Init, GameState);
|
||||||
gGameState->running = false;
|
gGameState->running = false;
|
||||||
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnExitGame>(gSaveContext.fileNum);
|
GameInteractor::Instance->ExecuteHooks<GameInteractor::OnExitGame>(gSaveContext.fileNum);
|
||||||
|
@ -52,15 +52,6 @@ typedef enum {
|
|||||||
ENEMY_RANDOMIZER_RANDOM_SEEDED,
|
ENEMY_RANDOMIZER_RANDOM_SEEDED,
|
||||||
} EnemyRandomizerMode;
|
} EnemyRandomizerMode;
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
AUTOSAVE_OFF,
|
|
||||||
AUTOSAVE_LOCATION_AND_MAJOR_ITEMS,
|
|
||||||
AUTOSAVE_LOCATION_AND_ALL_ITEMS,
|
|
||||||
AUTOSAVE_LOCATION,
|
|
||||||
AUTOSAVE_MAJOR_ITEMS,
|
|
||||||
AUTOSAVE_ALL_ITEMS
|
|
||||||
} AutosaveType;
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BOOTSEQUENCE_DEFAULT,
|
BOOTSEQUENCE_DEFAULT,
|
||||||
BOOTSEQUENCE_AUTHENTIC,
|
BOOTSEQUENCE_AUTHENTIC,
|
||||||
|
@ -135,87 +135,6 @@ void RegisterOcarinaTimeTravel() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoSave(GetItemEntry itemEntry) {
|
|
||||||
u8 item = itemEntry.itemId;
|
|
||||||
bool performSave = false;
|
|
||||||
// Don't autosave immediately after buying items from shops to prevent getting them for free!
|
|
||||||
// Don't autosave in the Chamber of Sages since resuming from that map breaks the game
|
|
||||||
// Don't autosave during the Ganon fight when picking up the Master Sword
|
|
||||||
if ((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) != AUTOSAVE_OFF) && (gPlayState != NULL) && (gSaveContext.ship.pendingSale == ITEM_NONE) &&
|
|
||||||
(gPlayState->gameplayFrames > 60 && gSaveContext.cutsceneIndex < 0xFFF0) && (gPlayState->sceneNum != SCENE_GANON_BOSS) && (gPlayState->sceneNum != SCENE_CHAMBER_OF_THE_SAGES)) {
|
|
||||||
if (((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS) || (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_ALL_ITEMS)) && (item != ITEM_NONE)) {
|
|
||||||
// Autosave for all items
|
|
||||||
performSave = true;
|
|
||||||
|
|
||||||
} else if (((CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS) || (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_MAJOR_ITEMS)) && (item != ITEM_NONE)) {
|
|
||||||
// Autosave for major items
|
|
||||||
if (itemEntry.modIndex == 0) {
|
|
||||||
switch (item) {
|
|
||||||
case ITEM_STICK:
|
|
||||||
case ITEM_NUT:
|
|
||||||
case ITEM_BOMB:
|
|
||||||
case ITEM_BOW:
|
|
||||||
case ITEM_SEEDS:
|
|
||||||
case ITEM_FISHING_POLE:
|
|
||||||
case ITEM_MAGIC_SMALL:
|
|
||||||
case ITEM_MAGIC_LARGE:
|
|
||||||
case ITEM_INVALID_4:
|
|
||||||
case ITEM_INVALID_5:
|
|
||||||
case ITEM_INVALID_6:
|
|
||||||
case ITEM_INVALID_7:
|
|
||||||
case ITEM_HEART:
|
|
||||||
case ITEM_RUPEE_GREEN:
|
|
||||||
case ITEM_RUPEE_BLUE:
|
|
||||||
case ITEM_RUPEE_RED:
|
|
||||||
case ITEM_RUPEE_PURPLE:
|
|
||||||
case ITEM_RUPEE_GOLD:
|
|
||||||
case ITEM_INVALID_8:
|
|
||||||
case ITEM_STICKS_5:
|
|
||||||
case ITEM_STICKS_10:
|
|
||||||
case ITEM_NUTS_5:
|
|
||||||
case ITEM_NUTS_10:
|
|
||||||
case ITEM_BOMBS_5:
|
|
||||||
case ITEM_BOMBS_10:
|
|
||||||
case ITEM_BOMBS_20:
|
|
||||||
case ITEM_BOMBS_30:
|
|
||||||
case ITEM_ARROWS_SMALL:
|
|
||||||
case ITEM_ARROWS_MEDIUM:
|
|
||||||
case ITEM_ARROWS_LARGE:
|
|
||||||
case ITEM_SEEDS_30:
|
|
||||||
case ITEM_NONE:
|
|
||||||
break;
|
|
||||||
case ITEM_BOMBCHU:
|
|
||||||
case ITEM_BOMBCHUS_5:
|
|
||||||
case ITEM_BOMBCHUS_20:
|
|
||||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("EnableBombchuDrops"), 0)) {
|
|
||||||
performSave = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
performSave = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (itemEntry.modIndex == 1 && item != RG_ICE_TRAP) {
|
|
||||||
performSave = true;
|
|
||||||
}
|
|
||||||
} else if (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_MAJOR_ITEMS ||
|
|
||||||
CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION_AND_ALL_ITEMS ||
|
|
||||||
CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) == AUTOSAVE_LOCATION) {
|
|
||||||
performSave = true;
|
|
||||||
}
|
|
||||||
if (performSave) {
|
|
||||||
Play_PerformSave(gPlayState);
|
|
||||||
performSave = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterAutoSave() {
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry itemEntry) { AutoSave(itemEntry); });
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnSaleEnd>([](GetItemEntry itemEntry) { AutoSave(itemEntry); });
|
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnTransitionEnd>([](int32_t sceneNum) { AutoSave(GET_ITEM_NONE); });
|
|
||||||
}
|
|
||||||
|
|
||||||
void RegisterRupeeDash() {
|
void RegisterRupeeDash() {
|
||||||
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
|
||||||
if (!CVarGetInteger(CVAR_ENHANCEMENT("RupeeDash"), 0)) {
|
if (!CVarGetInteger(CVAR_ENHANCEMENT("RupeeDash"), 0)) {
|
||||||
@ -1168,7 +1087,6 @@ void InitMods() {
|
|||||||
TimeSavers_Register();
|
TimeSavers_Register();
|
||||||
RegisterTTS();
|
RegisterTTS();
|
||||||
RegisterOcarinaTimeTravel();
|
RegisterOcarinaTimeTravel();
|
||||||
RegisterAutoSave();
|
|
||||||
RegisterDaytimeGoldSkultullas();
|
RegisterDaytimeGoldSkultullas();
|
||||||
RegisterRupeeDash();
|
RegisterRupeeDash();
|
||||||
RegisterShadowTag();
|
RegisterShadowTag();
|
||||||
|
@ -157,7 +157,6 @@ const std::vector<const char*> enhancementsCvars = {
|
|||||||
CVAR_ENHANCEMENT("GSCutscene"),
|
CVAR_ENHANCEMENT("GSCutscene"),
|
||||||
CVAR_ENHANCEMENT("RestoreRBAValues"),
|
CVAR_ENHANCEMENT("RestoreRBAValues"),
|
||||||
CVAR_ENHANCEMENT("SkipSaveConfirmation"),
|
CVAR_ENHANCEMENT("SkipSaveConfirmation"),
|
||||||
CVAR_ENHANCEMENT("Autosave"),
|
|
||||||
CVAR_ENHANCEMENT("DisableCritWiggle"),
|
CVAR_ENHANCEMENT("DisableCritWiggle"),
|
||||||
CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"),
|
CVAR_ENHANCEMENT("ChestSizeDependsStoneOfAgony"),
|
||||||
CVAR_ENHANCEMENT("SkipArrowAnimation"),
|
CVAR_ENHANCEMENT("SkipArrowAnimation"),
|
||||||
@ -754,7 +753,7 @@ const std::vector<PresetEntry> enhancedPresetEntries = {
|
|||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1),
|
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1),
|
||||||
|
|
||||||
// Autosave
|
// Autosave
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS),
|
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1),
|
||||||
|
|
||||||
// Bombchu shop doesn't sell out, and 10 bombchus cost 99 instead of 100
|
// Bombchu shop doesn't sell out, and 10 bombchus cost 99 instead of 100
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1),
|
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("BetterBombchuShopping"), 1),
|
||||||
@ -887,7 +886,7 @@ const std::vector<PresetEntry> randomizerPresetEntries = {
|
|||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1),
|
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("AnubisFix"), 1),
|
||||||
|
|
||||||
// Autosave
|
// Autosave
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_LOCATION_AND_MAJOR_ITEMS),
|
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("Autosave"), 1),
|
||||||
|
|
||||||
// Customize Fishing Behaviour
|
// Customize Fishing Behaviour
|
||||||
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFishing"), 1),
|
PRESET_ENTRY_S32(CVAR_ENHANCEMENT("CustomizeFishing"), 1),
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#include "soh/util.h"
|
#include "soh/util.h"
|
||||||
#include "fishsanity.h"
|
#include "fishsanity.h"
|
||||||
#include "randomizerTypes.h"
|
#include "randomizerTypes.h"
|
||||||
|
#include "soh/Notification/Notification.h"
|
||||||
|
|
||||||
extern std::map<RandomizerCheckArea, std::string> rcAreaNames;
|
extern std::map<RandomizerCheckArea, std::string> rcAreaNames;
|
||||||
|
|
||||||
@ -4105,6 +4106,9 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
|
|||||||
gSaveContext.ship.stats.gameComplete = 1;
|
gSaveContext.ship.stats.gameComplete = 1;
|
||||||
Flags_SetRandomizerInf(RAND_INF_GRANT_GANONS_BOSSKEY);
|
Flags_SetRandomizerInf(RAND_INF_GRANT_GANONS_BOSSKEY);
|
||||||
Play_PerformSave(play);
|
Play_PerformSave(play);
|
||||||
|
Notification::Emit({
|
||||||
|
.message = "Game autosaved",
|
||||||
|
});
|
||||||
GameInteractor_SetTriforceHuntCreditsWarpActive(true);
|
GameInteractor_SetTriforceHuntCreditsWarpActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1382,7 +1382,9 @@ void UpdateAllAreas() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAreas(RandomizerCheckArea area) {
|
void UpdateAreas(RandomizerCheckArea area) {
|
||||||
|
if (checksByArea.contains(area)) {
|
||||||
areasFullyChecked[area] = areaChecksGotten[area] == checksByArea.find(area)->second.size();
|
areasFullyChecked[area] = areaChecksGotten[area] == checksByArea.find(area)->second.size();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateAllOrdering() {
|
void UpdateAllOrdering() {
|
||||||
|
@ -64,7 +64,6 @@ namespace SohGui {
|
|||||||
static const char* subPowers[8] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6], allPowers[7] };
|
static const char* subPowers[8] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6], allPowers[7] };
|
||||||
static const char* subSubPowers[7] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6] };
|
static const char* subSubPowers[7] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6] };
|
||||||
static const char* zFightingOptions[3] = { "Disabled", "Consistent Vanish", "No Vanish" };
|
static const char* zFightingOptions[3] = { "Disabled", "Consistent Vanish", "No Vanish" };
|
||||||
static const char* autosaveLabels[6] = { "Off", "New Location + Major Item", "New Location + Any Item", "New Location", "Major Item", "Any Item" };
|
|
||||||
static const char* bonkDamageValues[8] = {
|
static const char* bonkDamageValues[8] = {
|
||||||
"No Damage",
|
"No Damage",
|
||||||
"0.25 Heart",
|
"0.25 Heart",
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "soh/Enhancements/randomizer/Plandomizer.h"
|
#include "soh/Enhancements/randomizer/Plandomizer.h"
|
||||||
#include "soh/Enhancements/TimeDisplay/TimeDisplay.h"
|
#include "soh/Enhancements/TimeDisplay/TimeDisplay.h"
|
||||||
#include "soh/AboutWindow.h"
|
#include "soh/AboutWindow.h"
|
||||||
|
#include "soh/Enhancements/Autosave.h"
|
||||||
|
|
||||||
// FA icons are kind of wonky, if they worked how I expected them to the "+ 2.0f" wouldn't be needed, but
|
// FA icons are kind of wonky, if they worked how I expected them to the "+ 2.0f" wouldn't be needed, but
|
||||||
// they don't work how I expect them to so I added that because it looked good when I eyeballed it
|
// they don't work how I expect them to so I added that because it looked good when I eyeballed it
|
||||||
@ -104,7 +105,6 @@ static const char* imguiScaleOptions[4] = { "Small", "Normal", "Large", "X-Large
|
|||||||
static const char* subPowers[8] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6], allPowers[7] };
|
static const char* subPowers[8] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6], allPowers[7] };
|
||||||
static const char* subSubPowers[7] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6] };
|
static const char* subSubPowers[7] = { allPowers[0], allPowers[1], allPowers[2], allPowers[3], allPowers[4], allPowers[5], allPowers[6] };
|
||||||
static const char* zFightingOptions[3] = { "Disabled", "Consistent Vanish", "No Vanish" };
|
static const char* zFightingOptions[3] = { "Disabled", "Consistent Vanish", "No Vanish" };
|
||||||
static const char* autosaveLabels[6] = { "Off", "New Location + Major Item", "New Location + Any Item", "New Location", "Major Item", "Any Item" };
|
|
||||||
static const char* bootSequenceLabels[3] = { "Default", "Authentic", "File Select" };
|
static const char* bootSequenceLabels[3] = { "Default", "Authentic", "File Select" };
|
||||||
static const char* DebugSaveFileModes[3] = { "Off", "Vanilla", "Maxed" };
|
static const char* DebugSaveFileModes[3] = { "Off", "Vanilla", "Maxed" };
|
||||||
static const char* DekuStickCheat[3] = { "Normal", "Unbreakable", "Unbreakable + Always on Fire" };
|
static const char* DekuStickCheat[3] = { "Normal", "Unbreakable", "Unbreakable + Always on Fire" };
|
||||||
@ -1569,13 +1569,11 @@ void DrawEnhancementsMenu() {
|
|||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
UIWidgets::PaddedSeparator(false, true);
|
UIWidgets::PaddedSeparator();
|
||||||
|
|
||||||
// Autosave enum value of 1 is the default in presets and the old checkbox "on" state for backwards compatibility
|
UIWidgets::EnhancementCheckbox("Autosave", CVAR_ENHANCEMENT("Autosave"));
|
||||||
UIWidgets::PaddedText("Autosave", false, true);
|
UIWidgets::Tooltip("Save the game automatically on a 3 minute interval and when soft-resetting the game.\n\n"
|
||||||
UIWidgets::EnhancementCombobox(CVAR_ENHANCEMENT("Autosave"), autosaveLabels, AUTOSAVE_OFF);
|
"The interval autosave will wait if the game is paused in any way (dialogue, pause screen up, cutscenes).");
|
||||||
UIWidgets::Tooltip("Automatically save the game when changing locations and/or obtaining items\n"
|
|
||||||
"Major items exclude rupees and health/magic/ammo refills (but include bombchus unless bombchu drops are enabled)");
|
|
||||||
|
|
||||||
UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
|
UIWidgets::PaddedSeparator(true, true, 2.0f, 2.0f);
|
||||||
|
|
||||||
|
@ -145,7 +145,6 @@ namespace SOH {
|
|||||||
{ MigrationAction::Rename, "gAskToEquip", "gEnhancements.AskToEquip" },
|
{ MigrationAction::Rename, "gAskToEquip", "gEnhancements.AskToEquip" },
|
||||||
{ MigrationAction::Rename, "gAssignableTunicsAndBoots", "gEnhancements.AssignableTunicsAndBoots" },
|
{ MigrationAction::Rename, "gAssignableTunicsAndBoots", "gEnhancements.AssignableTunicsAndBoots" },
|
||||||
{ MigrationAction::Rename, "gAuthenticLogo", "gEnhancements.AuthenticLogo" },
|
{ MigrationAction::Rename, "gAuthenticLogo", "gEnhancements.AuthenticLogo" },
|
||||||
{ MigrationAction::Rename, "gAutosave", "gEnhancements.Autosave" },
|
|
||||||
{ MigrationAction::Rename, "gBetterFW", "gEnhancements.BetterFarore" },
|
{ MigrationAction::Rename, "gBetterFW", "gEnhancements.BetterFarore" },
|
||||||
{ MigrationAction::Rename, "gBetterOwl", "gEnhancements.BetterOwl" },
|
{ MigrationAction::Rename, "gBetterOwl", "gEnhancements.BetterOwl" },
|
||||||
{ MigrationAction::Rename, "gBlueFireArrows", "gEnhancements.BlueFireArrows" },
|
{ MigrationAction::Rename, "gBlueFireArrows", "gEnhancements.BlueFireArrows" },
|
||||||
|
@ -2206,13 +2206,5 @@ void Play_PerformSave(PlayState* play) {
|
|||||||
// Restore temp B values back
|
// Restore temp B values back
|
||||||
gSaveContext.equips.buttonItems[0] = prevB;
|
gSaveContext.equips.buttonItems[0] = prevB;
|
||||||
gSaveContext.buttonStatus[0] = prevStatus;
|
gSaveContext.buttonStatus[0] = prevStatus;
|
||||||
|
|
||||||
uint8_t triforceHuntCompleted =
|
|
||||||
IS_RANDO &&
|
|
||||||
gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected == (Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED) + 1) &&
|
|
||||||
Randomizer_GetSettingValue(RSK_TRIFORCE_HUNT);
|
|
||||||
if (CVarGetInteger(CVAR_ENHANCEMENT("Autosave"), AUTOSAVE_OFF) != AUTOSAVE_OFF || triforceHuntCompleted) {
|
|
||||||
Overlay_DisplayText(3.0f, "Game Saved");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user