2013-11-16 09:31:46 +00:00
# include "statemanagerimp.hpp"
2013-11-19 14:38:26 +00:00
# include <components/esm/esmwriter.hpp>
2013-11-21 11:24:24 +00:00
# include <components/esm/esmreader.hpp>
2014-01-16 11:03:23 +00:00
# include <components/esm/cellid.hpp>
# include <components/esm/loadcell.hpp>
2013-11-19 14:38:26 +00:00
2014-01-27 12:27:42 +00:00
# include <components/misc/stringops.hpp>
2013-11-26 09:37:58 +00:00
# include <components/settings/settings.hpp>
2014-01-24 16:49:16 +00:00
# include <OgreImage.h>
2014-05-19 11:43:25 +00:00
# include <boost/filesystem/fstream.hpp>
2013-11-16 11:22:28 +00:00
# include "../mwbase/environment.hpp"
# include "../mwbase/world.hpp"
# include "../mwbase/journal.hpp"
# include "../mwbase/dialoguemanager.hpp"
# include "../mwbase/windowmanager.hpp"
2013-12-07 12:17:28 +00:00
# include "../mwbase/mechanicsmanager.hpp"
2013-12-12 12:15:38 +00:00
# include "../mwbase/scriptmanager.hpp"
2014-01-21 13:13:13 +00:00
# include "../mwbase/soundmanager.hpp"
2014-03-09 02:34:49 +00:00
# include "../mwbase/inputmanager.hpp"
2013-11-16 11:22:28 +00:00
2013-11-21 09:53:42 +00:00
# include "../mwworld/player.hpp"
# include "../mwworld/class.hpp"
2014-02-23 19:11:05 +00:00
# include "../mwworld/cellstore.hpp"
2014-12-19 10:26:54 +00:00
# include "../mwworld/esmstore.hpp"
2014-03-27 02:08:31 +00:00
# include "../mwworld/inventorystore.hpp"
2013-11-21 09:53:42 +00:00
# include "../mwmechanics/npcstats.hpp"
2014-04-29 17:56:33 +00:00
# include "../mwmechanics/creaturestats.hpp"
2013-11-21 09:53:42 +00:00
2013-12-12 12:15:38 +00:00
# include "../mwscript/globalscripts.hpp"
2014-01-23 10:29:40 +00:00
void MWState : : StateManager : : cleanup ( bool force )
2013-11-28 10:22:34 +00:00
{
2014-01-23 10:29:40 +00:00
if ( mState ! = State_NoGame | | force )
2013-11-28 10:22:34 +00:00
{
2014-01-21 13:13:13 +00:00
MWBase : : Environment : : get ( ) . getSoundManager ( ) - > clear ( ) ;
2013-11-28 10:22:34 +00:00
MWBase : : Environment : : get ( ) . getDialogueManager ( ) - > clear ( ) ;
MWBase : : Environment : : get ( ) . getJournal ( ) - > clear ( ) ;
2013-12-12 12:15:38 +00:00
MWBase : : Environment : : get ( ) . getScriptManager ( ) - > getGlobalScripts ( ) . clear ( ) ;
2013-12-05 11:49:25 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > clear ( ) ;
2014-01-25 12:34:56 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > clear ( ) ;
2014-03-09 02:34:49 +00:00
MWBase : : Environment : : get ( ) . getInputManager ( ) - > clear ( ) ;
2014-06-12 23:24:58 +00:00
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > clear ( ) ;
2013-12-12 12:15:38 +00:00
2013-11-28 10:22:34 +00:00
mState = State_NoGame ;
mCharacterManager . clearCurrentCharacter ( ) ;
mTimePlayed = 0 ;
2014-04-29 17:56:33 +00:00
MWMechanics : : CreatureStats : : cleanup ( ) ;
2013-11-28 10:22:34 +00:00
}
}
2014-01-27 12:27:42 +00:00
std : : map < int , int > MWState : : StateManager : : buildContentFileIndexMap ( const ESM : : ESMReader & reader )
const
{
const std : : vector < std : : string > & current =
MWBase : : Environment : : get ( ) . getWorld ( ) - > getContentFiles ( ) ;
const std : : vector < ESM : : Header : : MasterData > & prev = reader . getGameFiles ( ) ;
std : : map < int , int > map ;
for ( int iPrev = 0 ; iPrev < static_cast < int > ( prev . size ( ) ) ; + + iPrev )
{
std : : string id = Misc : : StringUtils : : lowerCase ( prev [ iPrev ] . name ) ;
for ( int iCurrent = 0 ; iCurrent < static_cast < int > ( current . size ( ) ) ; + + iCurrent )
if ( id = = Misc : : StringUtils : : lowerCase ( current [ iCurrent ] ) )
{
map . insert ( std : : make_pair ( iPrev , iCurrent ) ) ;
break ;
}
}
return map ;
}
2013-11-25 12:00:05 +00:00
MWState : : StateManager : : StateManager ( const boost : : filesystem : : path & saves , const std : : string & game )
2013-12-19 20:08:34 +00:00
: mQuitRequest ( false ) , mAskLoadRecent ( false ) , mState ( State_NoGame ) , mCharacterManager ( saves , game ) , mTimePlayed ( 0 )
2013-11-16 09:31:46 +00:00
{
2013-11-16 10:07:23 +00:00
}
void MWState : : StateManager : : requestQuit ( )
{
mQuitRequest = true ;
}
bool MWState : : StateManager : : hasQuitRequest ( ) const
{
return mQuitRequest ;
2013-11-16 11:22:28 +00:00
}
2013-12-19 20:08:34 +00:00
void MWState : : StateManager : : askLoadRecent ( )
{
if ( MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getMode ( ) = = MWGui : : GM_MainMenu )
return ;
if ( ! mAskLoadRecent )
{
2013-12-20 12:04:59 +00:00
if ( getCurrentCharacter ( ) - > begin ( ) = = getCurrentCharacter ( ) - > end ( ) ) //no saves
2013-12-19 20:08:34 +00:00
{
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > pushGuiMode ( MWGui : : GM_MainMenu ) ;
}
else
{
MWState : : Slot lastSave = * getCurrentCharacter ( ) - > begin ( ) ;
std : : vector < std : : string > buttons ;
2014-01-25 12:34:56 +00:00
buttons . push_back ( " #{sYes} " ) ;
buttons . push_back ( " #{sNo} " ) ;
2013-12-20 12:04:59 +00:00
std : : string tag ( " %s " ) ;
std : : string message = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getGameSettingString ( " sLoadLastSaveMsg " , tag ) ;
size_t pos = message . find ( tag ) ;
message . replace ( pos , tag . length ( ) , lastSave . mProfile . mDescription ) ;
2015-01-10 22:21:39 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > interactiveMessageBox ( message , buttons ) ;
2013-12-19 20:08:34 +00:00
mAskLoadRecent = true ;
}
}
}
2013-11-18 14:15:47 +00:00
MWState : : StateManager : : State MWState : : StateManager : : getState ( ) const
2013-11-16 11:22:28 +00:00
{
2013-11-18 14:15:47 +00:00
return mState ;
2013-11-16 11:22:28 +00:00
}
void MWState : : StateManager : : newGame ( bool bypass )
{
2013-11-28 10:22:34 +00:00
cleanup ( ) ;
2013-11-16 11:22:28 +00:00
if ( ! bypass )
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > setNewGame ( true ) ;
2014-07-25 10:17:15 +00:00
MWBase : : Environment : : get ( ) . getScriptManager ( ) - > getGlobalScripts ( ) . addStartup ( ) ;
2014-07-25 10:23:18 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > startNewGame ( bypass ) ;
2013-11-18 14:15:47 +00:00
mState = State_Running ;
2013-11-16 11:22:28 +00:00
}
2013-11-18 14:38:08 +00:00
void MWState : : StateManager : : endGame ( )
{
mState = State_Ended ;
}
2013-11-19 14:38:26 +00:00
2013-11-24 14:19:56 +00:00
void MWState : : StateManager : : saveGame ( const std : : string & description , const Slot * slot )
2013-11-19 14:38:26 +00:00
{
2014-06-02 12:46:41 +00:00
try
{
ESM : : SavedGame profile ;
2013-11-19 14:38:26 +00:00
2014-06-02 12:46:41 +00:00
MWBase : : World & world = * MWBase : : Environment : : get ( ) . getWorld ( ) ;
2013-11-21 09:53:42 +00:00
2014-06-02 12:46:41 +00:00
MWWorld : : Ptr player = world . getPlayerPtr ( ) ;
2013-11-21 09:53:42 +00:00
2014-06-02 12:46:41 +00:00
profile . mContentFiles = world . getContentFiles ( ) ;
2013-11-25 12:00:05 +00:00
2014-09-13 00:58:01 +00:00
profile . mPlayerName = player . get < ESM : : NPC > ( ) - > mBase - > mName ;
2014-06-02 12:46:41 +00:00
profile . mPlayerLevel = player . getClass ( ) . getNpcStats ( player ) . getLevel ( ) ;
2014-03-27 21:32:42 +00:00
2014-06-02 12:46:41 +00:00
std : : string classId = player . get < ESM : : NPC > ( ) - > mBase - > mClass ;
if ( world . getStore ( ) . get < ESM : : Class > ( ) . isDynamic ( classId ) )
profile . mPlayerClassName = world . getStore ( ) . get < ESM : : Class > ( ) . find ( classId ) - > mName ;
else
profile . mPlayerClassId = classId ;
profile . mPlayerCell = world . getCellName ( ) ;
profile . mInGameTime . mGameHour = world . getTimeStamp ( ) . getHour ( ) ;
profile . mInGameTime . mDay = world . getDay ( ) ;
profile . mInGameTime . mMonth = world . getMonth ( ) ;
profile . mInGameTime . mYear = world . getYear ( ) ;
profile . mTimePlayed = mTimePlayed ;
profile . mDescription = description ;
int screenshotW = 259 * 2 , screenshotH = 133 * 2 ; // *2 to get some nice antialiasing
Ogre : : Image screenshot ;
world . screenshot ( screenshot , screenshotW , screenshotH ) ;
Ogre : : DataStreamPtr encoded = screenshot . encode ( " jpg " ) ;
profile . mScreenshot . resize ( encoded - > size ( ) ) ;
encoded - > read ( & profile . mScreenshot [ 0 ] , encoded - > size ( ) ) ;
if ( ! slot )
2014-06-09 22:22:00 +00:00
slot = getCurrentCharacter ( ) - > createSlot ( profile ) ;
2014-06-02 12:46:41 +00:00
else
2014-06-09 22:22:00 +00:00
slot = getCurrentCharacter ( ) - > updateSlot ( slot , profile ) ;
2013-11-19 14:38:26 +00:00
2014-06-02 12:46:41 +00:00
boost : : filesystem : : ofstream stream ( slot - > mPath , std : : ios : : binary ) ;
2014-01-27 12:27:42 +00:00
2014-06-02 12:46:41 +00:00
ESM : : ESMWriter writer ;
2014-01-27 12:27:42 +00:00
2014-06-02 12:46:41 +00:00
const std : : vector < std : : string > & current =
MWBase : : Environment : : get ( ) . getWorld ( ) - > getContentFiles ( ) ;
for ( std : : vector < std : : string > : : const_iterator iter ( current . begin ( ) ) ; iter ! = current . end ( ) ;
+ + iter )
writer . addMaster ( * iter , 0 ) ; // not using the size information anyway -> use value of 0
writer . setFormat ( ESM : : Header : : CurrentFormat ) ;
2014-06-24 22:11:25 +00:00
// all unused
writer . setVersion ( 0 ) ;
writer . setType ( 0 ) ;
writer . setAuthor ( " " ) ;
writer . setDescription ( " " ) ;
2014-06-02 12:46:41 +00:00
int recordCount = 1 // saved game header
+ MWBase : : Environment : : get ( ) . getJournal ( ) - > countSavedGameRecords ( )
+ MWBase : : Environment : : get ( ) . getWorld ( ) - > countSavedGameRecords ( )
+ MWBase : : Environment : : get ( ) . getScriptManager ( ) - > getGlobalScripts ( ) . countSavedGameRecords ( )
+ MWBase : : Environment : : get ( ) . getDialogueManager ( ) - > countSavedGameRecords ( )
2014-06-12 23:24:58 +00:00
+ MWBase : : Environment : : get ( ) . getWindowManager ( ) - > countSavedGameRecords ( )
+ MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > countSavedGameRecords ( ) ;
2014-06-02 12:46:41 +00:00
writer . setRecordCount ( recordCount ) ;
2014-01-27 12:27:42 +00:00
2014-06-02 12:46:41 +00:00
writer . save ( stream ) ;
2014-01-27 12:27:42 +00:00
2014-06-02 12:46:41 +00:00
Loading : : Listener & listener = * MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) ;
listener . setProgressRange ( recordCount ) ;
listener . setLabel ( " #{sNotifyMessage4} " ) ;
2013-12-03 13:28:46 +00:00
2014-06-02 12:46:41 +00:00
Loading : : ScopedLoad load ( & listener ) ;
2013-12-03 13:28:46 +00:00
2014-06-02 12:46:41 +00:00
writer . startRecord ( ESM : : REC_SAVE ) ;
slot - > mProfile . save ( writer ) ;
writer . endRecord ( ESM : : REC_SAVE ) ;
listener . increaseProgress ( ) ;
2014-04-28 09:29:57 +00:00
2014-06-02 12:46:41 +00:00
MWBase : : Environment : : get ( ) . getJournal ( ) - > write ( writer , listener ) ;
MWBase : : Environment : : get ( ) . getDialogueManager ( ) - > write ( writer , listener ) ;
MWBase : : Environment : : get ( ) . getWorld ( ) - > write ( writer , listener ) ;
MWBase : : Environment : : get ( ) . getScriptManager ( ) - > getGlobalScripts ( ) . write ( writer , listener ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > write ( writer , listener ) ;
2014-06-12 23:24:58 +00:00
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > write ( writer , listener ) ;
2014-04-28 09:29:57 +00:00
2014-06-02 12:46:41 +00:00
// Ensure we have written the number of records that was estimated
if ( writer . getRecordCount ( ) ! = recordCount + 1 ) // 1 extra for TES3 record
std : : cerr < < " Warning: number of written savegame records does not match. Estimated: " < < recordCount + 1 < < " , written: " < < writer . getRecordCount ( ) < < std : : endl ;
2014-04-28 09:29:57 +00:00
2014-06-02 12:46:41 +00:00
writer . close ( ) ;
2013-11-28 10:22:34 +00:00
2014-06-07 15:48:40 +00:00
if ( stream . fail ( ) )
throw std : : runtime_error ( " Write operation failed " ) ;
2014-06-02 12:46:41 +00:00
Settings : : Manager : : setString ( " character " , " Saves " ,
slot - > mPath . parent_path ( ) . filename ( ) . string ( ) ) ;
}
catch ( const std : : exception & e )
{
std : : stringstream error ;
error < < " Failed to save game: " < < e . what ( ) ;
2013-11-28 10:22:34 +00:00
2014-06-02 12:46:41 +00:00
std : : cerr < < error . str ( ) < < std : : endl ;
2013-11-26 09:37:58 +00:00
2014-06-02 12:46:41 +00:00
std : : vector < std : : string > buttons ;
buttons . push_back ( " #{sOk} " ) ;
2015-01-10 22:21:39 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > interactiveMessageBox ( error . str ( ) , buttons ) ;
2014-06-07 15:48:40 +00:00
// If no file was written, clean up the slot
if ( slot & & ! boost : : filesystem : : exists ( slot - > mPath ) )
2014-06-09 22:22:00 +00:00
getCurrentCharacter ( ) - > deleteSlot ( slot ) ;
2014-06-02 12:46:41 +00:00
}
2013-11-19 14:38:26 +00:00
}
2014-04-24 08:14:17 +00:00
void MWState : : StateManager : : quickSave ( std : : string name )
{
2014-05-02 09:20:43 +00:00
if ( ! ( mState = = State_Running & &
MWBase : : Environment : : get ( ) . getWorld ( ) - > getGlobalInt ( " chargenstate " ) = = - 1 // char gen
& & MWBase : : Environment : : get ( ) . getWindowManager ( ) - > isSavingAllowed ( ) ) )
2014-04-25 06:39:40 +00:00
{
//You can not save your game right now
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > messageBox ( " #{sSaveGameDenied} " ) ;
2014-04-24 08:14:17 +00:00
return ;
2014-04-24 07:06:36 +00:00
}
2014-04-24 07:54:47 +00:00
2014-04-24 08:14:17 +00:00
const Slot * slot = NULL ;
Character * mCurrentCharacter = getCurrentCharacter ( true ) ; //Get current character
//Find quicksave slot
for ( Character : : SlotIterator it = mCurrentCharacter - > begin ( ) ; it ! = mCurrentCharacter - > end ( ) ; + + it )
{
if ( it - > mProfile . mDescription = = name )
slot = & * it ;
2014-04-24 07:06:36 +00:00
}
2014-04-24 08:14:17 +00:00
saveGame ( name , slot ) ;
2014-04-24 07:06:36 +00:00
}
2015-01-07 02:03:56 +00:00
void MWState : : StateManager : : loadGame ( const std : : string & filepath )
{
for ( CharacterIterator it = mCharacterManager . begin ( ) ; it ! = mCharacterManager . end ( ) ; + + it )
{
const MWState : : Character & character = * it ;
for ( MWState : : Character : : SlotIterator slotIt = character . begin ( ) ; slotIt ! = character . end ( ) ; + + slotIt )
{
const MWState : : Slot & slot = * slotIt ;
if ( slot . mPath = = boost : : filesystem : : path ( filepath ) )
{
loadGame ( & character , slot . mPath . string ( ) ) ;
return ;
}
}
}
// have to peek into the save file to get the player name
ESM : : ESMReader reader ;
reader . open ( filepath ) ;
if ( reader . getFormat ( ) > ESM : : Header : : CurrentFormat )
return ; // format is too new -> ignore
if ( reader . getRecName ( ) ! = ESM : : REC_SAVE )
return ; // invalid save file -> ignore
reader . getRecHeader ( ) ;
ESM : : SavedGame profile ;
profile . load ( reader ) ;
reader . close ( ) ;
MWState : : Character * character = mCharacterManager . getCurrentCharacter ( true , profile . mPlayerName ) ;
loadGame ( character , filepath ) ;
mTimePlayed = profile . mTimePlayed ;
}
void MWState : : StateManager : : loadGame ( const Character * character , const std : : string & filepath )
2013-11-21 11:24:24 +00:00
{
2014-01-23 10:29:40 +00:00
try
2013-12-03 13:28:46 +00:00
{
2014-01-23 10:29:40 +00:00
cleanup ( ) ;
2013-12-07 12:17:28 +00:00
2014-01-23 10:29:40 +00:00
ESM : : ESMReader reader ;
2015-01-07 02:03:56 +00:00
reader . open ( filepath ) ;
2013-12-15 15:16:50 +00:00
2014-01-27 12:27:42 +00:00
std : : map < int , int > contentFileMap = buildContentFileIndexMap ( reader ) ;
2014-04-28 09:29:57 +00:00
Loading : : Listener & listener = * MWBase : : Environment : : get ( ) . getWindowManager ( ) - > getLoadingScreen ( ) ;
2014-04-28 13:00:52 +00:00
listener . setProgressRange ( reader . getRecordCount ( ) ) ;
2014-04-28 09:29:57 +00:00
listener . setLabel ( " #{sLoadingMessage14} " ) ;
Loading : : ScopedLoad load ( & listener ) ;
2014-01-23 10:29:40 +00:00
while ( reader . hasMoreRecs ( ) )
{
ESM : : NAME n = reader . getRecName ( ) ;
reader . getRecHeader ( ) ;
switch ( n . val )
{
case ESM : : REC_SAVE :
2015-01-07 02:03:56 +00:00
{
ESM : : SavedGame profile ;
profile . load ( reader ) ;
2015-01-10 22:58:55 +00:00
if ( ! verifyProfile ( profile ) )
{
cleanup ( true ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > pushGuiMode ( MWGui : : GM_MainMenu ) ;
return ;
}
2015-01-07 02:03:56 +00:00
mTimePlayed = profile . mTimePlayed ;
}
2014-01-23 10:29:40 +00:00
break ;
case ESM : : REC_JOUR :
case ESM : : REC_QUES :
MWBase : : Environment : : get ( ) . getJournal ( ) - > readRecord ( reader , n . val ) ;
break ;
2014-02-16 11:54:27 +00:00
case ESM : : REC_DIAS :
MWBase : : Environment : : get ( ) . getDialogueManager ( ) - > readRecord ( reader , n . val ) ;
break ;
2014-01-23 10:29:40 +00:00
case ESM : : REC_ALCH :
case ESM : : REC_ARMO :
case ESM : : REC_BOOK :
case ESM : : REC_CLAS :
case ESM : : REC_CLOT :
case ESM : : REC_ENCH :
case ESM : : REC_NPC_ :
case ESM : : REC_SPEL :
case ESM : : REC_WEAP :
case ESM : : REC_GLOB :
case ESM : : REC_PLAY :
case ESM : : REC_CSTA :
2014-03-20 06:25:52 +00:00
case ESM : : REC_WTHR :
2014-05-10 22:32:22 +00:00
case ESM : : REC_DYNA :
2014-05-14 07:47:49 +00:00
case ESM : : REC_ACTC :
2014-05-17 03:21:17 +00:00
case ESM : : REC_PROJ :
case ESM : : REC_MPRJ :
2014-09-21 11:37:20 +00:00
case ESM : : REC_ENAB :
2014-12-17 00:05:32 +00:00
case ESM : : REC_LEVC :
case ESM : : REC_LEVI :
2015-01-06 18:29:33 +00:00
case ESM : : REC_CAM_ :
2014-01-23 10:29:40 +00:00
2014-01-27 12:27:42 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > readRecord ( reader , n . val , contentFileMap ) ;
2014-01-23 10:29:40 +00:00
break ;
case ESM : : REC_GSCR :
MWBase : : Environment : : get ( ) . getScriptManager ( ) - > getGlobalScripts ( ) . readRecord ( reader , n . val ) ;
break ;
2014-01-25 17:20:17 +00:00
case ESM : : REC_GMAP :
2014-05-01 19:16:32 +00:00
case ESM : : REC_KEYS :
2014-05-12 19:04:02 +00:00
case ESM : : REC_ASPL :
2014-08-17 03:45:35 +00:00
case ESM : : REC_MARK :
2014-05-12 19:04:02 +00:00
2014-01-25 17:20:17 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > readRecord ( reader , n . val ) ;
break ;
2014-06-12 23:24:58 +00:00
case ESM : : REC_DCOU :
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > readRecord ( reader , n . val ) ;
break ;
2014-01-23 10:29:40 +00:00
default :
// ignore invalid records
2014-08-17 03:45:35 +00:00
std : : cerr < < " Ignoring unknown record: " < < n . name < < std : : endl ;
2014-01-23 10:29:40 +00:00
reader . skipRecord ( ) ;
}
2014-04-28 09:29:57 +00:00
listener . increaseProgress ( ) ;
2013-12-03 13:28:46 +00:00
}
2013-11-21 11:24:24 +00:00
2014-01-23 10:29:40 +00:00
mCharacterManager . setCurrentCharacter ( character ) ;
2013-11-21 19:24:58 +00:00
2014-01-23 10:29:40 +00:00
mState = State_Running ;
2013-11-26 09:37:58 +00:00
2014-01-23 10:29:40 +00:00
Settings : : Manager : : setString ( " character " , " Saves " ,
2015-01-07 02:03:56 +00:00
character - > getPath ( ) . filename ( ) . string ( ) ) ;
2013-12-05 13:22:08 +00:00
2014-01-25 12:34:56 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > setNewGame ( false ) ;
2014-01-23 10:29:40 +00:00
MWBase : : Environment : : get ( ) . getWorld ( ) - > setupPlayer ( ) ;
MWBase : : Environment : : get ( ) . getWorld ( ) - > renderPlayer ( ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > updatePlayer ( ) ;
MWBase : : Environment : : get ( ) . getMechanicsManager ( ) - > playerLoaded ( ) ;
2013-12-07 12:17:28 +00:00
2014-03-07 05:11:00 +00:00
MWWorld : : Ptr ptr = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
2014-04-24 07:06:36 +00:00
2014-02-21 10:35:46 +00:00
ESM : : CellId cellId = ptr . getCell ( ) - > getCell ( ) - > getCellId ( ) ;
2014-01-16 11:03:23 +00:00
2014-05-17 03:21:17 +00:00
// Use detectWorldSpaceChange=false, otherwise some of the data we just loaded would be cleared again
MWBase : : Environment : : get ( ) . getWorld ( ) - > changeToCell ( cellId , ptr . getRefData ( ) . getPosition ( ) , false ) ;
2015-01-06 18:29:33 +00:00
// Vanilla MW will restart startup scripts when a save game is loaded. This is unintuive,
// but some mods may be using it as a reload detector.
2014-07-25 10:17:15 +00:00
MWBase : : Environment : : get ( ) . getScriptManager ( ) - > getGlobalScripts ( ) . addStartup ( ) ;
2014-05-17 03:21:17 +00:00
// Do not trigger erroneous cellChanged events
MWBase : : Environment : : get ( ) . getWorld ( ) - > markCellAsUnchanged ( ) ;
2014-01-23 10:29:40 +00:00
}
catch ( const std : : exception & e )
{
2014-06-02 12:46:41 +00:00
std : : stringstream error ;
error < < " Failed to load saved game: " < < e . what ( ) ;
std : : cerr < < error . str ( ) < < std : : endl ;
2014-01-23 10:29:40 +00:00
cleanup ( true ) ;
2014-05-20 15:11:26 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > pushGuiMode ( MWGui : : GM_MainMenu ) ;
2014-06-02 12:46:41 +00:00
std : : vector < std : : string > buttons ;
buttons . push_back ( " #{sOk} " ) ;
2015-01-10 22:21:39 +00:00
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > interactiveMessageBox ( error . str ( ) , buttons ) ;
2014-01-23 10:29:40 +00:00
}
2013-11-21 11:24:24 +00:00
}
2014-04-24 08:14:17 +00:00
void MWState : : StateManager : : quickLoad ( )
{
if ( Character * mCurrentCharacter = getCurrentCharacter ( false ) )
if ( const MWState : : Slot * slot = & * mCurrentCharacter - > begin ( ) ) //Get newest save
2015-01-07 02:03:56 +00:00
loadGame ( mCurrentCharacter , slot - > mPath . string ( ) ) ;
2014-04-24 07:14:47 +00:00
}
2014-04-28 18:57:45 +00:00
void MWState : : StateManager : : deleteGame ( const MWState : : Character * character , const MWState : : Slot * slot )
{
mCharacterManager . deleteSlot ( character , slot ) ;
}
2013-11-24 15:58:41 +00:00
MWState : : Character * MWState : : StateManager : : getCurrentCharacter ( bool create )
2013-11-19 14:38:26 +00:00
{
2014-06-09 22:22:00 +00:00
MWWorld : : Ptr player = MWBase : : Environment : : get ( ) . getWorld ( ) - > getPlayerPtr ( ) ;
2014-09-13 00:58:01 +00:00
std : : string name = player . get < ESM : : NPC > ( ) - > mBase - > mName ;
2014-06-09 22:22:00 +00:00
return mCharacterManager . getCurrentCharacter ( create , name ) ;
2013-11-21 10:10:18 +00:00
}
MWState : : StateManager : : CharacterIterator MWState : : StateManager : : characterBegin ( )
{
return mCharacterManager . begin ( ) ;
}
MWState : : StateManager : : CharacterIterator MWState : : StateManager : : characterEnd ( )
{
return mCharacterManager . end ( ) ;
}
2013-11-28 08:33:50 +00:00
void MWState : : StateManager : : update ( float duration )
{
mTimePlayed + = duration ;
2014-01-25 21:20:46 +00:00
// Note: It would be nicer to trigger this from InputManager, i.e. the very beginning of the frame update.
if ( mAskLoadRecent )
{
int iButton = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > readPressedButton ( ) ;
2014-06-09 22:22:00 +00:00
MWState : : Character * curCharacter = getCurrentCharacter ( false ) ;
if ( iButton = = 0 & & curCharacter )
2014-01-25 21:20:46 +00:00
{
mAskLoadRecent = false ;
//Load last saved game for current character
2014-06-09 22:22:00 +00:00
2014-01-25 21:20:46 +00:00
MWState : : Slot lastSave = * curCharacter - > begin ( ) ;
2015-01-07 02:03:56 +00:00
loadGame ( curCharacter , lastSave . mPath . string ( ) ) ;
2014-01-25 21:20:46 +00:00
}
else if ( iButton = = 1 )
{
mAskLoadRecent = false ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > pushGuiMode ( MWGui : : GM_MainMenu ) ;
}
}
2013-11-28 08:33:50 +00:00
}
2015-01-10 22:58:55 +00:00
bool MWState : : StateManager : : verifyProfile ( const ESM : : SavedGame & profile ) const
{
const std : : vector < std : : string > & selectedContentFiles = MWBase : : Environment : : get ( ) . getWorld ( ) - > getContentFiles ( ) ;
bool notFound = false ;
for ( std : : vector < std : : string > : : const_iterator it = profile . mContentFiles . begin ( ) ;
it ! = profile . mContentFiles . end ( ) ; + + it )
{
if ( std : : find ( selectedContentFiles . begin ( ) , selectedContentFiles . end ( ) , * it )
= = selectedContentFiles . end ( ) )
{
2015-01-11 14:12:47 +00:00
std : : cerr < < " Savegame dependency " < < * it < < " is missing. " < < std : : endl ;
2015-01-10 22:58:55 +00:00
notFound = true ;
}
}
if ( notFound )
{
std : : vector < std : : string > buttons ;
buttons . push_back ( " #{sYes} " ) ;
buttons . push_back ( " #{sNo} " ) ;
MWBase : : Environment : : get ( ) . getWindowManager ( ) - > interactiveMessageBox ( " #{sMissingMastersMsg} " , buttons , true ) ;
int selectedButton = MWBase : : Environment : : get ( ) . getWindowManager ( ) - > readPressedButton ( ) ;
if ( selectedButton = = 1 | | selectedButton = = - 1 )
return false ;
}
return true ;
}