forked from teamnwah/openmw-tes3coop
Merge pull request #1701 from akortunov/standfix
Do not apply queue movement for standing actors
This commit is contained in:
commit
da47fc79f5
11 changed files with 63 additions and 8 deletions
|
@ -391,6 +391,7 @@ namespace MWBase
|
||||||
virtual bool isUnderwater(const MWWorld::ConstPtr &object, const float heightRatio) const = 0;
|
virtual bool isUnderwater(const MWWorld::ConstPtr &object, const float heightRatio) const = 0;
|
||||||
virtual bool isWaterWalkingCastableOnTarget(const MWWorld::ConstPtr &target) const = 0;
|
virtual bool isWaterWalkingCastableOnTarget(const MWWorld::ConstPtr &target) const = 0;
|
||||||
virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0;
|
virtual bool isOnGround(const MWWorld::Ptr &ptr) const = 0;
|
||||||
|
virtual bool isIdle(const MWWorld::Ptr &ptr) const = 0;
|
||||||
|
|
||||||
virtual osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const = 0;
|
virtual osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const = 0;
|
||||||
|
|
||||||
|
|
|
@ -866,8 +866,7 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
// place above to prevent moving inside objects, e.g. stairs, because a vector between pathgrids can be underground.
|
// place above to prevent moving inside objects, e.g. stairs, because a vector between pathgrids can be underground.
|
||||||
// Adding 20 in adjustPosition() is not enough.
|
dest.mZ += 80;
|
||||||
dest.mZ += 60;
|
|
||||||
|
|
||||||
ToWorldCoordinates(dest, actor.getCell()->getCell());
|
ToWorldCoordinates(dest, actor.getCell()->getCell());
|
||||||
|
|
||||||
|
|
|
@ -2036,7 +2036,8 @@ void CharacterController::update(float duration)
|
||||||
moved.z() = 1.0;
|
moved.z() = 1.0;
|
||||||
|
|
||||||
// Update movement
|
// Update movement
|
||||||
if(mMovementAnimationControlled && mPtr.getClass().isActor())
|
// We should not apply movement for standing actors
|
||||||
|
if(mMovementAnimationControlled && mPtr.getClass().isActor() && (movement.length2() > 0.f || !world->isIdle(mPtr)))
|
||||||
world->queueMovement(mPtr, moved);
|
world->queueMovement(mPtr, moved);
|
||||||
|
|
||||||
mSkipAnim = false;
|
mSkipAnim = false;
|
||||||
|
|
|
@ -18,7 +18,7 @@ namespace MWPhysics
|
||||||
|
|
||||||
Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<const Resource::BulletShape> shape, btCollisionWorld* world)
|
Actor::Actor(const MWWorld::Ptr& ptr, osg::ref_ptr<const Resource::BulletShape> shape, btCollisionWorld* world)
|
||||||
: mCanWaterWalk(false), mWalkingOnWater(false)
|
: mCanWaterWalk(false), mWalkingOnWater(false)
|
||||||
, mCollisionObject(nullptr), mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false)
|
, mCollisionObject(nullptr), mForce(0.f, 0.f, 0.f), mOnGround(true), mOnSlope(false), mIdle(true)
|
||||||
, mInternalCollisionMode(true)
|
, mInternalCollisionMode(true)
|
||||||
, mExternalCollisionMode(true)
|
, mExternalCollisionMode(true)
|
||||||
, mCollisionWorld(world)
|
, mCollisionWorld(world)
|
||||||
|
@ -195,6 +195,11 @@ void Actor::setOnSlope(bool slope)
|
||||||
mOnSlope = slope;
|
mOnSlope = slope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Actor::setIdle(bool idle)
|
||||||
|
{
|
||||||
|
mIdle = idle;
|
||||||
|
}
|
||||||
|
|
||||||
bool Actor::isWalkingOnWater() const
|
bool Actor::isWalkingOnWater() const
|
||||||
{
|
{
|
||||||
return mWalkingOnWater;
|
return mWalkingOnWater;
|
||||||
|
|
|
@ -139,6 +139,13 @@ namespace MWPhysics
|
||||||
return mInternalCollisionMode && mOnSlope;
|
return mInternalCollisionMode && mOnSlope;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setIdle(bool idle);
|
||||||
|
|
||||||
|
bool getIdle() const
|
||||||
|
{
|
||||||
|
return mIdle;
|
||||||
|
}
|
||||||
|
|
||||||
btCollisionObject* getCollisionObject() const
|
btCollisionObject* getCollisionObject() const
|
||||||
{
|
{
|
||||||
return mCollisionObject.get();
|
return mCollisionObject.get();
|
||||||
|
@ -179,6 +186,7 @@ namespace MWPhysics
|
||||||
osg::Vec3f mForce;
|
osg::Vec3f mForce;
|
||||||
bool mOnGround;
|
bool mOnGround;
|
||||||
bool mOnSlope;
|
bool mOnSlope;
|
||||||
|
bool mIdle;
|
||||||
bool mInternalCollisionMode;
|
bool mInternalCollisionMode;
|
||||||
bool mExternalCollisionMode;
|
bool mExternalCollisionMode;
|
||||||
|
|
||||||
|
|
|
@ -249,7 +249,7 @@ namespace MWPhysics
|
||||||
// Check if we actually found a valid spawn point (use an infinitely thin ray this time).
|
// Check if we actually found a valid spawn point (use an infinitely thin ray this time).
|
||||||
// Required for some broken door destinations in Morrowind.esm, where the spawn point
|
// Required for some broken door destinations in Morrowind.esm, where the spawn point
|
||||||
// intersects with other geometry if the actor's base is taken into account
|
// intersects with other geometry if the actor's base is taken into account
|
||||||
btVector3 from = toBullet(position);
|
btVector3 from = toBullet(position + offset);
|
||||||
btVector3 to = from - btVector3(0,0,maxHeight);
|
btVector3 to = from - btVector3(0,0,maxHeight);
|
||||||
|
|
||||||
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
btCollisionWorld::ClosestRayResultCallback resultCallback1(from, to);
|
||||||
|
@ -683,6 +683,7 @@ namespace MWPhysics
|
||||||
, mWaterEnabled(false)
|
, mWaterEnabled(false)
|
||||||
, mParentNode(parentNode)
|
, mParentNode(parentNode)
|
||||||
, mPhysicsDt(1.f / 60.f)
|
, mPhysicsDt(1.f / 60.f)
|
||||||
|
, mIdleUpdateTimer(0)
|
||||||
{
|
{
|
||||||
mResourceSystem->addResourceManager(mShapeManager.get());
|
mResourceSystem->addResourceManager(mShapeManager.get());
|
||||||
|
|
||||||
|
@ -739,6 +740,18 @@ namespace MWPhysics
|
||||||
delete mBroadphase;
|
delete mBroadphase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PhysicsSystem::updateIdle()
|
||||||
|
{
|
||||||
|
for (ActorMap::iterator it = mActors.begin(); it != mActors.end(); ++it)
|
||||||
|
{
|
||||||
|
osg::Vec3f pos(it->second->getCollisionObjectPosition());
|
||||||
|
|
||||||
|
RayResult result = castRay(pos, pos - osg::Vec3f(0, 0, it->second->getHalfExtents().z() + 2), it->second->getPtr(), std::vector<MWWorld::Ptr>(), CollisionType_World|CollisionType_HeightMap|CollisionType_Door);
|
||||||
|
|
||||||
|
it->second->setIdle(result.mHit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PhysicsSystem::setUnrefQueue(SceneUtil::UnrefQueue *unrefQueue)
|
void PhysicsSystem::setUnrefQueue(SceneUtil::UnrefQueue *unrefQueue)
|
||||||
{
|
{
|
||||||
mUnrefQueue = unrefQueue;
|
mUnrefQueue = unrefQueue;
|
||||||
|
@ -1045,6 +1058,11 @@ namespace MWPhysics
|
||||||
return physactor && physactor->getOnGround();
|
return physactor && physactor->getOnGround();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PhysicsSystem::isIdle(const MWWorld::Ptr &actor)
|
||||||
|
{
|
||||||
|
Actor* physactor = getActor(actor);
|
||||||
|
return physactor && physactor->getIdle();
|
||||||
|
}
|
||||||
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);
|
const Actor* physicActor = getActor(actor);
|
||||||
|
@ -1337,6 +1355,10 @@ namespace MWPhysics
|
||||||
cmode = !cmode;
|
cmode = !cmode;
|
||||||
found->second->enableCollisionMode(cmode);
|
found->second->enableCollisionMode(cmode);
|
||||||
found->second->enableCollisionBody(cmode);
|
found->second->enableCollisionBody(cmode);
|
||||||
|
|
||||||
|
if (cmode)
|
||||||
|
queueObjectMovement(MWMechanics::getPlayer(), osg::Vec3f(0, 0, -0.1f));
|
||||||
|
|
||||||
return cmode;
|
return cmode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1456,6 +1478,13 @@ namespace MWPhysics
|
||||||
for (std::set<Object*>::iterator it = mAnimatedObjects.begin(); it != mAnimatedObjects.end(); ++it)
|
for (std::set<Object*>::iterator it = mAnimatedObjects.begin(); it != mAnimatedObjects.end(); ++it)
|
||||||
(*it)->animateCollisionShapes(mCollisionWorld);
|
(*it)->animateCollisionShapes(mCollisionWorld);
|
||||||
|
|
||||||
|
mIdleUpdateTimer -= dt;
|
||||||
|
if (mIdleUpdateTimer <= 0.f)
|
||||||
|
{
|
||||||
|
mIdleUpdateTimer = 0.5f;
|
||||||
|
updateIdle();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef BT_NO_PROFILE
|
#ifndef BT_NO_PROFILE
|
||||||
CProfileManager::Reset();
|
CProfileManager::Reset();
|
||||||
CProfileManager::Increment_Frame_Counter();
|
CProfileManager::Increment_Frame_Counter();
|
||||||
|
|
|
@ -124,6 +124,7 @@ namespace MWPhysics
|
||||||
bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const;
|
bool getLineOfSight(const MWWorld::ConstPtr& actor1, const MWWorld::ConstPtr& actor2) const;
|
||||||
|
|
||||||
bool isOnGround (const MWWorld::Ptr& actor);
|
bool isOnGround (const MWWorld::Ptr& actor);
|
||||||
|
bool isIdle (const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
bool canMoveToWaterSurface (const MWWorld::ConstPtr &actor, const float waterlevel);
|
bool canMoveToWaterSurface (const MWWorld::ConstPtr &actor, const float waterlevel);
|
||||||
|
|
||||||
|
@ -173,6 +174,7 @@ namespace MWPhysics
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void updateWater();
|
void updateWater();
|
||||||
|
void updateIdle();
|
||||||
|
|
||||||
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
osg::ref_ptr<SceneUtil::UnrefQueue> mUnrefQueue;
|
||||||
|
|
||||||
|
@ -221,6 +223,7 @@ namespace MWPhysics
|
||||||
osg::ref_ptr<osg::Group> mParentNode;
|
osg::ref_ptr<osg::Group> mParentNode;
|
||||||
|
|
||||||
float mPhysicsDt;
|
float mPhysicsDt;
|
||||||
|
float mIdleUpdateTimer;
|
||||||
|
|
||||||
PhysicsSystem (const PhysicsSystem&);
|
PhysicsSystem (const PhysicsSystem&);
|
||||||
PhysicsSystem& operator= (const PhysicsSystem&);
|
PhysicsSystem& operator= (const PhysicsSystem&);
|
||||||
|
|
|
@ -701,6 +701,8 @@ namespace MWScript
|
||||||
|
|
||||||
virtual void execute (Interpreter::Runtime& runtime)
|
virtual void execute (Interpreter::Runtime& runtime)
|
||||||
{
|
{
|
||||||
|
MWWorld::Ptr ptr = R()(runtime);
|
||||||
|
MWBase::Environment::get().getWorld()->queueMovement(ptr, osg::Vec3f(0, 0, -0.1f));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -506,7 +506,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
||||||
if (firstPersonCam != MWBase::Environment::get().getWorld()->isFirstPerson())
|
if (firstPersonCam != MWBase::Environment::get().getWorld()->isFirstPerson())
|
||||||
MWBase::Environment::get().getWorld()->togglePOV();
|
MWBase::Environment::get().getWorld()->togglePOV();
|
||||||
|
|
||||||
MWWorld::ConstPtr ptr = MWMechanics::getPlayer();
|
const MWWorld::Ptr ptr = MWMechanics::getPlayer();
|
||||||
|
|
||||||
if (ptr.isInCell())
|
if (ptr.isInCell())
|
||||||
{
|
{
|
||||||
|
@ -538,6 +538,9 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
||||||
// Since we passed "changeEvent=false" to changeCell, we shouldn't have triggered the cell change flag.
|
// Since we passed "changeEvent=false" to changeCell, we shouldn't have triggered the cell change flag.
|
||||||
// But make sure the flag is cleared anyway in case it was set from an earlier game.
|
// But make sure the flag is cleared anyway in case it was set from an earlier game.
|
||||||
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
||||||
|
|
||||||
|
// Workaround to fix camera position upon game load
|
||||||
|
MWBase::Environment::get().getWorld()->queueMovement(ptr, osg::Vec3f(0, 0, 0));
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1314,8 +1314,6 @@ namespace MWWorld
|
||||||
if (pos.z() < terrainHeight)
|
if (pos.z() < terrainHeight)
|
||||||
pos.z() = terrainHeight;
|
pos.z() = terrainHeight;
|
||||||
|
|
||||||
pos.z() += 20; // place slightly above. will snap down to ground with code below
|
|
||||||
|
|
||||||
if (force || !isFlying(ptr))
|
if (force || !isFlying(ptr))
|
||||||
{
|
{
|
||||||
osg::Vec3f traced = mPhysics->traceDown(ptr, pos, 500);
|
osg::Vec3f traced = mPhysics->traceDown(ptr, pos, 500);
|
||||||
|
@ -2162,6 +2160,11 @@ namespace MWWorld
|
||||||
return mPhysics->isOnGround(ptr);
|
return mPhysics->isOnGround(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool World::isIdle(const MWWorld::Ptr &ptr) const
|
||||||
|
{
|
||||||
|
return mPhysics->isIdle(ptr);
|
||||||
|
}
|
||||||
|
|
||||||
void World::togglePOV()
|
void World::togglePOV()
|
||||||
{
|
{
|
||||||
mRendering->togglePOV();
|
mRendering->togglePOV();
|
||||||
|
|
|
@ -489,6 +489,7 @@ namespace MWWorld
|
||||||
bool isWading(const MWWorld::ConstPtr &object) const override;
|
bool isWading(const MWWorld::ConstPtr &object) const override;
|
||||||
bool isWaterWalkingCastableOnTarget(const MWWorld::ConstPtr &target) const override;
|
bool isWaterWalkingCastableOnTarget(const MWWorld::ConstPtr &target) const override;
|
||||||
bool isOnGround(const MWWorld::Ptr &ptr) const override;
|
bool isOnGround(const MWWorld::Ptr &ptr) const override;
|
||||||
|
bool isIdle(const MWWorld::Ptr &ptr) const override;
|
||||||
|
|
||||||
osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const override;
|
osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const override;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue