Flame Heat Buildup

The flame weapon (and any weapon using the flame_stream behavior) tracks an internal _flameHeat scalar in [0, 1] that ramps up while firing and decays after a brief idle. Heat scales the cone width, ember count, and projectile speed of the stream, so the first frames of a flame burst are narrow, sparse, and slow before the weapon reaches full intensity.

This is distinct from ship heat / overheat: ship heat is a hull-level resource shared across systems, while _flameHeat is per-weapon-instance state stored on the weapon entry in ship.weapons[].

State

  • Field: weapon._flameHeat: number (range 01), stored on the weapon instance, initialized lazily to 0 on first fire.
  • Companion field: weapon._flameLastFireTime: number — timestamp (ms via Clock.now()) of the most recent firing frame. Used by the cooldown tick to know when decay should kick in.

Ramp up — while firing

Each frame the flame stream actually fires, fireFlameStream() in engine/weapons/weapons.ts advances heat:

  • FLAME_RAMP_UP = 0.75 seconds — time to climb from 0 to 1 at fixed-step.
  • Per frame: weapon._flameHeat = min(1, weapon._flameHeat + (1 / 0.75) * (1 / 60)).
  • _flameLastFireTime is stamped to Clock.now() on the same frame.

Decay — when not firing

updateCooldowns() (called once per frame from the bridge before per-weapon fire) decays heat:

  • If _flameHeat > 0 and the time since _flameLastFireTime exceeds 0.2 seconds, heat decays.
  • FLAME_DECAY_RATE = 2.0 units/second — weapon._flameHeat = max(0, _flameHeat - 2.0 * dt).
  • The 0.2 s grace covers gaps between cooldown cycles so heat doesn’t bleed away between consecutive shots of the same sustained burst.

How heat shapes the stream

fireFlameStream() derives a heatFactor = 0.3 + heat * 0.7, so at cold start the stream operates at 30% of its full configuration and reaches 100% only at full heat:

  • Cone width: coneWidthDeg = baseConeWidthDeg * extraConeMult * earlyNerf * heatFactor — the cone visually opens from narrow to wide as heat builds.
  • Ember count: emberCount = max(1, round(fullEmberCount * heatFactor)) — fewer embers spawn per fire while cold, building to the full count.
  • Projectile speed: projSpeed = baseSpeed * (0.7 + heat * 0.3) — embers travel 70%→100% of base speed across the ramp.

The composite effect is a flame stream that visibly “warms up” over the first ~0.75 s of sustained fire and trails off after ~0.2 s of idle, giving the weapon a distinct cadence-shaped silhouette rather than a binary on/off cone.

Files

  • src/starship-survivors/engine/weapons/weapons.tsfireFlameStream() (~L1630) writes heat each fire frame; updateCooldowns() (~L3093) decays it.
  • src/starship-survivors/data/weapons/flame.ts — flame weapon spec (behavior: 'flame_stream', coneWidth: 65, emberCount stepped table, etc.). The data file does not define ramp constants — those are hard-coded in the engine.