1
0
Fork 1
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:
Marc Zinnschlag 2014-01-16 12:03:23 +01:00
parent d8d4f1a15e
commit c300cd9375
10 changed files with 210 additions and 11 deletions

View file

@ -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.

View file

@ -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)

View 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;
}

View file

@ -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

View file

@ -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;
}
} }

View file

@ -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

View file

@ -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

View file

@ -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).

View file

@ -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();

View file

@ -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.