Edit detail for StaminaModel revision 10 of 36

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
Editor: DonovanBaarda
Time: 2012/11/01 18:25:54 GMT-4
Note:

changed:
-  M = 1.0 + Km*E
-
-Where::
-
-  Km = 1.0, the max lift in number of your own body weights.
-
-A real max lift is about 2x your own body weight, but anything over 1x is unsustainable. I suggest Km=1.0 so that the top-half of the encumbrance bar doesn't go unused and give players an unrealistic impression of how much they can carry. If you want you can allow temporary heavy lifts where E > 1.0 (over encumbered) and have them drop it or collapse when S < Smin.
  M = 1.0 + encumbMult*E

Where::

  encumbMult = 1.0, the "max" lift in number of your own body weights when E=1.0.

changed:
-  Smax = H^(1/Kh)
-
-Where::
-
-  Kh=2.0, but can be tuned up to delay the onset of wound effects.
-
-Note RF uses Smax=1-(1-H)^Kh instead, which compared to the above makes drains less for small injuries, but more for big ones, making it harder to "turn the tables" in combat. The above formula is probably better for gameplay.
  Smax = H^(1/healthExp)

Where::

  healthExp=2, but can be turned up to delay the onset of wound effects.

Note RF uses Smax=1-(1-H)^healthExp instead, which compared to the above makes drains less for small injuries, but more for big ones, making it harder to "turn the tables" in combat. The above formula is probably better for gameplay.

changed:
-  dSmax = H^(1/Kh) - Smax
  dSmax = H^(1/healthExp) - Smax

changed:
-  Smin = (Km/2 * E)^Ke
-
-Where::
-
-  Km=1.0, for a max lift in number of your own body weights.
-  Ke=2.0, but can be tuned up to delay the onset of encumbrance effects.
-
-If S < Smin you are too tired to lift that much weight and collapse.
  Smin = (0.5 * encumbMult * E)^encumbExp

Where::

  encumbMult=1.0, for a max lift in number of your own body weights.
  encumbExp=2.0, but can be tuned up to delay the onset of encumbrance effects.

A real max lift is about 2x your own body weight, but anything over 1x is unsustainable. I suggest encumbMult=1.0 so that the top-half of the encumbrance bar doesn't go unused and give players an unrealistic impression of how much they can carry. If you want you can allow temporary heavy lifts where E > 1.0 (over encumbered) and have them drop it or collapse when S < Smin.

changed:
-  Elift = Kl * Smin
  Elift = Klift * Smin

changed:
-  Kl=1.0 is the cost of lifting relative to other things.
  Klift=1.0 is the cost of lifting relative to other things.

changed:
-Going uphill burns extra energy, ultimately slowing you down. Going downhill doesn't burn any extra energy::
Going uphill or downhill uses energy:::

changed:
-  horizRate = dh/dd = cos(climbAngle)
-  Vc = climbRate * V
-  Vh = horizRate * V
-  Eclimb = Kc * M * max(0,Vc)
  Kclimb = max(Kup*climbRate, -Kdown*climbRate)
  Eclimb = Kclimb * M * V

changed:
-  climbScale = 1/(horizRate + Kc*max(0,climbRate))
-
-Where::
  climbScale = 1/((climbRate/0.1)^2 + 1)

Where::

changed:
-  climbAngle is the elevation angle of the direction traveled.
  climbAngle is the elevation angle of the direction travelled.

changed:
-  horizRate is horizontal movement per total distance moved.
-  Vc is vertical speed as a fraction of max horizontal running speed.
-  Vh is horizontal speed as a fraction of max horizontal running speed. 
-  Kc = 6, climbing vertical is Kc x the cost of running the same horizontal distance.
  Kup = 10.0, is the cost of climbing up per meter relative to other things.
  Kdown = 2.0, is the cost of going down per meter relative to other things.
  Kclimb  is the cost of climbing based on the gradient.

