From OpenMW Wiki
Jump to navigation Jump to search




Actions affected Movement
Description Describes an actor's movement speed for each mode of movement. Uses common term normalizedEncumbrance.
Implementation status changed since last implementation
Analysis status Still has further interactions with physics

Actor target speeds[edit]

Passed to the animation system, as well as used for AI target leading. <syntaxhighlight lang="python"> if actor is a npc:

   walkSpeed = fMinWalkSpeed + 0.01 * speedAttribute * (fMaxWalkSpeed - fMinWalkSpeed)
   walkSpeed *= 1 - fEncumberedMoveEffect * normalizedEncumbrance
   walkSpeed = max(0, walkSpeed)
   if sneaking: walkSpeed *= fSneakSpeedMultiplier

elif actor is a creature:

   walkSpeed = fMinWalkSpeedCreature + 0.01 * speedAttribute * (fMaxWalkSpeedCreature - fMinWalkSpeedCreature)

runSpeed = walkSpeed * (0.01 * athleticsSkill * fAthleticsRunBonus + fBaseRunMultiplier)

if encumbrance > maxEncumbrance:

   moveSpeed = 0

elif flying or levitating:

   flySpeed = 0.01 * (speedAttribute + levitationBonus)
   flySpeed = fMinFlySpeed + flySpeed * (fMaxFlySpeed - fMinFlySpeed)
   flySpeed *= 1 - fEncumberedMoveEffect * normalizedEncumbrance
   flySpeed = max(0, flySpeed)
   moveSpeed = flySpeed

elif swimming:

   if running mode is on:
       swimSpeed = runSpeed
       swimSpeed = walkSpeed
   swimSpeed *= 1 + 0.01 * swiftSwimBonus
   swimSpeed *= 0.01 * athleticsSkill * fSwimRunAthleticsMult + fSwimRunBase
   moveSpeed = swimSpeed

elif walking or sneaking:

   moveSpeed = walkSpeed

elif running:

   moveSpeed = runSpeed


   moveSpeed = 0

if strafing (not including diagonally): moveSpeed *= 0.75 if actor is a werewolf and running and has no weapon ready: moveSpeed *= fWereWolfRunMult

moveSpeed is stored for later use. </syntaxhighlight>

Animation system[edit]

Determines movement of the model root bone which feeds back to the physics system. <syntaxhighlight lang="python"> anim = the relevant movement mode animation: # diagonal strafe uses the forward/back animations

   Walk, Fly -> Walk<direction>[+weapon]

if actor is a creature:

   moveSpeed is re-calculated as if the creature was not running (as walking)
   referenceAnim = choose the walking equivalent of the current movement mode:
       Walk, Fly, Run -> Walk<direction>
       SwimWalk, SwimRun -> SwimWalk<direction>

if actor is an NPC:

   referenceAnim = anim

dist, dt = distance and time between the root bone positions at the "Loop Start" (or "Start" if it doesnt exist)

          and "Loop Stop" (or "Stop" if it doesnt exist) animation notes for 'referenceAnim'
  1. note: if there are multiple matching animation notes, the last occurring one is used
  2. note: if the "Loop Stop" key occurs after the "Stop" key, the "Stop" key is used

animBaseSpeed = int(dist / dt) animationScale = moveSpeed / animBaseSpeed animationScale = min(animationScale, 10)

The animation system plays 'anim' with a rate multiplier animationScale. The root bone movement is passed to the physics system. </syntaxhighlight>

Physics movement[edit]

Provides three-dimensional movement like jumps, falls, navigating stairs, levitation. <syntaxhighlight lang="python"> The actor reference is updated with the root bone movement from the current frame.

fStromWindSpeed and fStromWalkMult both affect movement, slowing movement into the wind and faster with the wind. fStromWindSpeed is used with the current wind speed in all weathers. fStromWalkMult is used with storms. These are not applied when NPCs are underwater, but do seem to apply to slaughterfish. </syntaxhighlight>


Creatures have generalized combat, magic and stealth stats which substitute for the specific skills (in the same way as specializations). Creatures do not suffer slow down from encumbrance (fEncumberedMoveEffect). They will only completely stop dead, once they exceed their encumbrance limit.

Note the 10x cap on the animation scaling. This causes an upper limit on the movement rate of actors, which will be at a speed attribute of approximately 1030.


Actions affected Jumping, landing, and midair control
Description Uses common terms fatigueTerm, normalizedEncumbrance.
Implementation status implemented
Analysis status Initial velocity verified; requires testing in combination with physics system

On jumping[edit]

<syntaxhighlight lang="python"> encumbranceTerm = fJumpEncumbranceBase + fJumpEncumbranceMultiplier * (1 - normalizedEncumbrance)

if acrobaticsSkill <= 50:

   a = acrobaticsSkill, b = 0


   a = 50, b = acrobaticsSkill - 50

x = fJumpAcrobaticsBase + pow(a / 15.0, fJumpAcroMultiplier) x += 3 * b * fJumpAcroMultiplier x += jumpSpellBonus * 64 x *= encumbranceTerm if actor is running: x *= fJumpRunMultiplier x *= fatigueTerm x -= gravityAcceleration [constant; -627.2 exactly] x /= 3

if actor is standing still:

   set kinematic velocity to {0, 0, x}

if actor is moving:

   groundVelocity = normalize({actorVelocity.x, actorVelocity.y})
   set kinematic velocity to 0.707 * x * {groundVelocity.x, groundVelocity.y, 1.0}

decrease fatigue by fFatigueJumpBase + normalizedEncumbrance * fFatigueJumpMult </syntaxhighlight>


Airborne velocity can be offset from the initial jump vector based on ground speed and Acrobatics skill.

<syntaxhighlight lang="python"> jumpMoveTerm = fJumpMoveBase + 0.01 * acrobaticsSkill * fJumpMoveMult total velocity = kinematic velocity + ground movement velocity * jumpMoveTerm </syntaxhighlight>

On landing[edit]

<syntaxhighlight lang="python"> fallingDist = distance from peak height

if fallingDist <= fFallDamageDistanceMin: soft landing; skip the rest of the function

x = fallingDist - fFallDamageDistanceMin x -= 1.5 * acrobaticsSkill + jumpSpellBonus x = max(0, x)

a = fFallAcroBase + fFallAcroMult * (100 - acrobaticsSkill) x = fFallDistanceBase + fFallDistanceMult * x x *= a

if x > 0: damage health by x * (1 - 0.25 * fatigueTerm)

if acrobaticsSkill * fatigueTerm < x: actor falls over

if actor is not incapacitated: acrobatics skill exercised (skill gain from fall damage) </syntaxhighlight>


Note that initial actor velocity is taken into account. Animation-driven kinematics mean the jump direction can be offset from the player facing if there is root bone movement. Agility does not appear to be involved in this calculation.