Fix triggering changed flag for all references when cell is visited

The InsertFunctor for cells was calling localRotateObject() for all references which set the mChanged flag in RefData to true.

Also clean up RefData interface slightly.
deque
scrawl 11 years ago
parent b20f8cc04f
commit 395f98e476

@ -837,8 +837,7 @@ namespace MWClass
ptr.getRefData().setCount(1); ptr.getRefData().setCount(1);
// Reset to original position // Reset to original position
ESM::Position& pos = ptr.getRefData().getPosition(); ptr.getRefData().setPosition(ptr.getCellRef().getPosition());
pos = ptr.getCellRef().getPosition();
ptr.getRefData().setCustomData(NULL); ptr.getRefData().setCustomData(NULL);
} }

@ -1325,8 +1325,7 @@ namespace MWClass
ptr.getRefData().setCount(1); ptr.getRefData().setCount(1);
// Reset to original position // Reset to original position
ESM::Position& pos = ptr.getRefData().getPosition(); ptr.getRefData().setPosition(ptr.getCellRef().getPosition());
pos = ptr.getCellRef().getPosition();
ptr.getRefData().setCustomData(NULL); ptr.getRefData().setCustomData(NULL);
} }

@ -88,7 +88,7 @@ bool AiSequence::canAddTarget(const ESM::Position& actorPos, float distToTarget)
else else
{ {
// add new target only if current target (player) is farther // add new target only if current target (player) is farther
ESM::Position &targetPos = combat->getTarget().getRefData().getPosition(); const ESM::Position &targetPos = combat->getTarget().getRefData().getPosition();
float distToCurrTarget = (Ogre::Vector3(targetPos.pos) - Ogre::Vector3(actorPos.pos)).length(); float distToCurrTarget = (Ogre::Vector3(targetPos.pos) - Ogre::Vector3(actorPos.pos)).length();
return (distToCurrTarget > distToTarget); return (distToCurrTarget > distToTarget);
@ -153,7 +153,7 @@ void AiSequence::execute (const MWWorld::Ptr& actor,float duration)
} }
else else
{ {
ESM::Position &targetPos = target.getRefData().getPosition(); const ESM::Position &targetPos = target.getRefData().getPosition();
float distTo = (Ogre::Vector3(targetPos.pos) - vActorPos).length(); float distTo = (Ogre::Vector3(targetPos.pos) - vActorPos).length();
if (distTo < nearestDist) if (distTo < nearestDist)

@ -100,6 +100,9 @@ namespace MWMechanics
if(!cell) if(!cell)
return false; return false;
if(mIsGraphConstructed)
return true;
mCell = cell; mCell = cell;
mIsExterior = cell->isExterior(); mIsExterior = cell->isExterior();
mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell); mPathgrid = MWBase::Environment::get().getWorld()->getStore().get<ESM::Pathgrid>().search(*cell);
@ -107,8 +110,6 @@ namespace MWMechanics
if(!mPathgrid) if(!mPathgrid)
return false; return false;
if(mIsGraphConstructed)
return true;
mGraph.resize(mPathgrid->mPoints.size()); mGraph.resize(mPathgrid->mPoints.size());
for(int i = 0; i < static_cast<int> (mPathgrid->mEdges.size()); i++) for(int i = 0; i < static_cast<int> (mPathgrid->mEdges.size()); i++)

@ -165,7 +165,7 @@ void RippleSimulation::addImpulses()
// for non-player actors this is done in updateObjectCell // for non-player actors this is done in updateObjectCell
it->mPtr = MWBase::Environment::get().getWorld ()->getPlayerPtr(); it->mPtr = MWBase::Environment::get().getWorld ()->getPlayerPtr();
} }
float* _currentPos = it->mPtr.getRefData().getPosition().pos; const float* _currentPos = it->mPtr.getRefData().getPosition().pos;
Ogre::Vector3 currentPos (_currentPos[0], _currentPos[1], _currentPos[2]); Ogre::Vector3 currentPos (_currentPos[0], _currentPos[1], _currentPos[2]);
if ( (currentPos - it->mLastEmitPosition).length() > 2 if ( (currentPos - it->mLastEmitPosition).length() > 2

@ -578,7 +578,7 @@ namespace MWScript
Interpreter::Type_Float rotation = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration()); Interpreter::Type_Float rotation = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
runtime.pop(); runtime.pop();
float *objRot = ptr.getRefData().getPosition().rot; const float *objRot = ptr.getRefData().getPosition().rot;
float ax = Ogre::Radian(objRot[0]).valueDegrees(); float ax = Ogre::Radian(objRot[0]).valueDegrees();
float ay = Ogre::Radian(objRot[1]).valueDegrees(); float ay = Ogre::Radian(objRot[1]).valueDegrees();
@ -613,9 +613,12 @@ namespace MWScript
if (!ptr.isInCell()) if (!ptr.isInCell())
return; return;
ptr.getRefData().getLocalRotation().rot[0] = 0; MWWorld::LocalRotation rot;
ptr.getRefData().getLocalRotation().rot[1] = 0; rot.rot[0] = 0;
ptr.getRefData().getLocalRotation().rot[2] = 0; rot.rot[1] = 0;
rot.rot[2] = 0;
ptr.getRefData().setLocalRotation(rot);
MWBase::Environment::get().getWorld()->rotateObject(ptr, 0,0,0,true); MWBase::Environment::get().getWorld()->rotateObject(ptr, 0,0,0,true);
MWBase::Environment::get().getWorld()->moveObject(ptr, ptr.getCellRef().getPosition().pos[0], MWBase::Environment::get().getWorld()->moveObject(ptr, ptr.getCellRef().getPosition().pos[0],
ptr.getCellRef().getPosition().pos[1], ptr.getCellRef().getPosition().pos[2]); ptr.getCellRef().getPosition().pos[1], ptr.getCellRef().getPosition().pos[2]);
@ -678,7 +681,7 @@ namespace MWScript
Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration()); Interpreter::Type_Float movement = (runtime[0].mFloat*MWBase::Environment::get().getFrameDuration());
runtime.pop(); runtime.pop();
float *objPos = ptr.getRefData().getPosition().pos; const float *objPos = ptr.getRefData().getPosition().pos;
if (axis == "x") if (axis == "x")
{ {

@ -42,7 +42,8 @@ namespace MWWorld
float getScale() const; float getScale() const;
void setScale(float scale); void setScale(float scale);
// Position and rotation of this object within the cell // The *original* position and rotation as it was given in the Construction Set.
// Current position and rotation of the object is stored in RefData.
ESM::Position getPosition() const; ESM::Position getPosition() const;
void setPosition (const ESM::Position& position); void setPosition (const ESM::Position& position);

@ -410,6 +410,9 @@ namespace MWWorld
loadRefs (store, esm); loadRefs (store, esm);
mState = State_Loaded; mState = State_Loaded;
// TODO: the pathgrid graph only needs to be loaded for active cells, so move this somewhere else.
// In a simple test, loading the graph for all cells in MW + expansions took 200 ms
mPathgridGraph.load(mCell); mPathgridGraph.load(mCell);
} }
} }

