mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-06-06 11:11:37 +00:00
loading/saving of some player state (cell/coordinates and some other bits)
This commit is contained in:
parent
d8d4f1a15e
commit
c300cd9375
10 changed files with 210 additions and 11 deletions
|
@ -37,6 +37,7 @@ namespace ESM
|
||||||
struct Potion;
|
struct Potion;
|
||||||
struct Spell;
|
struct Spell;
|
||||||
struct NPC;
|
struct NPC;
|
||||||
|
struct CellId;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
|
@ -105,12 +106,14 @@ namespace MWBase
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||||
|
|
||||||
virtual OEngine::Render::Fader* getFader() = 0;
|
virtual OEngine::Render::Fader* getFader() = 0;
|
||||||
///< \ŧodo remove this function. Rendering details should not be exposed.
|
///< \todo remove this function. Rendering details should not be exposed.
|
||||||
|
|
||||||
virtual MWWorld::CellStore *getExterior (int x, int y) = 0;
|
virtual MWWorld::CellStore *getExterior (int x, int y) = 0;
|
||||||
|
|
||||||
virtual MWWorld::CellStore *getInterior (const std::string& name) = 0;
|
virtual MWWorld::CellStore *getInterior (const std::string& name) = 0;
|
||||||
|
|
||||||
|
virtual MWWorld::CellStore *getCell (const ESM::CellId& id) = 0;
|
||||||
|
|
||||||
virtual void useDeathCamera() = 0;
|
virtual void useDeathCamera() = 0;
|
||||||
|
|
||||||
virtual void setWaterHeight(const float height) = 0;
|
virtual void setWaterHeight(const float height) = 0;
|
||||||
|
@ -236,6 +239,8 @@ namespace MWBase
|
||||||
virtual void changeToExteriorCell (const ESM::Position& position) = 0;
|
virtual void changeToExteriorCell (const ESM::Position& position) = 0;
|
||||||
///< Move to exterior cell.
|
///< Move to exterior cell.
|
||||||
|
|
||||||
|
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position) = 0;
|
||||||
|
|
||||||
virtual const ESM::Cell *getExterior (const std::string& cellName) const = 0;
|
virtual const ESM::Cell *getExterior (const std::string& cellName) const = 0;
|
||||||
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/esmreader.hpp>
|
#include <components/esm/esmreader.hpp>
|
||||||
|
#include <components/esm/cellid.hpp>
|
||||||
|
#include <components/esm/loadcell.hpp>
|
||||||
|
|
||||||
#include <components/settings/settings.hpp>
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
|
@ -216,6 +218,7 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
|
||||||
case ESM::REC_SPEL:
|
case ESM::REC_SPEL:
|
||||||
case ESM::REC_WEAP:
|
case ESM::REC_WEAP:
|
||||||
case ESM::REC_GLOB:
|
case ESM::REC_GLOB:
|
||||||
|
case ESM::REC_PLAY:
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->readRecord (reader, n.val);
|
MWBase::Environment::get().getWorld()->readRecord (reader, n.val);
|
||||||
break;
|
break;
|
||||||
|
@ -245,11 +248,11 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
|
||||||
MWBase::Environment::get().getWindowManager()->updatePlayer();
|
MWBase::Environment::get().getWindowManager()->updatePlayer();
|
||||||
MWBase::Environment::get().getMechanicsManager()->playerLoaded();
|
MWBase::Environment::get().getMechanicsManager()->playerLoaded();
|
||||||
|
|
||||||
// for testing purpose only
|
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
|
||||||
ESM::Position pos;
|
|
||||||
pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;
|
ESM::CellId cellId = ptr.getCell()->mCell->getCellId();
|
||||||
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
|
|
||||||
MWBase::Environment::get().getWorld()->changeToExteriorCell (pos);
|
MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
MWState::Character *MWState::StateManager::getCurrentCharacter (bool create)
|
MWState::Character *MWState::StateManager::getCurrentCharacter (bool create)
|
||||||
|
|
21
apps/openmw/mwworld/livecellref.cpp
Normal file
21
apps/openmw/mwworld/livecellref.cpp
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
|
||||||
|
#include "livecellref.hpp"
|
||||||
|
|
||||||
|
#include <components/esm/objectstate.hpp>
|
||||||
|
|
||||||
|
void MWWorld::LiveCellRefBase::loadImp (const ESM::ObjectState& state)
|
||||||
|
{
|
||||||
|
mRef = state.mRef;
|
||||||
|
mData = RefData (state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MWWorld::LiveCellRefBase::saveImp (ESM::ObjectState& state) const
|
||||||
|
{
|
||||||
|
state.mRef = mRef;
|
||||||
|
mData.write (state);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MWWorld::LiveCellRefBase::checkStateImp (const ESM::ObjectState& state)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -7,6 +7,11 @@
|
||||||
|
|
||||||
#include "refdata.hpp"
|
#include "refdata.hpp"
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ObjectState;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
class Ptr;
|
class Ptr;
|
||||||
|
@ -29,6 +34,24 @@ namespace MWWorld
|
||||||
LiveCellRefBase(std::string type, const ESM::CellRef &cref=ESM::CellRef());
|
LiveCellRefBase(std::string type, const ESM::CellRef &cref=ESM::CellRef());
|
||||||
/* Need this for the class to be recognized as polymorphic */
|
/* Need this for the class to be recognized as polymorphic */
|
||||||
virtual ~LiveCellRefBase() { }
|
virtual ~LiveCellRefBase() { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void loadImp (const ESM::ObjectState& state);
|
||||||
|
///< Load state into a LiveCellRef, that has already been initialised with base and
|
||||||
|
/// class.
|
||||||
|
///
|
||||||
|
/// \attention Must not be called with an invalid \a state.
|
||||||
|
|
||||||
|
void saveImp (ESM::ObjectState& state) const;
|
||||||
|
///< Save LiveCellRef state into \a state.
|
||||||
|
|
||||||
|
static bool checkStateImp (const ESM::ObjectState& state);
|
||||||
|
///< Check if state is valid and report errors.
|
||||||
|
///
|
||||||
|
/// \return Valid?
|
||||||
|
///
|
||||||
|
/// \note Does not check if the RefId exists.
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator== (const LiveCellRefBase& cellRef, const ESM::CellRef::RefNum refNum)
|
inline bool operator== (const LiveCellRefBase& cellRef, const ESM::CellRef::RefNum refNum)
|
||||||
|
@ -55,7 +78,41 @@ namespace MWWorld
|
||||||
|
|
||||||
// The object that this instance is based on.
|
// The object that this instance is based on.
|
||||||
const X* mBase;
|
const X* mBase;
|
||||||
|
|
||||||
|
void load (const ESM::ObjectState& state);
|
||||||
|
///< Load state into a LiveCellRef, that has already been initialised with base and class.
|
||||||
|
///
|
||||||
|
/// \attention Must not be called with an invalid \a state.
|
||||||
|
|
||||||
|
void save (ESM::ObjectState& state) const;
|
||||||
|
///< Save LiveCellRef state into \a state.
|
||||||
|
|
||||||
|
static bool checkState (const ESM::ObjectState& state);
|
||||||
|
///< Check if state is valid and report errors.
|
||||||
|
///
|
||||||
|
/// \return Valid?
|
||||||
|
///
|
||||||
|
/// \note Does not check if the RefId exists.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <typename X>
|
||||||
|
void LiveCellRef<X>::load (const ESM::ObjectState& state)
|
||||||
|
{
|
||||||
|
loadImp (state);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename X>
|
||||||
|
void LiveCellRef<X>::save (ESM::ObjectState& state) const
|
||||||
|
{
|
||||||
|
saveImp (state);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename X>
|
||||||
|
bool LiveCellRef<X>::checkState (const ESM::ObjectState& state)
|
||||||
|
{
|
||||||
|
return checkStateImp (state);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,13 @@
|
||||||
|
|
||||||
#include "player.hpp"
|
#include "player.hpp"
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <components/esm/esmreader.hpp>
|
||||||
|
#include <components/esm/esmwriter.hpp>
|
||||||
|
#include <components/esm/player.hpp>
|
||||||
|
#include <components/esm/defs.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
@ -34,9 +41,6 @@ namespace MWWorld
|
||||||
void Player::set(const ESM::NPC *player)
|
void Player::set(const ESM::NPC *player)
|
||||||
{
|
{
|
||||||
mPlayer.mBase = player;
|
mPlayer.mBase = player;
|
||||||
|
|
||||||
float* playerPos = mPlayer.mData.getPosition().pos;
|
|
||||||
playerPos[0] = playerPos[1] = playerPos[2] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setCell (MWWorld::CellStore *cellStore)
|
void Player::setCell (MWWorld::CellStore *cellStore)
|
||||||
|
@ -181,4 +185,54 @@ namespace MWWorld
|
||||||
mForwardBackward = 0;
|
mForwardBackward = 0;
|
||||||
mTeleported = false;
|
mTeleported = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::write (ESM::ESMWriter& writer) const
|
||||||
|
{
|
||||||
|
ESM::Player player;
|
||||||
|
|
||||||
|
mPlayer.save (player.mObject);
|
||||||
|
player.mCellId = mCellStore->mCell->getCellId();
|
||||||
|
|
||||||
|
/// \todo sign
|
||||||
|
/// \todo last know exterior position
|
||||||
|
/// \todo mark
|
||||||
|
|
||||||
|
player.mAutoMove = mAutoMove ? 1 : 0;
|
||||||
|
|
||||||
|
writer.startRecord (ESM::REC_PLAY);
|
||||||
|
player.save (writer);
|
||||||
|
writer.endRecord (ESM::REC_PLAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Player::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||||
|
{
|
||||||
|
if (type==ESM::REC_PLAY)
|
||||||
|
{
|
||||||
|
ESM::Player player;
|
||||||
|
player.load (reader);
|
||||||
|
|
||||||
|
if (!mPlayer.checkState (player.mObject))
|
||||||
|
{
|
||||||
|
// this is the one object we can not silently drop.
|
||||||
|
throw std::runtime_error ("invalid player state record");
|
||||||
|
}
|
||||||
|
|
||||||
|
mPlayer.load (player.mObject);
|
||||||
|
|
||||||
|
mCellStore = MWBase::Environment::get().getWorld()->getCell (player.mCellId);
|
||||||
|
|
||||||
|
/// \todo sign
|
||||||
|
/// \todo last know exterior position
|
||||||
|
/// \todo mark
|
||||||
|
|
||||||
|
mAutoMove = player.mAutoMove!=0;
|
||||||
|
|
||||||
|
mForwardBackward = 0;
|
||||||
|
mTeleported = false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
struct NPC;
|
struct NPC;
|
||||||
|
class ESMWriter;
|
||||||
|
class ESMReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWBase
|
namespace MWBase
|
||||||
|
@ -88,6 +90,10 @@ namespace MWWorld
|
||||||
void setTeleported(bool teleported);
|
void setTeleported(bool teleported);
|
||||||
|
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
void write (ESM::ESMWriter& writer) const;
|
||||||
|
|
||||||
|
bool readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include <OgreSceneNode.h>
|
#include <OgreSceneNode.h>
|
||||||
|
|
||||||
|
#include <components/esm/objectstate.hpp>
|
||||||
|
|
||||||
#include "customdata.hpp"
|
#include "customdata.hpp"
|
||||||
#include "cellstore.hpp"
|
#include "cellstore.hpp"
|
||||||
|
|
||||||
|
@ -52,6 +54,14 @@ namespace MWWorld
|
||||||
mLocalRotation.rot[2]=0;
|
mLocalRotation.rot[2]=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefData::RefData (const ESM::ObjectState& objectState)
|
||||||
|
: mBaseNode (0), mHasLocals (false), mEnabled (objectState.mEnabled),
|
||||||
|
mCount (objectState.mCount), mPosition (objectState.mPosition), mCustomData (0)
|
||||||
|
{
|
||||||
|
for (int i=0; i<3; ++i)
|
||||||
|
mLocalRotation.rot[i] = objectState.mLocalRotation[i];
|
||||||
|
}
|
||||||
|
|
||||||
RefData::RefData (const RefData& refData)
|
RefData::RefData (const RefData& refData)
|
||||||
: mBaseNode(0), mCustomData (0)
|
: mBaseNode(0), mCustomData (0)
|
||||||
{
|
{
|
||||||
|
@ -66,6 +76,17 @@ namespace MWWorld
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RefData::write (ESM::ObjectState& objectState) const
|
||||||
|
{
|
||||||
|
objectState.mHasLocals = false;
|
||||||
|
objectState.mEnabled = mEnabled;
|
||||||
|
objectState.mCount = mCount;
|
||||||
|
objectState.mPosition = mPosition;
|
||||||
|
|
||||||
|
for (int i=0; i<3; ++i)
|
||||||
|
objectState.mLocalRotation[i] = mLocalRotation.rot[i];
|
||||||
|
}
|
||||||
|
|
||||||
RefData& RefData::operator= (const RefData& refData)
|
RefData& RefData::operator= (const RefData& refData)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -14,6 +14,7 @@ namespace ESM
|
||||||
{
|
{
|
||||||
class Script;
|
class Script;
|
||||||
class CellRef;
|
class CellRef;
|
||||||
|
class ObjectState;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
|
@ -55,10 +56,18 @@ namespace MWWorld
|
||||||
/// to reset the position as the orignal data is still held in the CellRef
|
/// to reset the position as the orignal data is still held in the CellRef
|
||||||
RefData (const ESM::CellRef& cellRef);
|
RefData (const ESM::CellRef& cellRef);
|
||||||
|
|
||||||
|
RefData (const ESM::ObjectState& objectState);
|
||||||
|
///< Ignores local variables and custom data (not enough context available here to
|
||||||
|
/// perform these operations).
|
||||||
|
|
||||||
RefData (const RefData& refData);
|
RefData (const RefData& refData);
|
||||||
|
|
||||||
~RefData();
|
~RefData();
|
||||||
|
|
||||||
|
void write (ESM::ObjectState& objectState) const;
|
||||||
|
///< Ignores local variables and custom data (not enough context available here to
|
||||||
|
/// perform these operations).
|
||||||
|
|
||||||
RefData& operator= (const RefData& refData);
|
RefData& operator= (const RefData& refData);
|
||||||
|
|
||||||
/// Return OGRE handle (may be empty).
|
/// Return OGRE handle (may be empty).
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <components/bsa/bsa_archive.hpp>
|
#include <components/bsa/bsa_archive.hpp>
|
||||||
#include <components/files/collections.hpp>
|
#include <components/files/collections.hpp>
|
||||||
#include <components/compiler/locals.hpp>
|
#include <components/compiler/locals.hpp>
|
||||||
|
#include <components/esm/cellid.hpp>
|
||||||
|
|
||||||
#include <boost/math/special_functions/sign.hpp>
|
#include <boost/math/special_functions/sign.hpp>
|
||||||
|
|
||||||
|
@ -309,12 +310,14 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
mStore.write (writer);
|
mStore.write (writer);
|
||||||
mGlobalVariables.write (writer);
|
mGlobalVariables.write (writer);
|
||||||
|
mPlayer->write (writer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void World::readRecord (ESM::ESMReader& reader, int32_t type)
|
void World::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||||
{
|
{
|
||||||
if (!mStore.readRecord (reader, type) &&
|
if (!mStore.readRecord (reader, type) &&
|
||||||
!mGlobalVariables.readRecord (reader, type))
|
!mGlobalVariables.readRecord (reader, type) &&
|
||||||
|
!mPlayer->readRecord (reader, type))
|
||||||
{
|
{
|
||||||
throw std::runtime_error ("unknown record in saved game");
|
throw std::runtime_error ("unknown record in saved game");
|
||||||
}
|
}
|
||||||
|
@ -402,6 +405,14 @@ namespace MWWorld
|
||||||
return mCells.getInterior (name);
|
return mCells.getInterior (name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CellStore *World::getCell (const ESM::CellId& id)
|
||||||
|
{
|
||||||
|
if (id.mPaged)
|
||||||
|
return getExterior (id.mIndex.mX, id.mIndex.mY);
|
||||||
|
else
|
||||||
|
return getInterior (id.mWorldspace);
|
||||||
|
}
|
||||||
|
|
||||||
void World::useDeathCamera()
|
void World::useDeathCamera()
|
||||||
{
|
{
|
||||||
if(mRendering->getCamera()->isVanityOrPreviewModeEnabled() )
|
if(mRendering->getCamera()->isVanityOrPreviewModeEnabled() )
|
||||||
|
@ -802,6 +813,14 @@ namespace MWWorld
|
||||||
addContainerScripts(getPlayer().getPlayer(), getPlayer().getPlayer().getCell());
|
addContainerScripts(getPlayer().getPlayer(), getPlayer().getPlayer().getCell());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void World::changeToCell (const ESM::CellId& cellId, const ESM::Position& position)
|
||||||
|
{
|
||||||
|
if (cellId.mPaged)
|
||||||
|
changeToExteriorCell (position);
|
||||||
|
else
|
||||||
|
changeToInteriorCell (cellId.mWorldspace, position);
|
||||||
|
}
|
||||||
|
|
||||||
void World::markCellAsUnchanged()
|
void World::markCellAsUnchanged()
|
||||||
{
|
{
|
||||||
return mWorldScene->markCellAsUnchanged();
|
return mWorldScene->markCellAsUnchanged();
|
||||||
|
|
|
@ -181,12 +181,14 @@ namespace MWWorld
|
||||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||||
|
|
||||||
virtual OEngine::Render::Fader* getFader();
|
virtual OEngine::Render::Fader* getFader();
|
||||||
///< \ŧodo remove this function. Rendering details should not be exposed.
|
///< \todo remove this function. Rendering details should not be exposed.
|
||||||
|
|
||||||
virtual CellStore *getExterior (int x, int y);
|
virtual CellStore *getExterior (int x, int y);
|
||||||
|
|
||||||
virtual CellStore *getInterior (const std::string& name);
|
virtual CellStore *getInterior (const std::string& name);
|
||||||
|
|
||||||
|
virtual CellStore *getCell (const ESM::CellId& id);
|
||||||
|
|
||||||
//switch to POV before showing player's death animation
|
//switch to POV before showing player's death animation
|
||||||
virtual void useDeathCamera();
|
virtual void useDeathCamera();
|
||||||
|
|
||||||
|
@ -314,6 +316,8 @@ namespace MWWorld
|
||||||
virtual void changeToExteriorCell (const ESM::Position& position);
|
virtual void changeToExteriorCell (const ESM::Position& position);
|
||||||
///< Move to exterior cell.
|
///< Move to exterior cell.
|
||||||
|
|
||||||
|
virtual void changeToCell (const ESM::CellId& cellId, const ESM::Position& position);
|
||||||
|
|
||||||
virtual const ESM::Cell *getExterior (const std::string& cellName) const;
|
virtual const ESM::Cell *getExterior (const std::string& cellName) const;
|
||||||
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue