Add the option for multiple quicksave slots

With more than 1 quicksave slot, slots will be created each time you
quicksave until the maximum number (configured in settings) of
quicksaves has been reached.  After that, the oldest quicksave slot will
be replaced each time you quicksave.  Saves are numbered sequentially,
unless the maximum number of slots is 1, in which case it is not numbered.
pull/390/head
Daniel Vukelich 7 years ago
parent 2dff3aab22
commit 97924d97c7

@ -89,7 +89,7 @@ add_openmw_dir (mwmechanics
) )
add_openmw_dir (mwstate add_openmw_dir (mwstate
statemanagerimp charactermanager character statemanagerimp charactermanager character quicksavemanager
) )
add_openmw_dir (mwbase add_openmw_dir (mwbase
@ -223,4 +223,3 @@ endif (MSVC)
if (WIN32) if (WIN32)
INSTALL(TARGETS openmw RUNTIME DESTINATION ".") INSTALL(TARGETS openmw RUNTIME DESTINATION ".")
endif (WIN32) endif (WIN32)

@ -0,0 +1,73 @@
#include "quicksavemanager.hpp"
#include <sstream>
MWState::QuickSaveManager::QuickSaveManager(std::string &saveName, int maxSaves){
this->saveName = saveName;
this->maxSaves = maxSaves;
this->oldestSlotVisited = NULL;
this->oldestSlotId = 0;
this->slotsVisited = 0;
}
void MWState::QuickSaveManager::visitSave(const Slot *saveSlot){
int slotId;
if(tryExtractSlotId(saveSlot->mProfile.mDescription, slotId)){
++slotsVisited;
if(isOldestSave(saveSlot)){
oldestSlotVisited = saveSlot;
oldestSlotId = slotId;
}
}
}
bool MWState::QuickSaveManager::isOldestSave(const Slot *compare){
if(oldestSlotVisited == NULL)
return true;
return (compare->mTimeStamp < oldestSlotVisited->mTimeStamp);
}
bool MWState::QuickSaveManager::tryExtractSlotId(const std::string &slotName, int &extractedId){
std::istringstream formattedExtractor = std::istringstream(slotName);
std::string nameToTest;
formattedExtractor >> nameToTest;
if(nameToTest == saveName){
//Only try to extract the id if maxSaves > 1
//With maxSaves == 1, we don't append the slotId to the name
if(formattedExtractor >> extractedId)
return (isSlotIdValid(extractedId));
else if(maxSaves == 1)
return formattedExtractor.eof();
}
return false;
}
bool MWState::QuickSaveManager::isSlotIdValid(int slotId){
return (slotId > 0 && slotId <= maxSaves);
}
bool MWState::QuickSaveManager::shouldCreateNewSlot(){
return (slotsVisited < maxSaves);
}
const MWState::Slot *MWState::QuickSaveManager::getNextQuickSaveSlot(){
if(shouldCreateNewSlot())
return NULL;
return oldestSlotVisited;
}
std::string MWState::QuickSaveManager::getNextQuickSaveName(){
std::ostringstream nameFormatter;
nameFormatter << saveName;
//Only print the number if there will be more than 1
if(maxSaves > 1)
nameFormatter << " " << calcNextSlotId();
return nameFormatter.str();
}
int MWState::QuickSaveManager::calcNextSlotId(){
if(shouldCreateNewSlot())
return (slotsVisited + 1);
return oldestSlotId;
}

@ -0,0 +1,42 @@
#ifndef GAME_STATE_QUICKSAVEMANAGER_H
#define GAME_STATE_QUICKSAVEMANAGER_H
#include "character.hpp"
#include "../mwbase/statemanager.hpp"
#include <string>
namespace MWState{
class QuickSaveManager{
std::string saveName;
int maxSaves;
int slotsVisited;
int oldestSlotId;
const Slot *oldestSlotVisited;
private:
bool tryExtractSlotId(const std::string &slotName, int &extractedIdll);
bool isSlotIdValid(int slotId);
bool shouldCreateNewSlot();
bool isOldestSave(const Slot *compare);
int calcNextSlotId();
public:
QuickSaveManager(std::string &saveName, int maxSaves);
///< A utility class to manage multiple quicksave slots
///
/// \param saveName The name of the save ("QuickSave", "AutoSave", etc)
/// \param maxSaves The maximum number of save slots to use before recycling old ones
void visitSave(const Slot *saveSlot);
///< Visits the given \a slot \a
const Slot *getNextQuickSaveSlot();
///< Get the slot that the next quicksave should use.
///
///\return Either the oldest quicksave slot visited, or NULL if a new slot can be made
std::string getNextQuickSaveName();
///< Get the name that the next quicksave should use ("QuickSave 1", "AutoSave 10", etc)
};
}
#endif

@ -37,6 +37,8 @@
#include "../mwscript/globalscripts.hpp" #include "../mwscript/globalscripts.hpp"
#include "quicksavemanager.hpp"
void MWState::StateManager::cleanup (bool force) void MWState::StateManager::cleanup (bool force)
{ {
if (mState!=State_NoGame || force) if (mState!=State_NoGame || force)
@ -324,20 +326,25 @@ void MWState::StateManager::quickSave (std::string name)
return; return;
} }
const Slot* slot = NULL; int maxSaves = Settings::Manager::getInt("max quicksaves", "Saves");
if(maxSaves < 1)
maxSaves = 1;
Character* currentCharacter = getCurrentCharacter(); //Get current character Character* currentCharacter = getCurrentCharacter(); //Get current character
QuickSaveManager saveFinder = QuickSaveManager(name, maxSaves);
//Find quicksave slot
if (currentCharacter) if (currentCharacter)
{ {
for (Character::SlotIterator it = currentCharacter->begin(); it != currentCharacter->end(); ++it) for (Character::SlotIterator it = currentCharacter->begin(); it != currentCharacter->end(); ++it)
{ {
if (it->mProfile.mDescription == name) //Visiting slots allows the quicksave finder to find the oldest quicksave
slot = &*it; saveFinder.visitSave(&*it);
} }
} }
saveGame(name, slot); //Once all the saves have been visited, the save finder can tell us which
//one to replace (or create)
saveGame(saveFinder.getNextQuickSaveName(), saveFinder.getNextQuickSaveSlot());
} }
void MWState::StateManager::loadGame(const std::string& filepath) void MWState::StateManager::loadGame(const std::string& filepath)

@ -35,3 +35,14 @@ This setting determines whether the amount of the time the player has spent play
for each saved game in the Load menu. for each saved game in the Load menu.
This setting can only be configured by editing the settings configuration file. This setting can only be configured by editing the settings configuration file.
max quicksaves
----------
:Type: integer
:Range: >0
:Default: 5
This setting determines how many quicksave and autosave slots you can have at a time. If greater than 1, quicksaves will be sequentially created each time you quicksave. Once the maximum number of quicksaves has been reached, the oldest quicksave will be recycled the next time you perform a quicksave.
This setting can only be configured by editing the settings configuration file.

@ -288,6 +288,10 @@ autosave = true
# Display the time played on each save file in the load menu. # Display the time played on each save file in the load menu.
timeplayed = false timeplayed = false
# The maximum number of quick (or auto) save slots to have.
# If all slots are used, the oldest save is reused
max quicksaves = 5
[Sound] [Sound]
# Name of audio device file. Blank means use the default device. # Name of audio device file. Blank means use the default device.

Loading…
Cancel
Save