mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-03-25 16:43:33 +00:00
Use accumulated movement whenever possible. Apply diagonal movement by rotating accumulated movement and sliding based on that, rather than ignoring accumulated movement.
This commit is contained in:
parent
93b723a066
commit
f41de6b02d
@ -2387,48 +2387,72 @@ namespace MWMechanics
|
|||||||
}
|
}
|
||||||
|
|
||||||
osg::Vec3f moved = mAnimation->runAnimation(mSkipAnim && !isScriptedAnimPlaying() ? 0.f : duration);
|
osg::Vec3f moved = mAnimation->runAnimation(mSkipAnim && !isScriptedAnimPlaying() ? 0.f : duration);
|
||||||
if (duration > 0.0f)
|
|
||||||
moved /= duration;
|
|
||||||
else
|
|
||||||
moved = osg::Vec3f(0.f, 0.f, 0.f);
|
|
||||||
|
|
||||||
moved.x() *= scale;
|
if (mPtr.getClass().isActor() && isMovementAnimationControlled() && !isScriptedAnimPlaying())
|
||||||
moved.y() *= scale;
|
|
||||||
|
|
||||||
// Ensure we're moving in generally the right direction...
|
|
||||||
if (speed > 0.f && moved != osg::Vec3f())
|
|
||||||
{
|
{
|
||||||
float l = moved.length();
|
if (duration > 0.0f)
|
||||||
if (std::abs(movement.x() - moved.x()) > std::abs(moved.x()) / 2
|
moved /= duration;
|
||||||
|| std::abs(movement.y() - moved.y()) > std::abs(moved.y()) / 2
|
else
|
||||||
|| std::abs(movement.z() - moved.z()) > std::abs(moved.z()) / 2)
|
moved = osg::Vec3f(0.f, 0.f, 0.f);
|
||||||
{
|
|
||||||
moved = movement;
|
|
||||||
// For some creatures getSpeed doesn't work, so we adjust speed to the animation.
|
|
||||||
// TODO: Fix Creature::getSpeed.
|
|
||||||
float newLength = moved.length();
|
|
||||||
if (newLength > 0 && !cls.isNpc())
|
|
||||||
moved *= (l / newLength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mFloatToSurface && cls.isActor())
|
moved.x() *= scale;
|
||||||
{
|
moved.y() *= scale;
|
||||||
if (cls.getCreatureStats(mPtr).isDead()
|
|
||||||
|| (!godmode
|
|
||||||
&& cls.getCreatureStats(mPtr)
|
|
||||||
.getMagicEffects()
|
|
||||||
.getOrDefault(ESM::MagicEffect::Paralyze)
|
|
||||||
.getModifier()
|
|
||||||
> 0))
|
|
||||||
{
|
|
||||||
moved.z() = 1.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update movement
|
if (speed > 0.f && moved != osg::Vec3f())
|
||||||
if (isMovementAnimationControlled() && mPtr.getClass().isActor() && !isScriptedAnimPlaying())
|
{
|
||||||
|
// Ensure we're moving in generally the right direction
|
||||||
|
// This is necessary when the "turn to movement direction" feature is off, as animations
|
||||||
|
// will not be rotated to match diagonal movement. In this case we have to slide the
|
||||||
|
// character diagonally.
|
||||||
|
|
||||||
|
// First decide the general direction expected from the current animation
|
||||||
|
float animMovementAngle = 0;
|
||||||
|
if (!Settings::game().mTurnToMovementDirection || isFirstPersonPlayer)
|
||||||
|
{
|
||||||
|
if (cls.getMovementSettings(mPtr).mIsStrafing)
|
||||||
|
animMovementAngle = movement.x() > 0 ? -osg::PI_2f : osg::PI_2f;
|
||||||
|
else
|
||||||
|
animMovementAngle = movement.y() >= 0 ? 0 : -osg::PIf;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
animMovementAngle = mAnimation->getLegsYawRadians();
|
||||||
|
if (movement.y() < 0)
|
||||||
|
animMovementAngle -= osg::PIf;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float epsilon = 0.001f;
|
||||||
|
float targetMovementAngle = std::atan2(-movement.x(), movement.y());
|
||||||
|
float diff = targetMovementAngle - animMovementAngle;
|
||||||
|
if (std::fabsf(diff) > epsilon)
|
||||||
|
{
|
||||||
|
moved = osg::Quat(diff, osg::Vec3f(0, 0, 1)) * moved;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPlayer && Settings::game().mPlayerMovementIgnoresAnimation)
|
||||||
|
{
|
||||||
|
moved = movement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFloatToSurface)
|
||||||
|
{
|
||||||
|
if (cls.getCreatureStats(mPtr).isDead()
|
||||||
|
|| (!godmode
|
||||||
|
&& cls.getCreatureStats(mPtr)
|
||||||
|
.getMagicEffects()
|
||||||
|
.getOrDefault(ESM::MagicEffect::Paralyze)
|
||||||
|
.getModifier()
|
||||||
|
> 0))
|
||||||
|
{
|
||||||
|
moved.z() = 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update movement
|
||||||
|
&& !isScriptedAnimPlaying()
|
||||||
world->queueMovement(mPtr, moved);
|
world->queueMovement(mPtr, moved);
|
||||||
|
}
|
||||||
|
|
||||||
mSkipAnim = false;
|
mSkipAnim = false;
|
||||||
|
|
||||||
|
@ -74,6 +74,7 @@ namespace Settings
|
|||||||
"unarmed creature attacks damage armor" };
|
"unarmed creature attacks damage armor" };
|
||||||
SettingValue<DetourNavigator::CollisionShapeType> mActorCollisionShapeType{ mIndex, "Game",
|
SettingValue<DetourNavigator::CollisionShapeType> mActorCollisionShapeType{ mIndex, "Game",
|
||||||
"actor collision shape type" };
|
"actor collision shape type" };
|
||||||
|
SettingValue<bool> mPlayerMovementIgnoresAnimation{ mIndex, "Game", "player movement ignores animation" };
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,6 +365,11 @@ unarmed creature attacks damage armor = false
|
|||||||
# 2 = Cylinder
|
# 2 = Cylinder
|
||||||
actor collision shape type = 0
|
actor collision shape type = 0
|
||||||
|
|
||||||
|
# When false the player character will base movement on animations. This will sway the camera
|
||||||
|
# while moving in third person like in vanilla, and reproduce movement bugs caused by glitchy
|
||||||
|
# vanilla animations.
|
||||||
|
player movement ignores animation = false
|
||||||
|
|
||||||
[General]
|
[General]
|
||||||
|
|
||||||
# Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16).
|
# Anisotropy reduces distortion in textures at low angles (e.g. 0 to 16).
|
||||||
|
Loading…
x
Reference in New Issue
Block a user