diff --git a/src/g_game.cpp b/src/g_game.cpp index 3e040df56..fffa6eff3 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -95,8 +95,9 @@ void G_DoPlayDemo (void); void G_DoCompleted (void); void G_DoVictory (void); void G_DoWorldDone (void); -void G_DoSaveGame (bool okForQuicksave, FString filename, const char *description); +void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, const char *description); void G_DoAutoSave (); +void G_DoQuickSave (); void STAT_Serialize(FSerializer &file); bool WriteZip(const char *filename, TArray &filenames, TArray &content); @@ -1059,7 +1060,7 @@ void G_Ticker () G_DoLoadGame (); break; case ga_savegame: - G_DoSaveGame (true, savegamefile, savedescription); + G_DoSaveGame (true, false, savegamefile, savedescription); gameaction = ga_nothing; savegamefile = ""; savedescription = ""; @@ -2028,6 +2029,14 @@ CUSTOM_CVAR (Int, autosavecount, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) if (self < 0) self = 0; } +CVAR (Int, quicksavenum, -1, CVAR_NOSET|CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +static int lastquicksave = -1; +CVAR (Bool, quicksaverotation, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR (Int, quicksaverotationcount, 4, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +{ + if (self < 1) + self = 1; +} void G_DoAutoSave () { @@ -2061,7 +2070,35 @@ void G_DoAutoSave () readableTime = myasctime (); description.Format("Autosave %s", readableTime); - G_DoSaveGame (false, file, description); + G_DoSaveGame (false, false, file, description); +} + +void G_DoQuickSave () +{ + FString description; + FString file; + // Keeps a rotating set of quicksaves + UCVarValue num; + const char *readableTime; + int count = quicksaverotationcount != 0 ? quicksaverotationcount : 1; + + if (quicksavenum < 0) + { + lastquicksave = 0; + } + else + { + lastquicksave = (quicksavenum + 1) % count; + } + + num.Int = lastquicksave; + quicksavenum.ForceSet (num, CVAR_Int); + + file = G_BuildSaveName ("quick", lastquicksave); + + readableTime = myasctime (); + description.Format("Quicksave %s", readableTime); + G_DoSaveGame (true, true, file, description); } @@ -2166,7 +2203,7 @@ static void PutSavePic (FileWriter *file, int width, int height) } } -void G_DoSaveGame (bool okForQuicksave, FString filename, const char *description) +void G_DoSaveGame (bool okForQuicksave, bool forceQuicksave, FString filename, const char *description) { TArray savegame_content; TArray savegame_filenames; @@ -2282,7 +2319,7 @@ void G_DoSaveGame (bool okForQuicksave, FString filename, const char *descriptio WriteZip(filename, savegame_filenames, savegame_content); - savegameManager.NotifyNewSave (filename, description, okForQuicksave); + savegameManager.NotifyNewSave (filename, description, okForQuicksave, forceQuicksave); // delete the JSON buffers we created just above. Everything else will // either still be needed or taken care of automatically. diff --git a/src/g_game.h b/src/g_game.h index baedc0627..47d9231a0 100644 --- a/src/g_game.h +++ b/src/g_game.h @@ -82,6 +82,8 @@ void G_DoLoadGame (void); // Called by M_Responder. void G_SaveGame (const char *filename, const char *description); +// Called by messagebox +void G_DoQuickSave (); // Only called by startup code. void G_RecordDemo (const char* name); diff --git a/src/menu/loadsavemenu.cpp b/src/menu/loadsavemenu.cpp index a21818f54..6a3d5f0df 100644 --- a/src/menu/loadsavemenu.cpp +++ b/src/menu/loadsavemenu.cpp @@ -318,7 +318,7 @@ DEFINE_ACTION_FUNCTION(FSavegameManager, ReadSaveStrings) // //============================================================================= -void FSavegameManager::NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave) +void FSavegameManager::NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave) { FSaveGameNode *node; @@ -342,7 +342,7 @@ void FSavegameManager::NotifyNewSave(const FString &file, const FString &title, node->bMissingWads = false; if (okForQuicksave) { - if (quickSaveSlot == nullptr) quickSaveSlot = node; + if (quickSaveSlot == nullptr || forceQuicksave) quickSaveSlot = node; LastAccessed = LastSaved = i; } return; @@ -358,7 +358,7 @@ void FSavegameManager::NotifyNewSave(const FString &file, const FString &title, if (okForQuicksave) { - if (quickSaveSlot == nullptr) quickSaveSlot = node; + if (quickSaveSlot == nullptr || forceQuicksave) quickSaveSlot = node; LastAccessed = LastSaved = index; } } diff --git a/src/menu/menu.h b/src/menu/menu.h index 6928bd5b8..296665326 100644 --- a/src/menu/menu.h +++ b/src/menu/menu.h @@ -84,7 +84,7 @@ public: private: int InsertSaveNode(FSaveGameNode *node); public: - void NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave); + void NotifyNewSave(const FString &file, const FString &title, bool okForQuicksave, bool forceQuicksave); void ClearSaveGames(); void ReadSaveStrings(); diff --git a/src/menu/messagebox.cpp b/src/menu/messagebox.cpp index c58b2ab94..732ad8001 100644 --- a/src/menu/messagebox.cpp +++ b/src/menu/messagebox.cpp @@ -44,6 +44,7 @@ #include "vm.h" EXTERN_CVAR (Bool, saveloadconfirmation) // [mxd] +EXTERN_CVAR (Bool, quicksaverotation) typedef void(*hfunc)(); DEFINE_ACTION_FUNCTION(DMessageBoxMenu, CallHandler) @@ -174,6 +175,13 @@ CCMD (quicksave) if (gamestate != GS_LEVEL) return; + + // If the quick save rotation is enabled, it handles the save slot. + if (quicksaverotation) + { + G_DoQuickSave(); + return; + } if (savegameManager.quickSaveSlot == NULL) { diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 0e238666c..32fa61bdb 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1182,6 +1182,8 @@ OptionMenu "MiscOptions" protected Option "$MISCMNU_ENABLEAUTOSAVES", "disableautosave", "Autosave" Option "$MISCMNU_SAVELOADCONFIRMATION", "saveloadconfirmation", "OnOff" Slider "$MISCMNU_AUTOSAVECOUNT", "autosavecount", 1, 20, 1, 0 + Option "$MISCMNU_QUICKSAVEROTATION", "quicksaverotation", "OnOff" + Slider "$MISCMNU_QUICKSAVECOUNT", "quicksaverotationcount", 1, 20, 1, 0 Option "$MISCMNU_DEHLOAD", "dehload", "dehopt" Option "$MISCMNU_ENABLESCRIPTSCREENSHOTS", "enablescriptscreenshot", "OnOff" Option "$MISCMNU_INTERSCROLL", "nointerscrollabort", "OffOn"