added basic save slot management and connected main menu save to save function (bypassing the save GUI for now)

actorid
Marc Zinnschlag 11 years ago
parent 4c61deca8d
commit 5e64888227

@ -73,12 +73,12 @@ add_openmw_dir (mwmechanics
)
add_openmw_dir (mwstate
statemanagerimp
statemanagerimp charactermanager character
)
add_openmw_dir (mwbase
environment world scriptmanager dialoguemanager journal soundmanager mechanicsmanager
inputmanager windowmanager
inputmanager windowmanager statemanager
)
# Main executable

@ -323,7 +323,7 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
void OMW::Engine::prepareEngine (Settings::Manager & settings)
{
mEnvironment.setStateManager (new MWState::StateManager);
mEnvironment.setStateManager (new MWState::StateManager (mCfgMgr.getUserPath() / "saves"));
Nif::NIFFile::CacheLock cachelock;

@ -1,6 +1,12 @@
#ifndef GAME_MWSTATE_STATEMANAGER_H
#define GAME_MWSTATE_STATEMANAGER_H
namespace MWState
{
struct Slot;
class Character;
}
namespace MWBase
{
/// \brief Interface for game state manager (implemented in MWState)
@ -41,6 +47,14 @@ namespace MWBase
/// \param bypass Skip new game mechanics.
virtual void endGame() = 0;
virtual void saveGame (const MWState::Slot *slot = 0) = 0;
///< Write a saved game to \a slot or create a new slot if \a slot == 0.
///
/// \note Slot must belong to the current character.
virtual MWState::Character *getCurrentCharacter() = 0;
///< Must not be called, if there is no current character.
};
}

@ -61,9 +61,10 @@ namespace MWGui
}
else if (sender == mButtons["savegame"])
{
MWGui::SaveGameDialog* dialog = new MWGui::SaveGameDialog();
dialog->setLoadOrSave(false);
dialog->setVisible(true);
MWBase::Environment::get().getStateManager()->saveGame (0);
// MWGui::SaveGameDialog* dialog = new MWGui::SaveGameDialog();
// dialog->setLoadOrSave(false);
// dialog->setVisible(true);
}
}

@ -0,0 +1,101 @@
#include "character.hpp"
#include <ctime>
#include <sstream>
#include <algorithm>
#include <stdexcept>
#include <boost/filesystem.hpp>
bool MWState::operator< (const Slot& left, const Slot& right)
{
return left.mTimeStamp<right.mTimeStamp;
}
void MWState::Character::addSlot (const boost::filesystem::path& path)
{
Slot slot;
slot.mPath = path;
slot.mTimeStamp = boost::filesystem::last_write_time (path);
/// \todo load profile
mSlots.push_back (slot);
}
void MWState::Character::addSlot (const ESM::SavedGame& profile)
{
Slot slot;
std::ostringstream stream;
stream << mNext++;
slot.mPath = mPath / stream.str();
slot.mProfile = profile;
slot.mTimeStamp = std::time (0);
mSlots.push_back (slot);
}
MWState::Character::Character (const boost::filesystem::path& saves)
: mPath (saves), mNext (0)
{
if (!boost::filesystem::is_directory (mPath))
{
boost::filesystem::create_directories (mPath);
}
else
{
for (boost::filesystem::directory_iterator iter (mPath);
iter!=boost::filesystem::directory_iterator(); ++iter)
{
boost::filesystem::path slotPath = *iter;
try
{
addSlot (slotPath);
}
catch (...) {} // ignoring bad saved game files for now
std::istringstream stream (slotPath.filename().string());
int index = 0;
if ((stream >> index) && index>=mNext)
mNext = index+1;
}
std::sort (mSlots.begin(), mSlots.end());
}
}
const MWState::Slot *MWState::Character::createSlot (const ESM::SavedGame& profile)
{
addSlot (profile);
return &mSlots.back();
}
const MWState::Slot *MWState::Character::updateSlot (const Slot *slot, const ESM::SavedGame& profile)
{
int index = slot - &mSlots[0];
if (index<0 || index>=static_cast<int> (mSlots.size()))
{
// sanity check; not entirely reliable
throw std::logic_error ("slot not found");
}
Slot newSlot = *slot;
newSlot.mProfile = profile;
newSlot.mTimeStamp = std::time (0);
mSlots.erase (mSlots.begin()+index);
mSlots.push_back (newSlot);
return &mSlots.back();
}

