mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-20 07:53:51 +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 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)
|
||||
|
|
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"
|
||||
|
||||
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…
Reference in a new issue