changed:
-  climbScale is the speed scaling factor for climbing.
-
-Record 15m speed climbing top speed is 6.26sec, or about 2m/sec, compared to 100m record top speeds of about 12m/sec. This suggest climbing uses as much energy as going 6x the distance horizontally, but some documentation suggests it is 10x. It often surprises players how much affect climbing really has, so for playability you may want to lower Kc.
-
-Note climbScale is is 1/Kc=1/6 for going up vertically, and limited to 1.5 for downward slopes. This means you can walk/run up to 1.5x as fast when going downhill.
  climbScale is the scaling factor for energy spent walking/running.

Studies on walking/running on gradients show going uphill/downhill is about 12.5x/2.5x as expensive/meter as running horizontally, so Kup=12.5, Kdown=2.5. Record 15m speed climbing top speed is 6.26sec, or about 2m/sec, compared to 100m record top speeds of about 12m/sec, which suggests climbing vertically uses only ~6x the energy as horizontal running and half as much as uphill running. I suspect that climbing using both arms and legs allows double the power output compared to running with just legs, but the energy/meter is the same.

It often surprises players how much affect climbing really has, and games tend to have exaggerated gradients. For playability I suggest lower values like Kup=10.0 and Kdown=2.0, or even Kup=6.0 and Kdown=1.2.

changed:
-  moveSpeed = climbScale * Ks * ((S - Smin)/M)^(1/2)
-  Ewalk = Kw * M * V^2 = Kw * M * (V * horizRate)^3 = climbScale * Ks * (S - Smin)
  V = moveScale = walkMult * ((S - Smin)/M)^(1/2) / (climbScale + Kclimb)
  Ewalk = climbScale * Kwalk * M * V^2

changed:
-  moveSpeed is movement speed as a fraction of max run speed.
  moveScale is movement speed as a fraction of max run speed.
  Kwalk = 16.0 is the cost of walking relative to other things.

changed:
-  Kw = 16.0 is the cost of walking relative to other things.
-  Ks = 0.25 is max walking speed as a fraction of max run speed. Can be tuned down to reduce walking speed and stamina burn.
-
-Note Kw=0.25 represents a realistic maximum fast walking speed of around 2.5m/sec. Using Kw=0.2 would be like a more casual walking speed of 2m/sec, and significantly reduces the stamina burn.
  walkMult = 0.2 is max walking speed as a fraction of max run speed. Can be tuned down to reduce walking speed and stamina burn.

Using walkMult=0.25 represents a realistic maximum fast walking speed of around 2.5m/sec. Realistic minimum energy walk speed is walkMult=0.125, but would probably try the patience of gamers. Using walkMult=0.2 is a brisk walking speed of 2m/sec, and is a good gaming compromise between energy saving and speed.

changed:
-  moveSpeed = climbScale * (S - Smin)/M
-  Erun = Kr * M * V
  V = moveScale = (S-Smin)/(M * (Kclimb + climbScale*Krun))
  Erun = climbScale * Krun * M * V

changed:
-  Kr=1.0 is the cost of running relative to other things.
  moveScale is movement speed as a fraction of max run speed.
  Krun=1.0 is the cost of running relative to other things.
  Erun is the fraction of all muscles applied to running.

added:
  jumpHeight = jumpScale * jumpMax

added:
  jumpMax is the maximum unfatigued, unencumbered jump height in meters.

The RealisticFatigue? document was a bit too messy and Oblivion specific. This is an attempt to tidy and simplify it into something that can be used for other games. In particular, "stamina" is a better name than "fatigue".

Basic Attributes

The following attributes are in the range 0.0 (empty) to 1.0 (full). Note that there can be underlying health/strength/endurance/etc attributes that translate these into different numbers, but from the fatigue models point of view, the only thing that matters is the fraction of full health/stamina/encumbrance:

H - health. The fraction of life remaining after taking damage.
S - stamina. The fraction of un-damaged, un-fatigued muscles available for lifting/moving/fighting/etc.
E - encumbrance. The fraction of max lift worth of equipment currently carried.

The following constants adjust how quickly you get tired and recover. They are normally constants but could be tweaked per-character based on some endurance attribute:

F - stamina burn rate, stamina/second
R - stamina recovery rate, stamina/second

Note that R/(F+R) is the "steady state" or minimum S value reached for constant activity, so the the R/F ratio is important. Studies show F is 0.008~0.033, R is 0.0026~0.013, and F/R is 0.3~0.5, so F=0.03, R=0.01, for F/R = 1/3 is realistic, and gives an average fatigue recovery rate of 0.5%/sec. However for gameplay reasons speeding it up to F=0.9, R=0.03 might be better.

Many of the formulas use the total mass of the player in body-weights which is calculated as:

M = 1.0 + encumbMult*E

Where:

encumbMult = 1.0, the "max" lift in number of your own body weights when E=1.0.

Note the largest professional rugby league player is 133Kg, though 100~125Kg is probably more realistic for a big hero's bodyweight.

Movement speeds are measured as the fraction of Max unencumbered, unfatiged flat running speed:

V is fraction of Max speed.

Wounds

Wounds are modelled as damaged muscles, reducing your available muscles for running/fighting/etc. It applies a constant "drain" or cap on your stamina. This could be indicated as a red max stamina marker on the top end of the stamina bar:

Smax = H^(1/healthExp)

Where:

healthExp=2, but can be turned up to delay the onset of wound effects.

Note RF uses Smax=1-(1-H)^healthExp instead, which compared to the above makes drains less for small injuries, but more for big ones, making it harder to "turn the tables" in combat. The above formula is probably better for gameplay.

Whenever you are damaged/healed and your health changes, it damages/restores some of both fatigued and unfatigued muscles. There should be a change in S that reflects this. For a change in health of dH:

H = H + dH
dSmax = H^(1/healthExp) - Smax
dS = dSmax * S/Smax
Smax = Smax + dSmax
S = S + dS

Where:

dH is the change in health.
dSmax is the change in Smax
dS is the change in S

Note this ensures that at low stamina a hit winds you a bit, but not too much.

Encumbrance

Encumbrance preoccupies muscles, leaving less available for running/attacking/etc, and there is a minimum stamina required to lift everything you are carrying. It can be shown using a black min stamina marker on the bottom end of the stamina bar. These preoccupied muscles also should be subtracted from S when considering how fast you can run, hard you can hit etc:

Smin = (0.5 * encumbMult * E)^encumbExp

Where:

encumbMult=1.0, for a max lift in number of your own body weights.
encumbExp=2.0, but can be tuned up to delay the onset of encumbrance effects.

A real max lift is about 2x your own body weight, but anything over 1x is unsustainable. I suggest encumbMult=1.0 so that the top-half of the encumbrance bar doesn't go unused and give players an unrealistic impression of how much they can carry. If you want you can allow temporary heavy lifts where E > 1.0 (over encumbered) and have them drop it or collapse when S < Smin.

Note RF implements this as an additional "drain" on S, but that is slightly miss-leading as it is not really damaged/fatigued muscles and thus should not affect fatigue indicators like panting etc.

Recovery

Fatigued muscles (that are not wounded) continuously recover at a constant rate. This is how stamina recovers:

Erest = (Smax - S)
dS = R * Erest * dt

Where:

Erest is the fraction of all muscles that are fatigued and resting.

Note that stamina S cannot increase past Smax.

Lifting

Lifting stuff not only pre-occupies muscles, but also fatigues them. This is how stamina is constantly burned by encumbrance when standing:

Elift = Klift * Smin
dS = -F * Elift * dt

Where:

Klift=1.0 is the cost of lifting relative to other things.
Elift is the fraction of all muscles applied to lifting.

Climbing

Going uphill or downhill uses energy::

climbRate = dz/dd = sin(climbAngle)
Kclimb = max(Kup*climbRate, -Kdown*climbRate)
Eclimb = Kclimb * M * V
dS = -F * Eclimb * dt
climbScale = 1/((climbRate/0.1)^2 + 1)

Where:

