@ -2386,50 +2386,56 @@ namespace MWMechanics
}
}
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 ;
moved . y ( ) * = scale ;
osg : : Vec3f movementFromAnimation
= mAnimation - > runAnimation ( mSkipAnim & & ! isScriptedAnimPlaying ( ) ? 0.f : duration ) ;
// Ensure we're moving in generally the right direction...
if ( speed > 0.f & & moved ! = osg : : Vec3f ( ) )
if ( mPtr . getClass ( ) . isActor ( ) & & isMovementAnimationControlled ( ) & & ! isScriptedAnimPlaying ( ) )
{
float l = moved . length ( ) ;
if ( std : : abs ( movement . x ( ) - moved . x ( ) ) > std : : abs ( moved . x ( ) ) / 2
| | std : : abs ( movement . y ( ) - moved . y ( ) ) > std : : abs ( moved . y ( ) ) / 2
| | std : : abs ( movement . z ( ) - moved . z ( ) ) > std : : abs ( moved . z ( ) ) / 2 )
{
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 ( duration > 0.0f )
movementFromAnimation / = duration ;
else
movementFromAnimation = osg : : Vec3f ( 0.f , 0.f , 0.f ) ;
movementFromAnimation . x ( ) * = scale ;
movementFromAnimation . y ( ) * = scale ;
if ( speed > 0.f & & movementFromAnimation ! = osg : : Vec3f ( ) )
{
// 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
// frame will, and therefore we have to determine the direction based on the currently playing cycle
// instead.
float animMovementAngle = getAnimationMovementDirection ( ) ;
float targetMovementAngle = std : : atan2 ( - movement . x ( ) , movement . y ( ) ) ;
float diff = targetMovementAngle - animMovementAngle ;
movementFromAnimation = osg : : Quat ( diff , osg : : Vec3f ( 0 , 0 , 1 ) ) * movementFromAnimation ;
}
if ( ! ( isPlayer & & Settings : : game ( ) . mPlayerMovementIgnoresAnimation ) )
movement = movementFromAnimation ;
if ( mFloatToSurface )
{
if ( cls . getCreatureStats ( mPtr ) . isDead ( )
| | ( ! godmode
& & cls . getCreatureStats ( mPtr )
. getMagicEffects ( )
. getOrDefault ( ESM : : MagicEffect : : Paralyze )
. getModifier ( )
> 0 ) )
{
movement . z ( ) = 1.0 ;
}
}
}
if ( mFloatToSurface & & cls . isActor ( ) )
{
if ( cls . getCreatureStats ( mPtr ) . isDead ( )
| | ( ! godmode
& & cls . getCreatureStats ( mPtr )
. getMagicEffects ( )
. getOrDefault ( ESM : : MagicEffect : : Paralyze )
. getModifier ( )
> 0 ) )
{
moved . z ( ) = 1.0 ;
}
// Update movement
world - > queueMovement ( mPtr , movement ) ;
}
// Update movement
if ( isMovementAnimationControlled ( ) & & mPtr . getClass ( ) . isActor ( ) & & ! isScriptedAnimPlaying ( ) )
world - > queueMovement ( mPtr , moved ) ;
mSkipAnim = false ;
mAnimation - > enableHeadAnimation ( cls . isActor ( ) & & ! cls . getCreatureStats ( mPtr ) . isDead ( ) ) ;
@ -2909,6 +2915,39 @@ namespace MWMechanics
MWBase : : Environment : : get ( ) . getSoundManager ( ) - > playSound3D ( mPtr , * soundId , volume , pitch ) ;
}
float CharacterController : : getAnimationMovementDirection ( ) const
{
switch ( mMovementState )
{
case CharState_RunLeft :
case CharState_SneakLeft :
case CharState_SwimWalkLeft :
case CharState_SwimRunLeft :
case CharState_WalkLeft :
return osg : : PI_2f ;
case CharState_RunRight :
case CharState_SneakRight :
case CharState_SwimWalkRight :
case CharState_SwimRunRight :
case CharState_WalkRight :
return - osg : : PI_2f ;
case CharState_RunForward :
case CharState_SneakForward :
case CharState_SwimRunForward :
case CharState_SwimWalkForward :
case CharState_WalkForward :
return mAnimation - > getLegsYawRadians ( ) ;
case CharState_RunBack :
case CharState_SneakBack :
case CharState_SwimWalkBack :
case CharState_SwimRunBack :
case CharState_WalkBack :
return mAnimation - > getLegsYawRadians ( ) - osg : : PIf ;
default :
return 0.0f ;
}
}
void CharacterController : : updateHeadTracking ( float duration )
{
const osg : : Node * head = mAnimation - > getNode ( " Bip01 Head " ) ;