diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h index 51a6ab5a8..edbdf1500 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h @@ -47,6 +47,7 @@ DEFINE_HOOK(OnVanillaBehavior, (GIVanillaBehavior flag, bool* result, va_list or DEFINE_HOOK(OnSaveFile, (int32_t fileNum)); DEFINE_HOOK(OnLoadFile, (int32_t fileNum)); DEFINE_HOOK(OnDeleteFile, (int32_t fileNum)); +DEFINE_HOOK(OnDeleteAllFiles, ()); DEFINE_HOOK(OnDialogMessage, ()); DEFINE_HOOK(OnPresentTitleCard, ()); diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 4b830f846..ae8db834d 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -124,6 +124,9 @@ SaveManager::SaveManager() { AddInitFunction(InitFileImpl); + GameInteractor::Instance->RegisterGameHook( + [this]() { this->DeleteAllZeldaFiles(); }); + GameInteractor::Instance->RegisterGameHook( [this](uint32_t fileNum) { ThreadPoolWait(); }); @@ -2371,6 +2374,12 @@ void SaveManager::DeleteZeldaFile(int fileNum) { GameInteractor::Instance->ExecuteHooks(fileNum); } +void SaveManager::DeleteAllZeldaFiles() { + for (int fileNum = 0; fileNum < MaxFiles; fileNum++) { + DeleteZeldaFile(fileNum); + } +} + bool SaveManager::IsRandoFile() { return IS_RANDO; } diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index 6d7ef3b33..d89e090cb 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -103,6 +103,8 @@ class SaveManager { void CopyZeldaFile(int from, int to); void DeleteZeldaFile(int fileNum); + void DeleteAllZeldaFiles(); + bool IsRandoFile(); // Use a name of "" to save to an array. You must be in a SaveArray callback. diff --git a/soh/soh/SohGui/SohMenuSettings.cpp b/soh/soh/SohGui/SohMenuSettings.cpp index bb7c82574..e2bff6154 100644 --- a/soh/soh/SohGui/SohMenuSettings.cpp +++ b/soh/soh/SohGui/SohMenuSettings.cpp @@ -187,6 +187,28 @@ void SohMenu::AddMenuSettings() { SDL_OpenURL(std::string("file:///" + std::filesystem::absolute(filesPath).string()).c_str()); }) .Options(ButtonOptions().Tooltip("Opens the folder that contains the save and mods folders, etc.")); + AddWidget(path, "Enable Delete All Saves", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_SETTING("EnableDeleteAllSaveFilesButton")) + .RaceDisable(false) + .Options(CheckboxOptions() + .Tooltip("Turn on to enable the \"Delete All Saves\" button.Turns off automatically " + "when \"Delete All Saves\" is pressed") + .DefaultValue(false)); + AddWidget(path, "Delete All Saves", WIDGET_BUTTON) + .RaceDisable(false) + .PreFunc([](WidgetInfo& info) { + info.options->disabled = !CVarGetInteger(CVAR_SETTING("EnableDeleteAllSaveFilesButton"), 0); + info.options->disabledTooltip = + "This button is disabled because \"Enable Delete All Saves\" is turned off."; + }) + .Callback([](WidgetInfo& info) { + GameInteractor::Instance->ExecuteHooks(); + CVarSetInteger(CVAR_SETTING("EnableDeleteAllSaveFilesButton"), 0); + std::reinterpret_pointer_cast( + Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGuiWindow("Console")) + ->Dispatch("reset"); + }) + .Options(ButtonOptions().Tooltip("Warning deletes all save files")); AddWidget(path, "Boot", WIDGET_SEPARATOR_TEXT); AddWidget(path, "Boot Sequence", WIDGET_CVAR_COMBOBOX)