mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-05 21:15:33 +00:00
Change (again) the way SetPos behave.
Instead of registering the desired change of position and rely on physics simulation to apply it to the world, immediately change the position in the world without reset the simulation.
This commit is contained in:
parent
6e1c67a9ae
commit
8874a5be22
5 changed files with 27 additions and 49 deletions
|
@ -281,13 +281,13 @@ namespace MWBase
|
|||
virtual void deleteObject (const MWWorld::Ptr& ptr) = 0;
|
||||
virtual void undeleteObject (const MWWorld::Ptr& ptr) = 0;
|
||||
|
||||
virtual MWWorld::Ptr moveObject (const MWWorld::Ptr& ptr, float x, float y, float z, bool moveToActive=false) = 0;
|
||||
virtual MWWorld::Ptr moveObject (const MWWorld::Ptr& ptr, float x, float y, float z, bool movePhysics=true, bool moveToActive=false) = 0;
|
||||
///< @return an updated Ptr in case the Ptr's cell changes
|
||||
|
||||
virtual MWWorld::Ptr moveObject(const MWWorld::Ptr &ptr, MWWorld::CellStore* newCell, float x, float y, float z, bool movePhysics=true) = 0;
|
||||
///< @return an updated Ptr
|
||||
|
||||
virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, osg::Vec3f vec) = 0;
|
||||
virtual MWWorld::Ptr moveObjectBy(const MWWorld::Ptr &ptr, osg::Vec3f vec, bool moveToActive) = 0;
|
||||
///< @return an updated Ptr
|
||||
|
||||
virtual void scaleObject (const MWWorld::Ptr& ptr, float scale) = 0;
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
#include <BulletCollision/CollisionShapes/btBoxShape.h>
|
||||
#include <BulletCollision/CollisionDispatch/btCollisionWorld.h>
|
||||
|
||||
#include <apps/openmw/mwmechanics/actorutil.hpp>
|
||||
#include <apps/openmw/mwworld/cellstore.hpp>
|
||||
#include <components/sceneutil/positionattitudetransform.hpp>
|
||||
#include <components/resource/bulletshape.hpp>
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
@ -181,6 +179,7 @@ bool Actor::setPosition(const osg::Vec3f& position)
|
|||
if (mSkipSimulation)
|
||||
return false;
|
||||
bool hasChanged = mPosition != position || mPositionOffset.length() != 0 || mWorldPositionChanged;
|
||||
updateWorldPosition();
|
||||
applyOffsetChange();
|
||||
mPreviousPosition = mPosition;
|
||||
mPosition = position;
|
||||
|
@ -197,15 +196,6 @@ void Actor::applyOffsetChange()
|
|||
{
|
||||
if (mPositionOffset.length() == 0)
|
||||
return;
|
||||
if (mPositionOffset.z() != 0)
|
||||
{
|
||||
// Often, offset are set in sequence x, y, z
|
||||
// We don't want actors to be moved under the ground
|
||||
// Check terrain height at new coordinate and update z offset if necessary
|
||||
const auto pos = mWorldPosition + mPositionOffset;
|
||||
const auto terrainHeight = mPtr.getCell()->isExterior() ? MWBase::Environment::get().getWorld()->getTerrainHeightAt(pos) : -std::numeric_limits<float>::max();
|
||||
mPositionOffset.z() = std::max(pos.z(), terrainHeight) - mWorldPosition.z();
|
||||
}
|
||||
mWorldPosition += mPositionOffset;
|
||||
mPosition += mPositionOffset;
|
||||
mPreviousPosition += mPositionOffset;
|
||||
|
|
|
@ -32,7 +32,7 @@ namespace MWScript
|
|||
std::vector<MWWorld::Ptr> actors;
|
||||
MWBase::Environment::get().getWorld()->getActorsStandingOn (ptr, actors);
|
||||
for (auto& actor : actors)
|
||||
MWBase::Environment::get().getWorld()->moveObjectBy(actor, diff);
|
||||
MWBase::Environment::get().getWorld()->moveObjectBy(actor, diff, false);
|
||||
}
|
||||
|
||||
template<class R>
|
||||
|
@ -284,6 +284,17 @@ namespace MWScript
|
|||
}
|
||||
else if(axis == "z")
|
||||
{
|
||||
// We should not place actors under ground
|
||||
if (ptr.getClass().isActor())
|
||||
{
|
||||
float terrainHeight = -std::numeric_limits<float>::max();
|
||||
if (ptr.getCell()->isExterior())
|
||||
terrainHeight = MWBase::Environment::get().getWorld()->getTerrainHeightAt(curPos);
|
||||
|
||||
if (pos < terrainHeight)
|
||||
pos = terrainHeight;
|
||||
}
|
||||
|
||||
newPos[2] = pos;
|
||||
}
|
||||
else
|
||||
|
@ -292,7 +303,7 @@ namespace MWScript
|
|||
}
|
||||
|
||||
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr,
|
||||
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, newPos - curPos));
|
||||
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, newPos - curPos, true));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -428,7 +439,7 @@ namespace MWScript
|
|||
}
|
||||
else
|
||||
{
|
||||
ptr = MWBase::Environment::get().getWorld()->moveObject(ptr, x, y, z, true);
|
||||
ptr = MWBase::Environment::get().getWorld()->moveObject(ptr, x, y, z, true, true);
|
||||
}
|
||||
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(base,ptr);
|
||||
|
||||
|
@ -715,7 +726,7 @@ namespace MWScript
|
|||
// This approach can be used to create elevators.
|
||||
moveStandingActors(ptr, diff);
|
||||
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr,
|
||||
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff));
|
||||
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff, false));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -751,7 +762,7 @@ namespace MWScript
|
|||
// This approach can be used to create elevators.
|
||||
moveStandingActors(ptr, diff);
|
||||
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(ptr,
|
||||
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff));
|
||||
MWBase::Environment::get().getWorld()->moveObjectBy(ptr, diff, false));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -862,19 +862,6 @@ namespace MWWorld
|
|||
if (reference == getPlayerPtr())
|
||||
throw std::runtime_error("can not disable player object");
|
||||
|
||||
// A common pattern to teleport NPC in scripts is a sequence of SetPos/Disable/Enable
|
||||
// Disable/Enable create a new physics actor, and so the SetPos call is lost
|
||||
// Call moveObject so that the newly created physics actor will have up-to-date position
|
||||
if (reference.getClass().isActor())
|
||||
{
|
||||
auto* physactor = mPhysics->getActor(reference);
|
||||
if (physactor)
|
||||
{
|
||||
physactor->applyOffsetChange();
|
||||
const auto position = physactor->getSimulationPosition();
|
||||
moveObject(reference, position.x(), position.y(), position.z(), true);
|
||||
}
|
||||
}
|
||||
reference.getRefData().disable();
|
||||
|
||||
if (reference.getCellRef().getRefNum().hasContentFile())
|
||||
|
@ -1251,7 +1238,7 @@ namespace MWWorld
|
|||
return newPtr;
|
||||
}
|
||||
|
||||
MWWorld::Ptr World::moveObjectImp(const Ptr& ptr, float x, float y, float z, bool movePhysics, bool moveToActive)
|
||||
MWWorld::Ptr World::moveObject (const Ptr& ptr, float x, float y, float z, bool movePhysics, bool moveToActive)
|
||||
{
|
||||
int cellX, cellY;
|
||||
positionToIndex(x, y, cellX, cellY);
|
||||
|
@ -1266,21 +1253,14 @@ namespace MWWorld
|
|||
return moveObject(ptr, cell, x, y, z, movePhysics);
|
||||
}
|
||||
|
||||
MWWorld::Ptr World::moveObject (const Ptr& ptr, float x, float y, float z, bool moveToActive)
|
||||
{
|
||||
return moveObjectImp(ptr, x, y, z, true, moveToActive);
|
||||
}
|
||||
|
||||
MWWorld::Ptr World::moveObjectBy(const Ptr& ptr, osg::Vec3f vec)
|
||||
MWWorld::Ptr World::moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive)
|
||||
{
|
||||
auto* actor = mPhysics->getActor(ptr);
|
||||
if (actor)
|
||||
{
|
||||
actor->adjustPosition(vec);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
osg::Vec3f newpos = ptr.getRefData().getPosition().asVec3() + vec;
|
||||
return moveObject(ptr, newpos.x(), newpos.y(), newpos.z());
|
||||
return moveObject(ptr, newpos.x(), newpos.y(), newpos.z(), false, moveToActive && ptr != getPlayerPtr());
|
||||
}
|
||||
|
||||
void World::scaleObject (const Ptr& ptr, float scale)
|
||||
|
@ -1546,7 +1526,7 @@ namespace MWWorld
|
|||
auto* physactor = mPhysics->getActor(actor);
|
||||
assert(physactor);
|
||||
const auto position = physactor->getSimulationPosition();
|
||||
moveObjectImp(actor, position.x(), position.y(), position.z(), false);
|
||||
moveObject(actor, position.x(), position.y(), position.z(), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1556,7 +1536,7 @@ namespace MWWorld
|
|||
auto* physactor = mPhysics->getActor(*player);
|
||||
assert(physactor);
|
||||
const auto position = physactor->getSimulationPosition();
|
||||
moveObjectImp(*player, position.x(), position.y(), position.z(), false);
|
||||
moveObject(*player, position.x(), position.y(), position.z(), false, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -138,9 +138,6 @@ namespace MWWorld
|
|||
|
||||
void rotateObjectImp (const Ptr& ptr, const osg::Vec3f& rot, MWBase::RotationFlags flags);
|
||||
|
||||
Ptr moveObjectImp (const Ptr& ptr, float x, float y, float z, bool movePhysics=true, bool moveToActive=false);
|
||||
///< @return an updated Ptr in case the Ptr's cell changes
|
||||
|
||||
Ptr copyObjectToCell(const ConstPtr &ptr, CellStore* cell, ESM::Position pos, int count, bool adjustPos);
|
||||
|
||||
void updateSoundListener();
|
||||
|
@ -376,13 +373,13 @@ namespace MWWorld
|
|||
|
||||
void undeleteObject (const Ptr& ptr) override;
|
||||
|
||||
MWWorld::Ptr moveObject (const Ptr& ptr, float x, float y, float z, bool moveToActive=false) override;
|
||||
MWWorld::Ptr moveObject (const Ptr& ptr, float x, float y, float z, bool movePhysics=true, bool moveToActive=false) override;
|
||||
///< @return an updated Ptr in case the Ptr's cell changes
|
||||
|
||||
MWWorld::Ptr moveObject (const Ptr& ptr, CellStore* newCell, float x, float y, float z, bool movePhysics=true) override;
|
||||
///< @return an updated Ptr
|
||||
|
||||
MWWorld::Ptr moveObjectBy(const Ptr& ptr, osg::Vec3f vec) override;
|
||||
MWWorld::Ptr moveObjectBy(const Ptr& ptr, osg::Vec3f vec, bool moveToActive) override;
|
||||
///< @return an updated Ptr
|
||||
|
||||
void scaleObject (const Ptr& ptr, float scale) override;
|
||||
|
|
Loading…
Reference in a new issue