dz is vertical travel distance.
dd is total travel distance.
climbAngle is the elevation angle of the direction travelled.
climbRate is vertical movement per total distance moved.
Kup = 10.0, is the cost of climbing up per meter relative to other things.
Kdown = 2.0, is the cost of going down per meter relative to other things.
Kclimb  is the cost of climbing based on the gradient.
Eclimb is the fraction of all muscles applied to climbing.
climbScale is the scaling factor for energy spent walking/running.

Studies on walking/running on gradients show going uphill/downhill is about 12.5x/2.5x as expensive/meter as running horizontally, so Kup=12.5, Kdown=2.5. Record 15m speed climbing top speed is 6.26sec, or about 2m/sec, compared to 100m record top speeds of about 12m/sec, which suggests climbing vertically uses only ~6x the energy as horizontal running and half as much as uphill running. I suspect that climbing using both arms and legs allows double the power output compared to running with just legs, but the energy/meter is the same.

It often surprises players how much affect climbing really has, and games tend to have exaggerated gradients. For playability I suggest lower values like Kup=10.0 and Kdown=2.0, or even Kup=6.0 and Kdown=1.2.

climbRate should probably be low-pass filtered so jitter/bob doesn't burn fatigue like crazy. This is done by actually calculating it with:

climbRate = (dt*ds/dd + RC*climbRate)/(dt + RC)

Where:

RC = 0.5, but can be tweaked to adjust smoothing.

Walking

This is how stamina is burned when walking, and how walking speed varies with stamina and encumbrance:

V = moveScale = walkMult * ((S - Smin)/M)^(1/2) / (climbScale + Kclimb)
Ewalk = climbScale * Kwalk * M * V^2
dS = -F * Ewalk * dt

Where:

moveScale is movement speed as a fraction of max run speed.
Kwalk = 16.0 is the cost of walking relative to other things.
Ewalk is the fraction of all muscles applied to walking.
walkMult = 0.2 is max walking speed as a fraction of max run speed. Can be tuned down to reduce walking speed and stamina burn.

Using walkMult=0.25 represents a realistic maximum fast walking speed of around 2.5m/sec. Realistic minimum energy walk speed is walkMult=0.125, but would probably try the patience of gamers. Using walkMult=0.2 is a brisk walking speed of 2m/sec, and is a good gaming compromise between energy saving and speed.

Running

This is is how stamina is burned when running, and running speed varies with stamina and encumbrance:

V = moveScale = (S-Smin)/(M * (Kclimb + climbScale*Krun))
Erun = climbScale * Krun * M * V
dS = -F * Erun * dt

where:

moveScale is movement speed as a fraction of max run speed.
Krun=1.0 is the cost of running relative to other things.
Erun is the fraction of all muscles applied to running.
moveSpeed is the running speed as a fraction of max running speed.

Record 100m top speeds average about 10m/sec and peak at 12m/sec. A realistic maximum running speed (for a hero) would be about 10m/sec.

Jumping

This is how stamina is burned by jumping, and how jump height varies with stamina and encumbrance:

dS = -F * (S - Smin)
jumpScale = (S - Smin)/M
jumpHeight = jumpScale * jumpMax
jumpVelocity = sqrt(2*g*jumpHeight)

Where:

Kj = 2, but can be tuned down to reduce encumbrance effects on jumping.
jumpScale is the jump height as a fraction of max jump height.
jumpMax is the maximum unfatigued, unencumbered jump height in meters.
jumpHeight is the height of the jump in meters.
jumpVelocity is take-off velocity in meters/sec (for physics models).
g = 9.81m/s^2 is the gravitational constant.

A jump burns as much fatigue as running for 1 second.

The (unverified) world record for a vertical jump is around 1.5m, but anything over 1m is considered extraordinary, with 0.75m being the average for professional footballers and basketballers. Micheal Jordan could jump 1.2m. The average taken for a group of typical medical students was 0.56m for men and 0.35m for women.

Attacking/Blocking

The speed and effectiveness of attacks and blocks depends on available stamina, and also burns stamina:

dS = -F * W * (S - Smin)