@ -366,7 +366,7 @@ namespace MWWorld
Class::copyToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const Class::copyToCell(const Ptr &ptr, CellStore &cell, const ESM::Position &pos) const
{ {
Ptr newPtr = copyToCell(ptr, cell); Ptr newPtr = copyToCell(ptr, cell);
newPtr.getRefData().getPosition() = pos; newPtr.getRefData().setPosition(pos);
return newPtr; return newPtr;
} }

@ -44,8 +44,9 @@ namespace MWWorld
cellRef.mRefID = "player"; cellRef.mRefID = "player";
mPlayer = LiveCellRef<ESM::NPC>(cellRef, player); mPlayer = LiveCellRef<ESM::NPC>(cellRef, player);
float* playerPos = mPlayer.mData.getPosition().pos; ESM::Position playerPos = mPlayer.mData.getPosition();
playerPos[0] = playerPos[1] = playerPos[2] = 0; playerPos.pos[0] = playerPos.pos[1] = playerPos.pos[2] = 0;
mPlayer.mData.setPosition(playerPos);
} }
void Player::set(const ESM::NPC *player) void Player::set(const ESM::NPC *player)

@ -188,15 +188,25 @@ namespace MWWorld
mEnabled = false; mEnabled = false;
} }
ESM::Position& RefData::getPosition() void RefData::setPosition(const ESM::Position& pos)
{ {
mChanged = true; mChanged = true;
mPosition = pos;
}
const ESM::Position& RefData::getPosition()
{
return mPosition; return mPosition;
} }
LocalRotation& RefData::getLocalRotation() void RefData::setLocalRotation(const LocalRotation& rot)
{ {
mChanged = true; mChanged = true;
mLocalRotation = rot;
}
const LocalRotation& RefData::getLocalRotation()
{
return mLocalRotation; return mLocalRotation;
} }