@ -0,0 +1,45 @@
#ifndef GAME_STATE_CHARACTER_H
#define GAME_STATE_CHARACTER_H
#include <boost/filesystem/path.hpp>
#include <components/esm/savedgame.hpp>
namespace MWState
{
struct Slot
{
boost::filesystem::path mPath;
ESM::SavedGame mProfile;
std::time_t mTimeStamp;
};
bool operator< (const Slot& left, const Slot& right);
class Character
{
boost::filesystem::path mPath;
std::vector<Slot> mSlots;
int mNext;
void addSlot (const boost::filesystem::path& path);
void addSlot (const ESM::SavedGame& profile);
public:
Character (const boost::filesystem::path& saves);
const Slot *createSlot (const ESM::SavedGame& profile);
///< Create new slot.
///
/// \attention The ownership of the slot is not transferred.
const Slot *updateSlot (const Slot *slot, const ESM::SavedGame& profile);
/// \note Slot must belong to this character.
///
/// \attention The \æ slot pointer will be invalidated by this call.
};
}
#endif

@ -0,0 +1,57 @@
#include "charactermanager.hpp"
#include <sstream>
#include <stdexcept>
#include <boost/filesystem.hpp>
MWState::CharacterManager::CharacterManager (const boost::filesystem::path& saves)
: mPath (saves), mNext (0), mCurrent (0)
{
if (!boost::filesystem::is_directory (mPath))
{
boost::filesystem::create_directories (mPath);
}
else
{
for (boost::filesystem::directory_iterator iter (mPath);
iter!=boost::filesystem::directory_iterator(); ++iter)
{
boost::filesystem::path characterDir = *iter;
if (boost::filesystem::is_directory (characterDir))
{
Character character (characterDir);
mCharacters.push_back (character);
}
std::istringstream stream (characterDir.filename().string());
int index = 0;
if ((stream >> index) && index>=mNext)
mNext = index+1;
}
}
}
MWState::Character *MWState::CharacterManager::getCurrentCharacter()
{
if (!mCurrent)
throw std::logic_error ("no character selected");
return mCurrent;
}
void MWState::CharacterManager::createCharacter()
{
std::ostringstream stream;
stream << mNext++;
boost::filesystem::path path = mPath / stream.str();
mCharacters.push_back (Character (path));
mCurrent = &mCharacters.back();
}

@ -0,0 +1,37 @@
#ifndef GAME_STATE_CHARACTERMANAGER_H
#define GAME_STATE_CHARACTERMANAGER_H
#include <boost/filesystem/path.hpp>
#include "character.hpp"
namespace MWState
{
class CharacterManager
{
boost::filesystem::path mPath;
int mNext;
std::vector<Character> mCharacters;
Character *mCurrent;
private:
CharacterManager (const CharacterManager&);
///< Not implemented
CharacterManager& operator= (const CharacterManager&);
///< Not implemented
public:
CharacterManager (const boost::filesystem::path& saves);
Character *getCurrentCharacter();
///< Must not be called, if there is no current character.
void createCharacter();
///< Create new character within saved game management
};
}
#endif

@ -1,14 +1,16 @@
#include "statemanagerimp.hpp"
#include <components/esm/esmwriter.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/world.hpp"
#include "../mwbase/journal.hpp"
#include "../mwbase/dialoguemanager.hpp"
#include "../mwbase/windowmanager.hpp"
MWState::StateManager::StateManager()
: mQuitRequest (false), mState (State_NoGame)
MWState::StateManager::StateManager (const boost::filesystem::path& saves)
: mQuitRequest (false), mState (State_NoGame), mCharacterManager (saves)
{
}
@ -44,6 +46,8 @@ void MWState::StateManager::newGame (bool bypass)
MWBase::Environment::get().getWindowManager()->setNewGame (true);
}
mCharacterManager.createCharacter();
mState = State_Running;
}
@ -51,3 +55,26 @@ void MWState::StateManager::endGame()
{
mState = State_Ended;
}
void MWState::StateManager::saveGame (const Slot *slot)
{
ESM::SavedGame profile;
/// \todo configure profile
if (!slot)
slot = mCharacterManager.getCurrentCharacter()->createSlot (profile);
else
slot = mCharacterManager.getCurrentCharacter()->updateSlot (slot, profile);
ESM::ESMWriter writer;
// writer.setFormat ();
writer.save (slot->mPath.string());
slot->mProfile.save (writer);
writer.close();
}
MWState::Character *MWState::StateManager::getCurrentCharacter()
{
return mCharacterManager.getCurrentCharacter();
}

@ -3,16 +3,21 @@
#include "../mwbase/statemanager.hpp"
#include <boost/filesystem/path.hpp>
#include "charactermanager.hpp"
namespace MWState
{
class StateManager : public MWBase::StateManager
{
bool mQuitRequest;
State mState;
CharacterManager mCharacterManager;
public:
StateManager();
StateManager (const boost::filesystem::path& saves);
virtual void requestQuit();
@ -26,6 +31,14 @@ namespace MWState
/// \param bypass Skip new game mechanics.
virtual void endGame();
virtual void saveGame (const Slot *slot = 0);
///< Write a saved game to \a slot or create a new slot if \a slot == 0.
///
/// \note Slot must belong to the current character.
virtual Character *getCurrentCharacter();
///< Must not be called, if there is no current character.
};
}

Loading…
Cancel
Save