loading/saving of some player state (cell/coordinates and some other bits)

actorid
Marc Zinnschlag 11 years ago
parent d8d4f1a15e
commit c300cd9375

@ -37,6 +37,7 @@ namespace ESM
struct Potion;
struct Spell;
struct NPC;
struct CellId;
}
namespace MWRender
@ -105,12 +106,14 @@ namespace MWBase
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 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 *getInterior (const std::string& name) = 0;
virtual MWWorld::CellStore *getCell (const ESM::CellId& id) = 0;
virtual void useDeathCamera() = 0;
virtual void setWaterHeight(const float height) = 0;
@ -236,6 +239,8 @@ namespace MWBase
virtual void changeToExteriorCell (const ESM::Position& position) = 0;
///< 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;
///< 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/esmreader.hpp>
#include <components/esm/cellid.hpp>
#include <components/esm/loadcell.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_WEAP:
case ESM::REC_GLOB:
case ESM::REC_PLAY:
MWBase::Environment::get().getWorld()->readRecord (reader, n.val);
break;
@ -245,11 +248,11 @@ void MWState::StateManager::loadGame (const Character *character, const Slot *sl
MWBase::Environment::get().getWindowManager()->updatePlayer();
MWBase::Environment::get().getMechanicsManager()->playerLoaded();
// for testing purpose only
ESM::Position pos;
pos.pos[0] = pos.pos[1] = pos.pos[2] = 0;
pos.rot[0] = pos.rot[1] = pos.rot[2] = 0;
MWBase::Environment::get().getWorld()->changeToExteriorCell (pos);
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
ESM::CellId cellId = ptr.getCell()->mCell->getCellId();
MWBase::Environment::get().getWorld()->changeToCell (cellId, ptr.getRefData().getPosition());
}
MWState::Character *MWState::StateManager::getCurrentCharacter (bool create)

@ -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"
namespace ESM
{
class ObjectState;
}
namespace MWWorld
{
class Ptr;
@ -29,6 +34,24 @@ namespace MWWorld
LiveCellRefBase(std::string type, const ESM::CellRef &cref=ESM::CellRef());
/* Need this for the class to be recognized as polymorphic */
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)
@ -55,7 +78,41 @@ namespace MWWorld
// The object that this instance is based on.
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

@ -1,6 +1,13 @@
#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/world.hpp"
#include "../mwbase/windowmanager.hpp"
@ -34,9 +41,6 @@ namespace MWWorld
void Player::set(const ESM::NPC *player)
{
mPlayer.mBase = player;
float* playerPos = mPlayer.mData.getPosition().pos;
playerPos[0] = playerPos[1] = playerPos[2] = 0;
}
void Player::setCell (MWWorld::CellStore *cellStore)
@ -181,4 +185,54 @@ namespace MWWorld
mForwardBackward = 0;
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
{
struct NPC;
class ESMWriter;
class ESMReader;
}
namespace MWBase
@ -88,6 +90,10 @@ namespace MWWorld
void setTeleported(bool teleported);
void clear();
void write (ESM::ESMWriter& writer) const;
bool readRecord (ESM::ESMReader& reader, int32_t type);
};
}
#endif

@ -3,6 +3,8 @@
#include <OgreSceneNode.h>
#include <components/esm/objectstate.hpp>
#include "customdata.hpp"
#include "cellstore.hpp"
@ -52,6 +54,14 @@ namespace MWWorld
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)
: 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)
{
try

@ -14,6 +14,7 @@ namespace ESM
{
class Script;
class CellRef;
class ObjectState;
}
namespace MWWorld
@ -55,10 +56,18 @@ namespace MWWorld
/// to reset the position as the orignal data is still held in the 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();
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);
/// Return OGRE handle (may be empty).

@ -14,6 +14,7 @@
#include <components/bsa/bsa_archive.hpp>
#include <components/files/collections.hpp>
#include <components/compiler/locals.hpp>
#include <components/esm/cellid.hpp>
#include <boost/math/special_functions/sign.hpp>
@ -309,12 +310,14 @@ namespace MWWorld
{
mStore.write (writer);
mGlobalVariables.write (writer);
mPlayer->write (writer);
}
void World::readRecord (ESM::ESMReader& reader, int32_t 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");
}
@ -402,6 +405,14 @@ namespace MWWorld
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()
{
if(mRendering->getCamera()->isVanityOrPreviewModeEnabled() )
@ -802,6 +813,14 @@ namespace MWWorld
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()
{
return mWorldScene->markCellAsUnchanged();

@ -181,12 +181,14 @@ namespace MWWorld
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
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 *getInterior (const std::string& name);
virtual CellStore *getCell (const ESM::CellId& id);
//switch to POV before showing player's death animation
virtual void useDeathCamera();
@ -314,6 +316,8 @@ namespace MWWorld
virtual void changeToExteriorCell (const ESM::Position& position);
///< 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;
///< Return a cell matching the given name or a 0-pointer, if there is no such cell.

Loading…
Cancel
Save