@ -100,9 +100,11 @@ namespace MWWorld
void disable(); void disable();
ESM::Position& getPosition(); void setPosition (const ESM::Position& pos);
const ESM::Position& getPosition();
LocalRotation& getLocalRotation(); void setLocalRotation (const LocalRotation& rotation);
const LocalRotation& getLocalRotation();
void setCustomData (CustomData *data); void setCustomData (CustomData *data);
///< Set custom data (potentially replacing old custom data). The ownership of \æ data is ///< Set custom data (potentially replacing old custom data). The ownership of \æ data is

@ -22,6 +22,30 @@
namespace namespace
{ {
void updateObjectLocalRotation (const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics,
MWRender::RenderingManager& rendering)
{
if (ptr.getRefData().getBaseNode() != NULL)
{
Ogre::Quaternion worldRotQuat(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z);
if (!ptr.getClass().isActor())
worldRotQuat = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)*
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)* worldRotQuat;
float x = ptr.getRefData().getLocalRotation().rot[0];
float y = ptr.getRefData().getLocalRotation().rot[1];
float z = ptr.getRefData().getLocalRotation().rot[2];
Ogre::Quaternion rot(Ogre::Radian(z), Ogre::Vector3::NEGATIVE_UNIT_Z);
if (!ptr.getClass().isActor())
rot = Ogre::Quaternion(Ogre::Radian(x), Ogre::Vector3::NEGATIVE_UNIT_X)*
Ogre::Quaternion(Ogre::Radian(y), Ogre::Vector3::NEGATIVE_UNIT_Y)*rot;
ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot);
physics.rotateObject(ptr);
}
}
struct InsertFunctor struct InsertFunctor
{ {
MWWorld::CellStore& mCell; MWWorld::CellStore& mCell;
@ -60,11 +84,7 @@ namespace
mRendering.addObject (ptr); mRendering.addObject (ptr);
ptr.getClass().insertObject (ptr, mPhysics); ptr.getClass().insertObject (ptr, mPhysics);
float ax = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[0]).valueDegrees(); updateObjectLocalRotation(ptr, mPhysics, mRendering);
float ay = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[1]).valueDegrees();
float az = Ogre::Radian(ptr.getRefData().getLocalRotation().rot[2]).valueDegrees();
MWBase::Environment::get().getWorld()->localRotateObject (ptr, ax, ay, az);
MWBase::Environment::get().getWorld()->scaleObject (ptr, ptr.getCellRef().getScale()); MWBase::Environment::get().getWorld()->scaleObject (ptr, ptr.getCellRef().getScale());
ptr.getClass().adjustPosition (ptr); ptr.getClass().adjustPosition (ptr);
} }
@ -85,6 +105,20 @@ namespace
namespace MWWorld namespace MWWorld
{ {
void Scene::updateObjectLocalRotation (const Ptr& ptr)
{
::updateObjectLocalRotation(ptr, *mPhysics, mRendering);
}
void Scene::updateObjectRotation (const Ptr& ptr)
{
if(ptr.getRefData().getBaseNode() != 0)
{
mRendering.rotateObject(ptr);
mPhysics->rotateObject(ptr);
}
}
void Scene::update (float duration, bool paused) void Scene::update (float duration, bool paused)
{ {
if (mNeedMapUpdate) if (mNeedMapUpdate)

@ -103,6 +103,10 @@ namespace MWWorld
void removeObjectFromScene (const Ptr& ptr); void removeObjectFromScene (const Ptr& ptr);
///< Remove an object from the scene, but not from the world model. ///< Remove an object from the scene, but not from the world model.
void updateObjectLocalRotation (const Ptr& ptr);
void updateObjectRotation (const Ptr& ptr);
bool isCellActive(const CellStore &cell); bool isCellActive(const CellStore &cell);
Ptr searchPtrViaHandle (const std::string& handle); Ptr searchPtrViaHandle (const std::string& handle);

@ -957,12 +957,14 @@ namespace MWWorld
void World::moveObject(const Ptr &ptr, CellStore* newCell, float x, float y, float z) void World::moveObject(const Ptr &ptr, CellStore* newCell, float x, float y, float z)
{ {
ESM::Position &pos = ptr.getRefData().getPosition(); ESM::Position pos = ptr.getRefData().getPosition();
pos.pos[0] = x; pos.pos[0] = x;
pos.pos[1] = y; pos.pos[1] = y;
pos.pos[2] = z; pos.pos[2] = z;
ptr.getRefData().setPosition(pos);
Ogre::Vector3 vec(x, y, z); Ogre::Vector3 vec(x, y, z);
CellStore *currCell = ptr.isInCell() ? ptr.getCell() : NULL; CellStore *currCell = ptr.isInCell() ? ptr.getCell() : NULL;
@ -1068,7 +1070,8 @@ namespace MWWorld
const float two_pi = Ogre::Math::TWO_PI; const float two_pi = Ogre::Math::TWO_PI;
const float pi = Ogre::Math::PI; const float pi = Ogre::Math::PI;
float *objRot = ptr.getRefData().getPosition().rot; ESM::Position pos = ptr.getRefData().getPosition();
float *objRot = pos.rot;
if(adjust) if(adjust)
{ {
objRot[0] += rot.x; objRot[0] += rot.x;
@ -1105,43 +1108,33 @@ namespace MWWorld
while(objRot[2] < -pi) objRot[2] += two_pi; while(objRot[2] < -pi) objRot[2] += two_pi;
while(objRot[2] > pi) objRot[2] -= two_pi; while(objRot[2] > pi) objRot[2] -= two_pi;
if(ptr.getRefData().getBaseNode() != 0) ptr.getRefData().setPosition(pos);
{
mRendering->rotateObject(ptr); mWorldScene->updateObjectRotation(ptr);
mPhysics->rotateObject(ptr);
}
} }
void World::localRotateObject (const Ptr& ptr, float x, float y, float z) void World::localRotateObject (const Ptr& ptr, float x, float y, float z)
{ {
if (ptr.getRefData().getBaseNode() != 0) { if (ptr.getRefData().getBaseNode() != 0)
{
ptr.getRefData().getLocalRotation().rot[0]=Ogre::Degree(x).valueRadians(); LocalRotation rot = ptr.getRefData().getLocalRotation();
ptr.getRefData().getLocalRotation().rot[1]=Ogre::Degree(y).valueRadians(); rot.rot[0]=Ogre::Degree(x).valueRadians();
ptr.getRefData().getLocalRotation().rot[2]=Ogre::Degree(z).valueRadians(); rot.rot[1]=Ogre::Degree(y).valueRadians();
rot.rot[2]=Ogre::Degree(z).valueRadians();
wrap(ptr.getRefData().getLocalRotation().rot[0]);
wrap(ptr.getRefData().getLocalRotation().rot[1]);
wrap(ptr.getRefData().getLocalRotation().rot[2]);
Ogre::Quaternion worldRotQuat(Ogre::Radian(ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::NEGATIVE_UNIT_Z); wrap(rot.rot[0]);
if (!ptr.getClass().isActor()) wrap(rot.rot[1]);
worldRotQuat = Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::NEGATIVE_UNIT_X)* wrap(rot.rot[2]);
Ogre::Quaternion(Ogre::Radian(ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::NEGATIVE_UNIT_Y)* worldRotQuat;
Ogre::Quaternion rot(Ogre::Degree(z), Ogre::Vector3::NEGATIVE_UNIT_Z); ptr.getRefData().setLocalRotation(rot);
if (!ptr.getClass().isActor())
rot = Ogre::Quaternion(Ogre::Degree(x), Ogre::Vector3::NEGATIVE_UNIT_X)*
Ogre::Quaternion(Ogre::Degree(y), Ogre::Vector3::NEGATIVE_UNIT_Y)*rot;
ptr.getRefData().getBaseNode()->setOrientation(worldRotQuat*rot); mWorldScene->updateObjectLocalRotation(ptr);
mPhysics->rotateObject(ptr);
} }
} }
void World::adjustPosition(const Ptr &ptr) void World::adjustPosition(const Ptr &ptr)
{ {
Ogre::Vector3 pos (ptr.getRefData().getPosition().pos); ESM::Position pos (ptr.getRefData().getPosition());
if(!ptr.getRefData().getBaseNode()) if(!ptr.getRefData().getBaseNode())
{ {
@ -1149,21 +1142,23 @@ namespace MWWorld
return; return;
} }
float terrainHeight = mRendering->getTerrainHeightAt(pos); float terrainHeight = mRendering->getTerrainHeightAt(Ogre::Vector3(pos.pos));
if (pos.pos[2] < terrainHeight)
pos.pos[2] = terrainHeight;
if (pos.z < terrainHeight) pos.pos[2] += 20; // place slightly above. will snap down to ground with code below
pos.z = terrainHeight;
ptr.getRefData().getPosition().pos[2] = pos.z + 20; // place slightly above. will snap down to ground with code below ptr.getRefData().setPosition(pos);
if (!isFlying(ptr)) if (!isFlying(ptr))
{ {
Ogre::Vector3 traced = mPhysics->traceDown(ptr); Ogre::Vector3 traced = mPhysics->traceDown(ptr);
if (traced.z < pos.z) if (traced.z < pos.pos[2])
pos.z = traced.z; pos.pos[2] = traced.z;
} }
moveObject(ptr, ptr.getCell(), pos.x, pos.y, pos.z); moveObject(ptr, ptr.getCell(), pos.pos[0], pos.pos[1], pos.pos[2]);
} }
void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust)
@ -1429,7 +1424,7 @@ namespace MWWorld
// cast a ray from player to sun to detect if the sun is visible // cast a ray from player to sun to detect if the sun is visible
// this is temporary until we find a better place to put this code // this is temporary until we find a better place to put this code
// currently its here because we need to access the physics system // currently its here because we need to access the physics system
float* p = mPlayer->getPlayer().getRefData().getPosition().pos; const float* p = mPlayer->getPlayer().getRefData().getPosition().pos;
Vector3 sun = mRendering->getSkyManager()->getRealSunPos(); Vector3 sun = mRendering->getSkyManager()->getRealSunPos();
mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun)); mRendering->getSkyManager()->setGlare(!mPhysics->castRay(Ogre::Vector3(p[0], p[1], p[2]), sun));
} }
@ -1683,10 +1678,11 @@ namespace MWWorld
object.getClass().copyToCell(object, *cell, pos); object.getClass().copyToCell(object, *cell, pos);
// Reset some position values that could be uninitialized if this item came from a container // Reset some position values that could be uninitialized if this item came from a container
LocalRotation& localRotation = dropped.getRefData().getLocalRotation(); LocalRotation localRotation;
localRotation.rot[0] = 0; localRotation.rot[0] = 0;
localRotation.rot[1] = 0; localRotation.rot[1] = 0;
localRotation.rot[2] = 0; localRotation.rot[2] = 0;
dropped.getRefData().setLocalRotation(localRotation);
dropped.getCellRef().setPosition(pos); dropped.getCellRef().setPosition(pos);
if (mWorldScene->isCellActive(*cell)) { if (mWorldScene->isCellActive(*cell)) {
@ -1785,7 +1781,7 @@ namespace MWWorld
bool World::isSubmerged(const MWWorld::Ptr &object) const bool World::isSubmerged(const MWWorld::Ptr &object) const
{ {
float *fpos = object.getRefData().getPosition().pos; const float *fpos = object.getRefData().getPosition().pos;
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]); Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(object.getRefData().getHandle()); const OEngine::Physic::PhysicActor *actor = mPhysEngine->getCharacter(object.getRefData().getHandle());
@ -1798,7 +1794,7 @@ namespace MWWorld
World::isSwimming(const MWWorld::Ptr &object) const World::isSwimming(const MWWorld::Ptr &object) const
{ {
/// \todo add check ifActor() - only actors can swim /// \todo add check ifActor() - only actors can swim
float *fpos = object.getRefData().getPosition().pos; const float *fpos = object.getRefData().getPosition().pos;
Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]); Ogre::Vector3 pos(fpos[0], fpos[1], fpos[2]);
/// \fixme 3/4ths submerged? /// \fixme 3/4ths submerged?
@ -2031,9 +2027,9 @@ namespace MWWorld
if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled()) if (!targetNpc.getRefData().isEnabled() || !npc.getRefData().isEnabled())
return false; // cannot get LOS unless both NPC's are enabled return false; // cannot get LOS unless both NPC's are enabled
Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(npc.getRefData().getHandle())->getHalfExtents(); Ogre::Vector3 halfExt1 = mPhysEngine->getCharacter(npc.getRefData().getHandle())->getHalfExtents();
float* pos1 = npc.getRefData().getPosition().pos; const float* pos1 = npc.getRefData().getPosition().pos;
Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetNpc.getRefData().getHandle())->getHalfExtents(); Ogre::Vector3 halfExt2 = mPhysEngine->getCharacter(targetNpc.getRefData().getHandle())->getHalfExtents();
float* pos2 = targetNpc.getRefData().getPosition().pos; const float* pos2 = targetNpc.getRefData().getPosition().pos;
btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z); btVector3 from(pos1[0],pos1[1],pos1[2]+halfExt1.z);
btVector3 to(pos2[0],pos2[1],pos2[2]+halfExt2.z); btVector3 to(pos2[0],pos2[1],pos2[2]+halfExt2.z);

@ -336,10 +336,11 @@ namespace MWWorld
virtual void scaleObject (const Ptr& ptr, float scale); virtual void scaleObject (const Ptr& ptr, float scale);
/// Rotates object, uses degrees /// World rotates object, uses degrees
/// \param adjust indicates rotation should be set or adjusted /// \param adjust indicates rotation should be set or adjusted
virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false); virtual void rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust = false);
/// Local rotates object, uses degrees
virtual void localRotateObject (const Ptr& ptr, float x, float y, float z); virtual void localRotateObject (const Ptr& ptr, float x, float y, float z);
virtual MWWorld::Ptr safePlaceObject(const MWWorld::Ptr& ptr, MWWorld::CellStore* cell, ESM::Position pos); virtual MWWorld::Ptr safePlaceObject(const MWWorld::Ptr& ptr, MWWorld::CellStore* cell, ESM::Position pos);

Loading…
Cancel
Save