mirror of
https://github.com/TES3MP/TES3MP.git
synced 2025-09-23 20:48:16 -04:00
Merge branch 'smarterunstuck' into 'master'
Improve 'unstuck'ing code See merge request OpenMW/openmw!675
This commit is contained in:
commit
78894b6129
@ -159,6 +159,24 @@ namespace MWPhysics
|
|||||||
MWWorld::Ptr getStandingOnPtr() const;
|
MWWorld::Ptr getStandingOnPtr() const;
|
||||||
void setStandingOnPtr(const MWWorld::Ptr& ptr);
|
void setStandingOnPtr(const MWWorld::Ptr& ptr);
|
||||||
|
|
||||||
|
unsigned int getStuckFrames() const
|
||||||
|
{
|
||||||
|
return mStuckFrames;
|
||||||
|
}
|
||||||
|
void setStuckFrames(unsigned int frames)
|
||||||
|
{
|
||||||
|
mStuckFrames = frames;
|
||||||
|
}
|
||||||
|
|
||||||
|
const osg::Vec3f &getLastStuckPosition() const
|
||||||
|
{
|
||||||
|
return mLastStuckPosition;
|
||||||
|
}
|
||||||
|
void setLastStuckPosition(osg::Vec3f position)
|
||||||
|
{
|
||||||
|
mLastStuckPosition = position;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MWWorld::Ptr mStandingOnPtr;
|
MWWorld::Ptr mStandingOnPtr;
|
||||||
/// Removes then re-adds the collision object to the dynamics world
|
/// Removes then re-adds the collision object to the dynamics world
|
||||||
@ -192,6 +210,9 @@ namespace MWPhysics
|
|||||||
btTransform mLocalTransform;
|
btTransform mLocalTransform;
|
||||||
mutable std::mutex mPositionMutex;
|
mutable std::mutex mPositionMutex;
|
||||||
|
|
||||||
|
unsigned int mStuckFrames;
|
||||||
|
osg::Vec3f mLastStuckPosition;
|
||||||
|
|
||||||
osg::Vec3f mForce;
|
osg::Vec3f mForce;
|
||||||
std::atomic<bool> mOnGround;
|
std::atomic<bool> mOnGround;
|
||||||
std::atomic<bool> mOnSlope;
|
std::atomic<bool> mOnSlope;
|
||||||
|
@ -204,7 +204,7 @@ namespace MWPhysics
|
|||||||
osg::Vec3f lastSlideNormalFallback(0,0,1);
|
osg::Vec3f lastSlideNormalFallback(0,0,1);
|
||||||
bool forceGroundTest = false;
|
bool forceGroundTest = false;
|
||||||
|
|
||||||
for (int iterations = 0; iterations < sMaxIterations && remainingTime > 0.01f; ++iterations)
|
for (int iterations = 0; iterations < sMaxIterations && remainingTime > 0.0001f; ++iterations)
|
||||||
{
|
{
|
||||||
osg::Vec3f nextpos = newPosition + velocity * remainingTime;
|
osg::Vec3f nextpos = newPosition + velocity * remainingTime;
|
||||||
|
|
||||||
@ -394,6 +394,12 @@ namespace MWPhysics
|
|||||||
isOnGround = false;
|
isOnGround = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// forcibly treat stuck actors as if they're on flat ground because buggy collisions when inside of things can/will break ground detection
|
||||||
|
if(physicActor->getStuckFrames() > 0)
|
||||||
|
{
|
||||||
|
isOnGround = true;
|
||||||
|
isOnSlope = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if((isOnGround && !isOnSlope) || newPosition.z() < swimlevel || actor.mFlying)
|
if((isOnGround && !isOnSlope) || newPosition.z() < swimlevel || actor.mFlying)
|
||||||
@ -437,6 +443,17 @@ namespace MWPhysics
|
|||||||
auto* collisionObject = physicActor->getCollisionObject();
|
auto* collisionObject = physicActor->getCollisionObject();
|
||||||
auto tempPosition = actor.mPosition;
|
auto tempPosition = actor.mPosition;
|
||||||
|
|
||||||
|
if(physicActor->getStuckFrames() >= 10)
|
||||||
|
{
|
||||||
|
if((physicActor->getLastStuckPosition() - actor.mPosition).length2() < 100)
|
||||||
|
return;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
physicActor->setStuckFrames(0);
|
||||||
|
physicActor->setLastStuckPosition({0, 0, 0});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// use vanilla-accurate collision hull position hack (do same hitbox offset hack as movement solver)
|
// use vanilla-accurate collision hull position hack (do same hitbox offset hack as movement solver)
|
||||||
// if vanilla compatibility didn't matter, the "correct" collision hull position would be physicActor->getScaledMeshTranslation()
|
// if vanilla compatibility didn't matter, the "correct" collision hull position would be physicActor->getScaledMeshTranslation()
|
||||||
const auto verticalHalfExtent = osg::Vec3f(0.0, 0.0, physicActor->getHalfExtents().z());
|
const auto verticalHalfExtent = osg::Vec3f(0.0, 0.0, physicActor->getHalfExtents().z());
|
||||||
@ -470,6 +487,8 @@ namespace MWPhysics
|
|||||||
auto contactCallback = gatherContacts({0.0, 0.0, 0.0});
|
auto contactCallback = gatherContacts({0.0, 0.0, 0.0});
|
||||||
if(contactCallback.mDistance < -sAllowedPenetration)
|
if(contactCallback.mDistance < -sAllowedPenetration)
|
||||||
{
|
{
|
||||||
|
physicActor->setStuckFrames(physicActor->getStuckFrames() + 1);
|
||||||
|
physicActor->setLastStuckPosition(actor.mPosition);
|
||||||
// we are; try moving it out of the world
|
// we are; try moving it out of the world
|
||||||
auto positionDelta = contactCallback.mContactSum;
|
auto positionDelta = contactCallback.mContactSum;
|
||||||
// limit rejection delta to the largest known individual rejections
|
// limit rejection delta to the largest known individual rejections
|
||||||
@ -502,6 +521,11 @@ namespace MWPhysics
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
physicActor->setStuckFrames(0);
|
||||||
|
physicActor->setLastStuckPosition({0, 0, 0});
|
||||||
|
}
|
||||||
|
|
||||||
collisionObject->setWorldTransform(oldTransform);
|
collisionObject->setWorldTransform(oldTransform);
|
||||||
actor.mPosition = tempPosition;
|
actor.mPosition = tempPosition;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user