mirror of
https://github.com/OpenMW/openmw.git
synced 2025-05-02 12:41:24 +00:00
CharacterController: rework movement queueing logic (#7835)
This commit is contained in:
parent
a297a0e742
commit
41d41780a8
1 changed files with 49 additions and 39 deletions
|
@ -2237,8 +2237,6 @@ namespace MWMechanics
|
||||||
if (mAnimation->isPlaying(mCurrentJump))
|
if (mAnimation->isPlaying(mCurrentJump))
|
||||||
jumpstate = JumpState_Landing;
|
jumpstate = JumpState_Landing;
|
||||||
|
|
||||||
vec.x() *= scale;
|
|
||||||
vec.y() *= scale;
|
|
||||||
vec.z() = 0.0f;
|
vec.z() = 0.0f;
|
||||||
|
|
||||||
if (movementSettings.mIsStrafing)
|
if (movementSettings.mIsStrafing)
|
||||||
|
@ -2371,6 +2369,7 @@ namespace MWMechanics
|
||||||
const float speedMult = speed / mMovementAnimSpeed;
|
const float speedMult = speed / mMovementAnimSpeed;
|
||||||
mAnimation->adjustSpeedMult(mCurrentMovement, std::min(maxSpeedMult, speedMult));
|
mAnimation->adjustSpeedMult(mCurrentMovement, std::min(maxSpeedMult, speedMult));
|
||||||
// Make sure the actual speed is the "expected" speed even though the animation is slower
|
// Make sure the actual speed is the "expected" speed even though the animation is slower
|
||||||
|
if (isMovementAnimationControlled())
|
||||||
scale *= std::max(1.f, speedMult / maxSpeedMult);
|
scale *= std::max(1.f, speedMult / maxSpeedMult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2390,20 +2389,17 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isMovementAnimationControlled() && !isScriptedAnimPlaying())
|
updateHeadTracking(duration);
|
||||||
world->queueMovement(mPtr, vec);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
movement = vec;
|
movement = vec;
|
||||||
movementSettings.mPosition[0] = movementSettings.mPosition[1] = 0;
|
movementSettings.mPosition[0] = movementSettings.mPosition[1] = 0;
|
||||||
|
|
||||||
|
// Can't reset jump state (mPosition[2]) here in full; we don't know for sure whether the PhysicsSystem will
|
||||||
|
// actually handle it in this frame due to the fixed minimum timestep used for the physics update. It will
|
||||||
|
// be reset in PhysicsSystem::move once the jump is handled.
|
||||||
if (movement.z() == 0.f)
|
if (movement.z() == 0.f)
|
||||||
movementSettings.mPosition[2] = 0;
|
movementSettings.mPosition[2] = 0;
|
||||||
// Can't reset jump state (mPosition[2]) here in full; we don't know for sure whether the PhysicSystem will
|
|
||||||
// actually handle it in this frame due to the fixed minimum timestep used for the physics update. It will
|
|
||||||
// be reset in PhysicSystem::move once the jump is handled.
|
|
||||||
|
|
||||||
if (!mSkipAnim)
|
|
||||||
updateHeadTracking(duration);
|
|
||||||
}
|
}
|
||||||
else if (cls.getCreatureStats(mPtr).isDead())
|
else if (cls.getCreatureStats(mPtr).isDead())
|
||||||
{
|
{
|
||||||
|
@ -2420,34 +2416,41 @@ namespace MWMechanics
|
||||||
osg::Vec3f movementFromAnimation
|
osg::Vec3f movementFromAnimation
|
||||||
= mAnimation->runAnimation(mSkipAnim && !isScriptedAnimPlaying() ? 0.f : duration);
|
= mAnimation->runAnimation(mSkipAnim && !isScriptedAnimPlaying() ? 0.f : duration);
|
||||||
|
|
||||||
if (mPtr.getClass().isActor() && isMovementAnimationControlled() && !isScriptedAnimPlaying())
|
if (mPtr.getClass().isActor() && !isScriptedAnimPlaying())
|
||||||
|
{
|
||||||
|
if (isMovementAnimationControlled())
|
||||||
|
{
|
||||||
|
if (duration != 0.f && movementFromAnimation != osg::Vec3f())
|
||||||
{
|
{
|
||||||
if (duration > 0.0f)
|
|
||||||
movementFromAnimation /= duration;
|
movementFromAnimation /= duration;
|
||||||
else
|
|
||||||
movementFromAnimation = osg::Vec3f(0.f, 0.f, 0.f);
|
|
||||||
|
|
||||||
movementFromAnimation.x() *= scale;
|
// Ensure we're moving in the right general direction.
|
||||||
movementFromAnimation.y() *= scale;
|
// In vanilla, all horizontal movement is taken from animations, even when moving diagonally (which
|
||||||
|
// doesn't have a corresponding animation). So to achieve diagonal movement, we have to rotate the
|
||||||
if (speed > 0.f && movementFromAnimation != osg::Vec3f())
|
// movement taken from the animation to the intended direction.
|
||||||
{
|
|
||||||
// Ensure we're moving in the right general direction. In vanilla, all horizontal movement is taken from
|
|
||||||
// animations, even when moving diagonally (which doesn't have a corresponding animation). So to acheive
|
|
||||||
// diagonal movement, we have to rotate the movement taken from the animation to the intended
|
|
||||||
// direction.
|
|
||||||
//
|
//
|
||||||
// Note that while a complete movement animation cycle will have a well defined direction, no individual
|
// Note that while a complete movement animation cycle will have a well defined direction, no
|
||||||
// frame will, and therefore we have to determine the direction based on the currently playing cycle
|
// individual frame will, and therefore we have to determine the direction based on the currently
|
||||||
// instead.
|
// playing cycle instead.
|
||||||
|
if (speed > 0.f)
|
||||||
|
{
|
||||||
float animMovementAngle = getAnimationMovementDirection();
|
float animMovementAngle = getAnimationMovementDirection();
|
||||||
float targetMovementAngle = std::atan2(-movement.x(), movement.y());
|
float targetMovementAngle = std::atan2(-movement.x(), movement.y());
|
||||||
float diff = targetMovementAngle - animMovementAngle;
|
float diff = targetMovementAngle - animMovementAngle;
|
||||||
movementFromAnimation = osg::Quat(diff, osg::Vec3f(0, 0, 1)) * movementFromAnimation;
|
movementFromAnimation = osg::Quat(diff, osg::Vec3f(0, 0, 1)) * movementFromAnimation;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(isPlayer && Settings::game().mPlayerMovementIgnoresAnimation))
|
|
||||||
movement = movementFromAnimation;
|
movement = movementFromAnimation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
movement = osg::Vec3f();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mSkipAnim)
|
||||||
|
{
|
||||||
|
movement = osg::Vec3f();
|
||||||
|
}
|
||||||
|
|
||||||
if (mFloatToSurface)
|
if (mFloatToSurface)
|
||||||
{
|
{
|
||||||
|
@ -2463,7 +2466,10 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
movement.x() *= scale;
|
||||||
|
movement.y() *= scale;
|
||||||
// Update movement
|
// Update movement
|
||||||
|
if (movement != osg::Vec3f())
|
||||||
world->queueMovement(mPtr, movement);
|
world->queueMovement(mPtr, movement);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2681,11 +2687,15 @@ namespace MWMechanics
|
||||||
|
|
||||||
bool CharacterController::isMovementAnimationControlled() const
|
bool CharacterController::isMovementAnimationControlled() const
|
||||||
{
|
{
|
||||||
|
if (Settings::game().mPlayerMovementIgnoresAnimation && mPtr == getPlayer())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (mInJump)
|
||||||
|
return false;
|
||||||
|
|
||||||
bool movementAnimationControlled = mIdleState != CharState_None;
|
bool movementAnimationControlled = mIdleState != CharState_None;
|
||||||
if (mMovementState != CharState_None)
|
if (mMovementState != CharState_None)
|
||||||
movementAnimationControlled = mMovementAnimationHasMovement;
|
movementAnimationControlled = mMovementAnimationHasMovement;
|
||||||
if (mInJump)
|
|
||||||
movementAnimationControlled = false;
|
|
||||||
return movementAnimationControlled;
|
return movementAnimationControlled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue