mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-05 21:45:33 +00:00
Account for waterwalking when updating position. Otherwise we might
trace down the actor at waterlevel at the wrong coordinate. Triggered by multimark mod with waterwalking effect.
This commit is contained in:
parent
fe2a97ee39
commit
6e1c67a9ae
3 changed files with 27 additions and 26 deletions
|
@ -317,7 +317,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
// init
|
// init
|
||||||
for (auto& data : actorsData)
|
for (auto& data : actorsData)
|
||||||
data.updatePosition();
|
data.updatePosition(mCollisionWorld);
|
||||||
mPrevStepCount = numSteps;
|
mPrevStepCount = numSteps;
|
||||||
mRemainingSteps = numSteps;
|
mRemainingSteps = numSteps;
|
||||||
mTimeAccum = timeAccum;
|
mTimeAccum = timeAccum;
|
||||||
|
|
|
@ -60,6 +60,22 @@
|
||||||
#include "movementsolver.hpp"
|
#include "movementsolver.hpp"
|
||||||
#include "mtphysics.hpp"
|
#include "mtphysics.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool canMoveToWaterSurface(const MWPhysics::Actor* physicActor, const float waterlevel, btCollisionWorld* world)
|
||||||
|
{
|
||||||
|
if (!physicActor)
|
||||||
|
return false;
|
||||||
|
const float halfZ = physicActor->getHalfExtents().z();
|
||||||
|
const osg::Vec3f actorPosition = physicActor->getPosition();
|
||||||
|
const osg::Vec3f startingPosition(actorPosition.x(), actorPosition.y(), actorPosition.z() + halfZ);
|
||||||
|
const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel + halfZ);
|
||||||
|
MWPhysics::ActorTracer tracer;
|
||||||
|
tracer.doTrace(physicActor->getCollisionObject(), startingPosition, destinationPosition, world);
|
||||||
|
return (tracer.mFraction >= 1.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWPhysics
|
namespace MWPhysics
|
||||||
{
|
{
|
||||||
PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode)
|
PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode)
|
||||||
|
@ -347,16 +363,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
bool PhysicsSystem::canMoveToWaterSurface(const MWWorld::ConstPtr &actor, const float waterlevel)
|
bool PhysicsSystem::canMoveToWaterSurface(const MWWorld::ConstPtr &actor, const float waterlevel)
|
||||||
{
|
{
|
||||||
const Actor* physicActor = getActor(actor);
|
return ::canMoveToWaterSurface(getActor(actor), waterlevel, mCollisionWorld.get());
|
||||||
if (!physicActor)
|
|
||||||
return false;
|
|
||||||
const float halfZ = physicActor->getHalfExtents().z();
|
|
||||||
const osg::Vec3f actorPosition = physicActor->getPosition();
|
|
||||||
const osg::Vec3f startingPosition(actorPosition.x(), actorPosition.y(), actorPosition.z() + halfZ);
|
|
||||||
const osg::Vec3f destinationPosition(actorPosition.x(), actorPosition.y(), waterlevel + halfZ);
|
|
||||||
ActorTracer tracer;
|
|
||||||
tracer.doTrace(physicActor->getCollisionObject(), startingPosition, destinationPosition, mCollisionWorld.get());
|
|
||||||
return (tracer.mFraction >= 1.0f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f PhysicsSystem::getHalfExtents(const MWWorld::ConstPtr &actor) const
|
osg::Vec3f PhysicsSystem::getHalfExtents(const MWWorld::ConstPtr &actor) const
|
||||||
|
@ -772,16 +779,10 @@ namespace MWPhysics
|
||||||
const MWMechanics::MagicEffects& effects = character.getClass().getCreatureStats(character).getMagicEffects();
|
const MWMechanics::MagicEffects& effects = character.getClass().getCreatureStats(character).getMagicEffects();
|
||||||
|
|
||||||
bool waterCollision = false;
|
bool waterCollision = false;
|
||||||
bool moveToWaterSurface = false;
|
|
||||||
if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude())
|
if (cell->getCell()->hasWater() && effects.get(ESM::MagicEffect::WaterWalking).getMagnitude())
|
||||||
{
|
{
|
||||||
if (!world->isUnderwater(character.getCell(), osg::Vec3f(character.getRefData().getPosition().asVec3())))
|
if (physicActor->getCollisionMode() || !world->isUnderwater(character.getCell(), osg::Vec3f(character.getRefData().getPosition().asVec3())))
|
||||||
waterCollision = true;
|
waterCollision = true;
|
||||||
else if (physicActor->getCollisionMode() && canMoveToWaterSurface(character, waterlevel))
|
|
||||||
{
|
|
||||||
moveToWaterSurface = true;
|
|
||||||
waterCollision = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
physicActor->setCanWaterWalk(waterCollision);
|
physicActor->setCanWaterWalk(waterCollision);
|
||||||
|
@ -794,7 +795,7 @@ namespace MWPhysics
|
||||||
if (!willSimulate)
|
if (!willSimulate)
|
||||||
standingOn = physicActor->getStandingOnPtr();
|
standingOn = physicActor->getStandingOnPtr();
|
||||||
|
|
||||||
actorsFrameData.emplace_back(std::move(physicActor), standingOn, moveToWaterSurface, movement, slowFall, waterlevel);
|
actorsFrameData.emplace_back(std::move(physicActor), standingOn, waterCollision, movement, slowFall, waterlevel);
|
||||||
}
|
}
|
||||||
mMovementQueue.clear();
|
mMovementQueue.clear();
|
||||||
return actorsFrameData;
|
return actorsFrameData;
|
||||||
|
@ -937,9 +938,9 @@ namespace MWPhysics
|
||||||
}
|
}
|
||||||
|
|
||||||
ActorFrameData::ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn,
|
ActorFrameData::ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn,
|
||||||
bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel)
|
bool waterCollision, osg::Vec3f movement, float slowFall, float waterlevel)
|
||||||
: mActor(actor), mActorRaw(actor.get()), mStandingOn(standingOn),
|
: mActor(actor), mActorRaw(actor.get()), mStandingOn(standingOn),
|
||||||
mDidJump(false), mNeedLand(false), mMoveToWaterSurface(moveToWaterSurface),
|
mDidJump(false), mNeedLand(false), mWaterCollision(waterCollision),
|
||||||
mWaterlevel(waterlevel), mSlowFall(slowFall), mOldHeight(0), mFallHeight(0), mMovement(movement), mPosition(), mRefpos()
|
mWaterlevel(waterlevel), mSlowFall(slowFall), mOldHeight(0), mFallHeight(0), mMovement(movement), mPosition(), mRefpos()
|
||||||
{
|
{
|
||||||
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
const MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
@ -953,7 +954,7 @@ namespace MWPhysics
|
||||||
mWasOnGround = actor->getOnGround();
|
mWasOnGround = actor->getOnGround();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ActorFrameData::updatePosition()
|
void ActorFrameData::updatePosition(btCollisionWorld* world)
|
||||||
{
|
{
|
||||||
mActorRaw->updateWorldPosition();
|
mActorRaw->updateWorldPosition();
|
||||||
// If physics runs "fast enough", position are interpolated without simulation
|
// If physics runs "fast enough", position are interpolated without simulation
|
||||||
|
@ -961,10 +962,10 @@ namespace MWPhysics
|
||||||
// regardless of simulation speed.
|
// regardless of simulation speed.
|
||||||
mActorRaw->applyOffsetChange();
|
mActorRaw->applyOffsetChange();
|
||||||
mPosition = mActorRaw->getPosition();
|
mPosition = mActorRaw->getPosition();
|
||||||
if (mMoveToWaterSurface)
|
if (mWaterCollision && mPosition.z() < mWaterlevel && canMoveToWaterSurface(mActorRaw, mWaterlevel, world))
|
||||||
{
|
{
|
||||||
mPosition.z() = mWaterlevel;
|
mPosition.z() = mWaterlevel;
|
||||||
MWBase::Environment::get().getWorld()->moveObject(mActorRaw->getPtr(), mPosition.x(), mPosition.y(), mPosition.z());
|
MWBase::Environment::get().getWorld()->moveObject(mActorRaw->getPtr(), mPosition.x(), mPosition.y(), mPosition.z(), false);
|
||||||
}
|
}
|
||||||
mOldHeight = mPosition.z();
|
mOldHeight = mPosition.z();
|
||||||
mRefpos = mActorRaw->getPtr().getRefData().getPosition();
|
mRefpos = mActorRaw->getPtr().getRefData().getPosition();
|
||||||
|
|
|
@ -79,7 +79,7 @@ namespace MWPhysics
|
||||||
struct ActorFrameData
|
struct ActorFrameData
|
||||||
{
|
{
|
||||||
ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel);
|
ActorFrameData(const std::shared_ptr<Actor>& actor, const MWWorld::Ptr standingOn, bool moveToWaterSurface, osg::Vec3f movement, float slowFall, float waterlevel);
|
||||||
void updatePosition();
|
void updatePosition(btCollisionWorld* world);
|
||||||
std::weak_ptr<Actor> mActor;
|
std::weak_ptr<Actor> mActor;
|
||||||
Actor* mActorRaw;
|
Actor* mActorRaw;
|
||||||
MWWorld::Ptr mStandingOn;
|
MWWorld::Ptr mStandingOn;
|
||||||
|
@ -90,7 +90,7 @@ namespace MWPhysics
|
||||||
bool mDidJump;
|
bool mDidJump;
|
||||||
bool mFloatToSurface;
|
bool mFloatToSurface;
|
||||||
bool mNeedLand;
|
bool mNeedLand;
|
||||||
bool mMoveToWaterSurface;
|
bool mWaterCollision;
|
||||||
float mWaterlevel;
|
float mWaterlevel;
|
||||||
float mSlowFall;
|
float mSlowFall;
|
||||||
float mOldHeight;
|
float mOldHeight;
|
||||||
|
|
Loading…
Reference in a new issue