Skating & Movement#
How the Speed attribute becomes top speed and acceleration, plus the other skating tuning values.
1. Speed → top speed and acceleration#
Both use a square-root curve of the Speed stat, clamped to 0–200:
r = sqrt( clamp(Speed, 0, 200) / 200 )
maxSpeed = maxSpeedRangeMin + maxSpeedRange · r = 8.5 + 3 · r
acceleration = accelerationSkatingMin + accelerationSkatingRange · r = 14 + 5 · r
Then:
finalMaxSpeed = maxSpeed × fatigueMovementMult
finalAccel = (acceleration [× 0.97 if carrying the puck] + bonus) × slowmoSpeedScale × fatigueMovementMult
× 1.05 if Enraged
| Speed stat | 0 | 25 | 50 | 75 | 100 | 125 | 150 | 200+ |
|---|---|---|---|---|---|---|---|---|
| Max speed | 8.50 | 9.56 | 10.00 | 10.34 | 10.62 | 10.87 | 11.10 | 11.50 |
| Acceleration | 14.00 | 15.77 | 16.50 | 17.06 | 17.54 | 17.95 | 18.33 | 19.00 |
Practical notes:
- Diminishing returns. Going from 0 to 50 Speed adds +1.5 top speed. Going from 100 to 200 adds only +0.88.
- The hard cap is 200. The cached speed is clamped to 300 and then to 200 inside the formula, so Speed above 200 does nothing.
- The cached speed includes injury and fatigue: a Leg injury multiplies Speed by 0.2 (see attributes-and-stats.md).
Source: Skaters.StatsUtil::GetMaxSpeed/GetAccelerationSkating (pow 0.5 of stat/200), Skaters.ForwardStats::GetMaxSpeed/GetAccelerationSkating/GetAcceleration, Skaters.Forward::GetAcceleration (Enraged ×1.05); data statUtil.
With the puck#
- Acceleration while carrying the puck is ×0.97 (
ForwardStats.GetAccelerationSkatingPuckand thehasPuckbranch ofGetAcceleration). - No top-speed penalty for carrying the puck was found in
GetMaxSpeed. StatsUtilalso hasaccelerationSkatingWithPuckMin = 14andaccelerationSkatingWithPuckIncrement = 0.07(linear14 + 0.07·Speed). Its getterGetAccelerationSkatingWithPuckhas no callers, so this appears to be unused legacy tuning (inferred).
2. Supernova (overspeed) regime#
A skater is "in supernova" when moving faster than their normal top speed:
IsInSupernova: |velocity| ≥ maxSpeedCached × slowmoSpeedScale − 0.2
This happens after boosts or dashes such as the Directional Shroom talent (SupernovaTalent: skate in one direction for 1.75 s, then get a push of force 100). In this regime the higher supernova caps apply:
supernovaMaxSpeed = (12 + 9 · r) × sizeMult × (1.05 if Enraged) × fatigueMovementMult
supernovaAccel = 7 + 11 · r
sizeMult is XS/S ×1.05, M ×1.00, L/XL ×0.95, XXL ×0.90.
| Speed stat | 0 | 50 | 100 | 150 | 200 |
|---|---|---|---|---|---|
| Supernova max speed (M) | 12.0 | 16.5 | 18.36 | 19.79 | 21.0 |
| Supernova acceleration | 7.0 | 12.5 | 14.78 | 16.53 | 18.0 |
On the SNES squad, the Speed stat used for the supernova speed is first multiplied by 0.6.
Source: Skaters.Forward::IsInSupernova, ForwardStats::GetMaxSpeedAtSupernova (size jump table, HasTag(Enraged)), ForwardStats::GetAcceleration (isSupernova branch), Rogue.SupernovaTalent data.
3. Squad-specific movement profiles#
| Squad | Effect |
|---|---|
Modern Squad (_isTchelSquad) |
Max speed, acceleration and supernova values are compressed toward an anchor: v' = ((v − anchor)·0.6 + anchor)·0.95. Anchors: max speed 10.2, accel 16.5, supernova speed 16.5, supernova accel 12.5. Result: smaller differences between skaters and ~5% slower overall. At Speed 0/100/200, max speed is 8.72/9.93/10.43. |
SNES Squad (_isSnesSquad) |
Uses standardDragSnes = 0.2 instead of standardDrag = 0.45. Supernova uses Speed ×0.6. Loc: "very low turning speed". |
| Double Decker Squad ("lines") | Stamina enabled (§5). |
Source: ForwardStats::ApplyTchelMovementProfile + consts TchelMovementCompression 0.6, TchelMovementSlowdown 0.95, Tchel*Anchor; ForwardStats::GetMaxSpeedAtSupernova (_isSnesSquad ×0.6); Movements.SkatingConfiguration::GetStandardDrag.
4. Turning, braking and drag constants#
Getter (ForwardStats) |
Value |
|---|---|
getTurningSpeed() |
0.5 (constant) |
getBrakingDrag() |
4 (constant) |
getDragToNormalSpeed() |
2 (constant): drag that pulls an overspeed skater back to normal top speed (inferred) |
getMinTurning(idx) |
idx 0–1: 0.09, idx 2: 0.10, else 0.11; plus a size delta: XL +0.02, XXL +0.04 (not applied if turnLikeMedium) |
The defaultAttribute asset (Skaters.SkaterAttribute, referenced by GameManager.defaultSkaterAttribute) holds older-looking constants. These are maxSpeed 11, accelerationSkating 20 (19.5 with puck), maxSpeedAtSupernova 16, accelerationAtSupernova 13.5, turningSpeed 0.5, dashSpeed 5, dashCooldown 1 s, dashDrag 3.5 for 0.75 s (after 0.1 s), forceToStumble 5, brakingDrag 5, pokecheckOdds 0.125, interception odds 1.0 (bullseye) / 0.1 (normal), and friction 0.05. The ForwardStats getters above override several of them. Which remaining fields are still live was not traced (inferred).
Source: ForwardStats::getTurningSpeed/getBrakingDrag/getDragToNormalSpeed/getMinTurning; Skaters.SkaterAttribute data.
Movements.SkatingConfiguration (asset skatingConfiguration)#
| Field | Value | Meaning |
|---|---|---|
| standardDrag / standardDragSnes | 0.45 / 0.20 | Base ice drag (SNES squad uses the second) |
| minTimeToHoldZero | 0.10 s | Input must be neutral this long before it counts as idle (inferred) |
| minTimeIdle | 0.06 s | |
| minSpeedToGlide | −2.0 | |
| minTimeBackwardSkating / minBackwardSkatingTime | 0.14 / 0.02 s | |
| minTimeBraking | 0.22 s | |
| minSpeedForBraking | 6.0 | Need this speed to enter a hockey stop |
| speedToStopBraking | 1.5 | Brake ends below this speed |
| pokecheckReceptionCooldownOther / PuckHolder | 0.7 / 0.8 s | Immunity after being pokechecked |
| distanceToManualShot | 24 | |
| Post-shot brake (enabled) | goalieDistance 12, contactDistance 1.1, stopMargin 0.15–0.9, releaseSpeed 2–4, lookAhead 0.6 s, maxDrag 12, maxDuration 0.8 s, accelMult 1.0 | After shooting close to the goalie, the shooter auto-brakes so they don't crash into the goalie |
| Pass-receiver stop zone (enabled) | goalieRadius 2.5, goalLineHalfWidth 2.5, maxBrakeDecel 8 | CPU pass prediction assumes receivers stop before the goalie and goal line |
Source: Movements.SkatingConfiguration (tooltips + data).
5. Stamina (Double Decker Squad)#
Stamina is only active when playing the Double Decker Squad (CampaignUtil.IsPlayingSquad("lines")). Other squads always get multiplier 1.
StaminaConfig |
Value |
|---|---|
| drainSeconds | 45 s from full to empty while on the ice |
| regenSeconds | 20 s from empty to full on the bench |
| floor | 0.5: attribute multiplier at 0 stamina |
| movementFloor | 0.75: max speed and acceleration multiplier at 0 stamina |
Both multipliers use the same curve (s = stamina 0–1):
mult(s) = 1 − (1 − floor) × (1 − s)²
| Stamina | 100% | 75% | 50% | 25% | 0% |
|---|---|---|---|---|---|
| Movement (max speed, accel) | 1.000 | 0.984 | 0.938 | 0.859 | 0.750 |
| Attributes (all four) | 1.000 | 0.969 | 0.875 | 0.719 | 0.500 |
The config tooltip explains why there are two multipliers. Speed maps to movement through sqrt, so halving the Speed stat barely changes movement. The movement multiplier is applied directly on top and is the part players actually feel.
Source: Skaters.StaminaConfig (data + tooltips), Skaters.TeamStaminaSystem::Initialize/Tick, ForwardStats::GetFatigueMovementMultiplier/GetStatAfterFatigueCheck.
6. Enraged skaters#
The EnragedEffect status lasts 10 s and has tagsToApply = [Enraged]. For a skater it gives:
- +50 Speed (
enrageBonus, added throughEnragedStatusEffectController.AddForwardSpeedBonus). - ×1.05 acceleration (
Forward.GetAcceleration) and ×1.05 supernova top speed. - Per the keyword text, every bodycheck sends the target flat.
Goalie enrage is covered in goalies.md.
Source: Rogue.EnragedStatusEffect data, Rogue.EnragedStatusEffectController, Skaters.Forward::GetAcceleration.
Comments