Cooldown commit
What this is
Cooldown commit is the moment in the fire pipeline when a weapon’s cooldownMax is computed from its final fire rate and fireTimer is reset to that value. It happens once per shot, inside the actual-fire branch of WeaponManager.fire, after warmup completes and immediately before projectiles spawn. The committed cooldown is what the per-frame updateCooldowns tick decrements toward zero to gate the next shot.
The commit reads three inputs to produce the final fire rate:
| Input | Source |
|---|---|
| Base fire rate | getWeaponStatAtLevel(def.fireRate, curvedLevel) |
| Horizontal modifier | 1 + def.ratePerH * horizontalDamageUpgrades |
| Early-level nerf | getPlayerFireRateNerf(rawLevel) |
Final fire rate = base × horizontal × early-level nerf. The cooldown is then 1 / finalFireRate, with optional per-shot jitter applied multiplicatively.
| Field | Value at commit |
|---|---|
weapon.cooldownMax | 1 / finalFireRate (or FALLBACK_COOLDOWN = 0.5 if rate ≤ 0) |
weapon.fireTimer | Set equal to weapon.cooldownMax |
| Jitter range | cooldownMax * (1 ± def.fireRateJitter) |
When cooldown is set
The cooldown is set on the fire frame — the frame the projectile actually spawns — not on the frame warmup started, not on the frame the weapon last came off cooldown. The ordered sequence inside fire():
| Step | Action |
|---|---|
| 1 | Tick active warmup if _warmingUp is set |
| 2 | If warmup not complete this frame, return without touching cooldown |
| 3 | On warmup-complete frame (or no-warmup ready frame), enter actual-fire branch |
| 4 | Compute curved level, raw level, early nerfs, horizontal counts |
| 5 | Compute finalDamage from base damage × multipliers |
| 6 | Compute finalFireRate from base rate × horizontal × early nerf |
| 7 | Assign weapon.cooldownMax = 1 / finalFireRate |
| 8 | Apply jitter to cooldownMax if def.fireRateJitter > 0 |
| 9 | Assign weapon.fireTimer = weapon.cooldownMax |
| 10 | Crash if cooldownMax is non-finite |
| 11 | Dispatch to family-specific projectile spawn |
A non-finite cooldownMax throws — invalid fire-rate data is treated as a broken weapon spec, not silently fallen back.
Per-frame, WeaponManager.updateCooldowns(ship, dt) runs once per ship before per-weapon fire calls and decrements fireTimer by dt, clamped at zero. A weapon is fire-eligible only when fireTimer <= 0 and _warmingUp is false.
Interaction with warmup
Cooldown is committed after warmup, not before. The fire-eligibility check (fireTimer <= 0 + valid target) is what triggers warmup-start; warmup itself runs while fireTimer is already at zero. During warmup the cooldown is not touched — only _warmupTimer accumulates. When warmup completes the actual-fire branch executes and commits the new cooldown.
| Phase | fireTimer state | _warmingUp |
|---|---|---|
| Ready, no target | 0 | false |
| Ready, target acquired, warmup begins | 0 (held at zero) | true |
| Mid-warmup | 0 | true |
| Warmup completes, actual fire commits | Reset to cooldownMax | false |
| Cooling down | Decremented each frame toward 0 | false |
The full inter-shot interval for a warmup weapon is therefore cooldown + warmup, because warmup runs after cooldown reaches zero rather than overlapping it. Horizontal fire-rate modifiers shorten cooldown only; they do not shorten warmup.
Practical effect
Cooldown committing on the fire frame rather than the warmup-start frame has three consequences:
| Effect | Detail |
|---|---|
| Warmup is additive to inter-shot interval | A weapon with 0.5s cooldown and 0.25s warmup fires every 0.75s, not every 0.5s |
| Fire-rate horizontals never accelerate warmup | The ratePerH modifier feeds into finalFireRate, which only affects the 1/x cooldown computation — warmup duration is a fixed spec value |
| Mid-warmup spec edits would not apply until next shot | Cooldown reflects the fire-frame’s level, horizontal count, and nerf state; any change between warmup-start and fire is captured at commit time, not at warmup-start time |
For warmup weapons specifically, this means high-warmup weapons (Railgun at 0.55s, Lightning at 0.35s, Hellrain beam at 0.30s — see gameplay/concepts/warmup) have a wider effective DPS gap from their nominal fire rate than low-warmup weapons. Pure fire-rate stacking reduces the cooldown half of the interval to a floor near the per-shot jitter range, but the warmup half is untouched and continues to dominate the cycle.