engine/bridge

PURPOSE — Mission harness. Owns the per-mission frame loop and the React-facing imperative handle. Assembles a run from a RunDefinition (validates, seeds, applies ship/weapon/artifact/world config, wires signals), then on each frame dispatches the ordered phase pipeline (physics → enemy AI → collision → boss tick → pickups → events → leveling/rewards → death/level-advance → render) and pumps every subsystem in the right order with the right dt/rawDt. Returns the MissionHandle GameScreen drives.

OWNS

  • Per-mission closure state: paused, frame rAF handle, manual-pump flag, _dpr snapshot, intro-fade timers, level-transition fade alpha, death cinematic timer + revive prompt timer + death defiance use count, post-decline-death latch, mission-complete countdown, engine trail ring buffer, terrain-expand throttles, frame-error counter, thermal-rest snapshot + flag, saved per-slot weapon modes, timed-weapon-chest schedule (next-time + checks-done + per-level counter + pending-relocation chest), dynamic artifact-drop scheduler state, illumination/trigger system handles, zone-debug and hub-spoke-wireframe toggles, event pool snapshot, init-planet ref, init-level-data ref.
  • Module-level rendering / VFX state shared across submodules: ship atlas v4 swap latch, cached ship diffuse image + aspect + rarity multiplier, deferred player-pass parameters, Star Power overlay buffer, active hull-class string, ship rarity, enemy atlas patched set + per-archetype/rarity region cache + boss-sprite atlas latches, terrain atlas patch count + dirty flag, solid + outline sticker buffers, ship-shadow-patched flag, weapon chest sprite + load latch, boss impact tracer list, runtime fog/dust VFX toggles and tints, intro fade alpha + level fade alpha, last frame timestamp, mobile-device cache, low-priority skip flag.
  • Per-archetype debris tint table, per-archetype debris-count multiplier, per-event-type audio cue map, per-event-type camera shake map, per-event-type completion VFX burst tint map, rarity-color map for elite outlines, full enemy-archetype list, melee-aura constants, forecast fade durations, shield-break suppress window, timed-weapon-chest schedule constants, boss-impact-tracer life + cap.
  • The death debris pool, the explosion-flash light pool, and the boss-impact tracer pool (caps, decay, eviction).
  • The mission-lifecycle phase machine itself — transitions between playing, levelup, dead, level_advance, complete, results and the bookkeeping that flips them (reward dispatch, death detection, boss-clear flag, timer-expiry, portal-entry vestige).
  • The MissionHandle surface returned to React (start, input, reward selection, reroll/banish, wheel spin/exit, pause/resume, destroy, revive/decline, ship screen pos + angle, weapon mode push, manual fire trigger, run snapshot, recover-from-stuck, canvas resize sync, and the whole sandbox / playground / test-pump API).
  • The dev console object (window.__dev, window.__diag, gauntlet death counter, boss event log) when devScenario / sandbox is active.

READS FROM

  • data/run-config for RunDefinition + validator + default; data/mission-result for the snapshot shape; data/planet-config for the active planet record; data/ships for hull classes + rarity-derived sprite scaling; data/hull-hitboxes for collision polygons; data/weapons for weapon defs + per-level stats; data/enemies for collision scale + radius; data/level-config for default level config + hub typing; data/level-progression to resolve next-level kind + final-level test; data/bosses for boss-def per-frame escalation; data/economy for death-defiance tuning; data/run-history for the new-account spawn dampener; data/artifacts for the artifact catalog; data/modifiers and data/mod-templates + the mod grid service for sandbox mod equip; data/affixes indirectly via the affix registry.
  • engine/core for ship/world/game/camera/playerInput refs, dimensions setter, debug-overlay toggle, signals, modifiers, clock, set-pool, frame cache, FPS smoother, fixed-step loop tick, set-of-pools helpers, render-diag instrumentation, perf flags, CFG constants, remote-error reporter.
  • engine/weapons for the WeaponManager API, manual-fire latch, delayed-shot queue tick, fire-rate nerf, bullet-bin size, bullet behavior registry.
  • engine/enemies for GameMaster, Director, racer lane generator, behavior registry, seek/steer/face helpers, mid-attack predicate, boss spawn-profile tick, boss-spawner-disabled sync, enemy release/bin telemetry.
  • engine/combat for the collision resolver, damage entry points, terrain push-off, XP-orb spawn, death VFX update, hull-poly transform.
  • engine/affixes for the catalog init, on-spawn/on-update dispatch, late-bound damage and prop-spawn adapter setters.
  • engine/physics for terrain collision helpers and the Rapier world/ship/terrain/enemies/debug subsystems.
  • engine/world for pickups, leveling, illumination + trigger systems, event manager + spawner + builder, shooting-star spawner + tick, warp-puddle system, world generator, chunk-manager level bake, artifact lifecycle + droid/beam/shield/T-bone/knockback state readers, prop pool, crate + debris fields, XP orb pool, level-data type.
  • engine/effects for the unified effect engine, status tick, run-effects register/teardown, custom flame-zone draw.
  • engine/player for the exclusive-state predicate + tick + apply.
  • engine/abilities for the per-frame ability tick.
  • engine/boss for sealed-arena + boss-room helpers, encounter spawn/end, shared boss VFX kit; engine/destructibles for hazard-zone tick.
  • engine/vfx for particles + smoke + sonar rings + post-FX + explosion FX + AoE explosion + thruster + player glow + juice + ship recoil + DmgNumbers + XP/Shield/Hp accumulators + enemy-orbit + boss-layer ticks.
  • engine/rendering for the renderer, camera, draw routines, HUD (warning push/dismiss, reward state machine, tutorial state, upgrade-show pipeline, merge cinematic, card vanish, autopick countdown, banner draw, boss bar), wheel UI, background, post-processing, gameplay underlay, parallax, vignette, atlas builder, 3D terrain draw, ship-v4 loader, sprite/glow batches, glow stamps, weapon-color lookup, enemy-sprite/boss-sprite maps, fire engine, cone-beam and warp-puddle runtimes, squash-stretch helper, artifact-pickup + artifact-banner draw, shooting-star draw, draw-3d-terrain outline constants.
  • engine/audio for the music player, audio bus, sample SFX, micro SFX, weapon chimes.
  • engine/telemetry for the collector, sender, sampler, perf observer, long-task observer, FPS tick, refresh-rate sampler, diag log.
  • Browser surfaces: requestAnimationFrame / setTimeout for scheduling, performance.now() only via the frame scheduler accumulator, localStorage for the challenge-unlocked flag, crypto.randomUUID for the sampler run id, the canvas + 2D context.

PUSHES TO

  • The provided BridgeCallbacks: onPhaseChange on every transition, onGameOver on results, onRewardShow on each reward open, onRevivePrompt when the revive prompt arms, onReviveDismissed on prompt auto-dismiss or decline.
  • engine/core state mutation: phase, level, XP, time dilation, reward queue, mission timer + elapsed, world knobs, run-def install, kill streak, current reward + family, weapon-chest freeze, magnet timer, hull flash, damage flash, base-stat snapshot for overtime restore, attack-speed multiplier, enemy-difficulty level, dirty-bits for various per-level resets.
  • engine/world mutation: enemy / bullet / pickup / weapon-box / artifact-box / event / destructible / sigil / star / regen-station / patrol / comet / forecast / timed-strike / hub / spoke / floater / terrain / chunk arrays cleared on level advance; weapon-box and artifact-box spawn paths; regen-station spawn; comet/event_star/golden-star lifecycle; world seed regen.
  • engine/audio — music player start/stop/warp-intensity/lowpass, sample SFX launch + thrust + level-up click + gong, micro SFX (warp puddle enter/exit), audio bus resume + music-lowpass set.
  • engine/rendering — pushes warnings (overheat / stalled / shield broken / level banner), starts reward reveals, kicks upgrade-show / merge / card-vanish cinematics, resets tutorial/autopick state, drives the hub-spoke-wireframe + zone-debug overlays, configures post-processing preset per planet, the sticker outline buffers, atlas patch + reupload via _bakeAllEnemySprites / _bakeAllBossSprites.
  • engine/vfx — particle bursts, sonar ring shockwaves, explosion FX, AoE finishes, post-FX rings, juice fire on player hit/death/level-up/revive/pickup/event/weapon-fire, ship recoil reset, thruster smoke + rarity color, smoke clouds during stall, enemy-orbit reset.
  • engine/physics — Rapier world init, rebuild on tier advance, ship body create/teleport/destroy, terrain registration on first trace, enemy sensor sync.
  • engine/boss — sealed-arena spawn + teardown, boss spawn + encounter-end on player death + win path, boss-room update, hazard-zone tick, boss-layer tick.
  • engine/telemetrytelemetry.begin at mission start, per-frame tick, weapon-fire + reward + death + director-phase records, finalize + sendRunTelemetry on results; Sampler.setRun + setRun(null), periodic snapshots, lifecycle events (run_start, level_start, level_complete, boss_spawn, boss_death, player_death, run_end, recover_button crash), explicit flush.
  • engine/world artifact lifecycle — initArtifacts / teardownArtifacts / grantArtifact / tickArtifacts; affix runtime adapters wired at module load.
  • Late-bound module init: registers the affix damage-player adapter, the affix prop-spawn adapter, and initializes the affix registry exactly once when the module loads.

Phases

  • Mission build (createMission) — validate the RunDef; reset engine + canvas + DPR; pick world seed; bake level data + spawn illumination + trigger systems; generate biome terrain (skipped for sealed-arena kinds); reset GameMaster + post-processing + background + nebula; install racer lanes for city planets; seed events via EventSpawner.seedHubs; set active hull + rarity; pre-bake every (archetype × rarity) outline and every boss sprite; apply ship combat stats from RunDef onto ship; mount starting weapons with fire-rate nerf + cooldown derive; install starting artifact (+ dev auto-artifacts); install run-effects + affix registry; build the empty MissionResult; expose game.runDef; apply per-level base world knobs with new-account dampener; spawn n weapon boxes from weaponBoxCount; place supply-level-1 weapon chest near the player; wire phase_change signal to onPhaseChange; reset tutorial; install dev-playground console API.
  • Mission start (handle.start) — flip phase to playing, install Rapier ship body with hull polygon, begin telemetry, schedule the first frame.
  • Frame scheduling — sandbox uses setTimeout(16) (Preview throttles rAF to 1Hz when hidden); normal mode uses requestAnimationFrame; manual-pump mode (tests) suppresses both and waits for testPumpFrame. paused short-circuits to a reschedule.
  • Per-frame entrygameLoopTick(now) (physics, input, camera, timers, fixed-step accumulator); read dt and rawDt; telemetry tick + sampler tick + pool-occupancy probe + refresh-rate sample.
  • Decay sweeps — explosion flashes decay (framerate-independent); ship hull poly + outer radius recomputed from the active hull silhouette; rebuild frame cache (alive counts only at this point).
  • Playing-phase physics block — overheat / stalled warnings; level-end helper drives boss-clear, timer-expiry, and vestigial portal-entry into either complete, end_of_level_artifact reward, or level_advance; weapon cooldowns + per-slot fire (auto vs manual with manual-trigger latch); delayed-shot drain; player bullet sim with homing delay + steering + drag (low-HP and nearest target modes); enemy bullet sim with ramp-in + fizzle decel + invuln sweep + arena cull; timed strikes + forecasts tick.
  • Enemy AI blockGameMaster.tick (gated by sandbox + boss-spawner-disabled), Director.update, death-timer decay, debris-on-killing-blow latch, AI cull with distance hysteresis (smart vs dumb mode), frame-skipped behavior tick by distance bucket, ability tick, spawn/spawn-pop timer decay, stun/fire-plop decay, melee aura windup + land + cooldown, push-apart via spatial grid every other frame, floater zeroing.
  • Terrain + collisions — throttled expandTerrain + event spawner tick on grid crossing (skipped for zone-aware + sealed-arena); leyline spoke speed boost; terrain polygon trace + Rapier piece registration; Rapier enemy sensor sync; CollisionResolver.resolve; boss arena onUpdate + hazard zone drain + bar coalescer flush (damage popup + camera shake + bar flash) + encounter-end detection.
  • Pickups + events — pickup system tick; crate + debris + prop pool tick; wheel state tick + reward apply; event manager update returning completed events; per-completed-event dispatch (per-type audio cue, VFX burst, camera shake, hub illumination, reward routing — magnet vacuum, +1 level with fractional preserve, weapon chest spawn, artifact-box queue or fallback weapon, wheel open with timeDilation=0, star power exclusive state, regen station spawn, cascade / forager / horde / pulse / vortex / comet_shower primitives); illumination is event-driven; trigger system tick; shooting-star spawn + collect → reward queue.
  • Region tick — regen-station heal + reverse-rain + halo VFX; Star Power rainbow trail; off-screen weapon-chest hide + relocation-pending; weapon-box and artifact-box lifecycle (flight arc, asteroid collide explode, mandala collect, fly-to-center collect cinematic, reward queue push, time-freeze gate); leveling tick (skipped in sandbox / during wheel).
  • Reward dispatch — dequeue one reward when free; route to family (event_reward_upgrade auto-apply + upgrade-show; artifact_box → upgrade-only rolls; end_of_level_artifact → 3 new artifact choices; shooting_star → 2 category choices; weapon_box with slots-full snapshot → auto-upgrade-show fallback or 3 weapon choices; default → modifier + weapon choices); set phase levelup, freeze, lowpass music, start reward reveal, fire onRewardShow.
  • Effect + VFX ticktickArtifacts, EffectEngine.tick, tickStatuses, warp-puddle enter/exit with music-bus intensity, deferred death VFX, particles + smoke + dmg numbers + accumulators + sonar rings + post-FX + explosion FX + AoE + thruster smoke + player glow + boss-layer (all rawDt so they animate during slow-mo), level-up ring decay, juice + ship-recoil decay, damage / hull / magnet / kill-streak decay, tutorial step triggers + proximity tutorials + tutorial timer, engine trail ring buffer push, distance accumulator, mission-elapsed advance (frozen in sandbox), thrust SFX update.
  • Progress + cleanupgame.progress = floor(kills/15 + elapsed/30); remove dead enemies (and re-pop the pending relocation chest from the nearest dying enemy on the way); detect !ship.alive → fire player_death sampler event, cancel any active reward overlay, flip phase to dead, stop music, route either to the death-defiance cinematic or the short fade-to-results when uses are spent.
  • Reward-reveal tick — drives the announce → slot-intro → slot-lock → shine → showing state machine outside the playing block so cards become visible during freeze.
  • Dead phase tick — cinematic timer counts down rawDt; arms revive prompt at zero with onRevivePrompt; prompt timer auto-dismisses on expiry; otherwise deathTimer counts down to results which populates MissionResult (outcome / performance / progression / combat / economy / exploration / score / reward tier), records death telemetry, finalizes + fire-and-forgets the run telemetry post, fires run_end, flushes the sampler, fires onGameOver.
  • Level-advance phase — fade-to-black tween, then: advance level counter, resolve next-level kind, teardown sealed arena, fire tier_advance, restore pre-overtime base knobs, scale enemy HP / damage / speed / count / attack-speed multiplicatively per level, decay enemy difficulty level, clear every transient world array, re-roll world seed, regenerate biome (skip sealed kinds), reset GameMaster + Background + EventSpawner, push level banner with kind-encoded color + label, reset timers + portal + boss state + weapon-chest counters + artifact-drop scheduler, clear VFX pools, center ship at origin, full Rapier rebuild + ship body re-create, brief invuln, sealed-arena setup with boss roster spawn (or normal-mode setup), fire level_start sampler, trigger fade-in, flip phase to playing, resume audio.
  • Complete phase — short victory delay, then populate the survived MissionResult (final score with survival bonus + reward tier), record telemetry + run-end sampler + flush, fire onGameOver.
  • Render — context-loss probe (synchronous isContextLost or 1px fillRect fallback); renderer.resize + dependent runtime resizes; bail early if canvas is 0×0; PostProcessing.update; the renderer’s two-callback pipeline (drawWorld, drawHUD) wires the 22-pass list — background, parallax mid, gameplay underlay, world events ground layer, fog below + dust behind, hub/spoke wireframe + zone debug, warp puddles, player underlay (blue aura + shield bottom), terrain pass 1 with sticker outline buffer + y-sort, boss-VFX-under pass + hazard zones, weapon boxes 3D, artifact orbs, shooting stars + ring pop, portal forming + materialized, companion droid + electricity, ship sprite via WebGL batch (with star-power overlay + thruster on Canvas 2D first), enemy sprites + outlines + HP bars batched, engine exhaust trail, postFx (charge orbs + fire plops + hitscan + sniper beams + death pulses + AoE + sonar), bullet danger overlay, particle batch via WebGL, level-up sonar ring, boss VFX additive, lighting/darkness (mobile-skipped), boss room walls, HUD (warnings, reward cards, damage flash, death cinematic, wheel overlay, tutorial, boss bar). Thermal-rest path skips the world pipeline and blits the cached snapshot.
  • Mission destroy — cancel frame, teardown artifacts + run-effects, clear signals, null illumination + trigger systems, clear Rapier.

Signals fired

  • phase_change — on every transition to dead, results, playing (level-advance, revive, sandbox respawn, sandbox reset for test).
  • tier_advance — on level advance, after the world knobs scale.
  • event_complete — on every event completed during play (per-type, x/y carried as num args for new artifact handlers); also fired on vestigial portal entry.
  • weapon_fire — once per weapon-slot fire (auto or manual), after the cooldown actually advanced.

Signals watched

  • phase_change — fans out to callbacks.onPhaseChange.
  • Dev-only listeners (registered once per session under an HMR guard): the boss event log subscribes to boss_intro / boss_phase / boss_part_destroyed / boss_defeated / boss_enrage / damage_dealt / player_damage / shield_break / shield_hit / hull_damage / enemy_kill; the gauntlet death counter listens for phase_change → dead during boss fights.

Entry points

  • createMission(canvas, callbacks, runDef) — module-level factory. Returns a MissionHandle.
  • MissionHandle.start — install Rapier + telemetry, flip to playing, schedule the first frame.
  • MissionHandle.setInput(angle, magnitude, thrusting) — push joystick state into playerInput and ship.targetAngle; autopilot suppresses.
  • MissionHandle.selectReward(index) — confirm a reward card (auto-pick, merge cinematic, or upgrade-show pipeline) and record the choice for telemetry.
  • MissionHandle.rerollRewards — re-roll the current reward family if a charge is available.
  • MissionHandle.toggleBanishTargeting / MissionHandle.banishOption(index) — enter/exit the banish UI and consume a charge by marking a key in banishedKeys + playing the smoke vanish.
  • MissionHandle.wheelSpin / MissionHandle.wheelExit — drive the wheel-of-fortune overlay state machine.
  • MissionHandle.pause / MissionHandle.resume — toggle frame execution (still schedules so it can resume).
  • MissionHandle.destroy — cancel frame, teardown artifacts + run-effects + signals + illumination + trigger + Rapier.
  • MissionHandle.revive / MissionHandle.declineRevive — accept death defiance (HP/shield restore, invuln, phoenix VFX, sweep the field) or decline (hard cut to results).
  • MissionHandle.getShipScreenPos / MissionHandle.getShipAngle — read-only view of where the ship is on screen.
  • MissionHandle.setWeaponModes(modes) / MissionHandle.fireWeapon(slotIndex) — push per-slot fire modes into live weapons + saved-modes cache; arm a manual-fire trigger.
  • MissionHandle.getRunSnapshot(causeOfDeath) — non-terminating MissionResult snapshot for cog-menu exit and beforeunload.
  • MissionHandle.recoverFromStuck — dump every transient pile (particles, dmg numbers, bullets, enemies), top off ship survivability, short invuln. Sampler-crashed first so the pre-recovery state is captured.
  • MissionHandle.onCanvasResize(cssW, cssH, dpr) — single source of truth for canvas resize: syncs engine dimensions + ctx transform + sprite batch buffers.
  • Sandbox surface — patchShipStats, setWeapons, setWorldKnobs, spawnEnemyAt, getCameraTransform, setSpawnerEnabled, setGodMode, clearEnemies, freezeEnemies, getAliveEnemyCount, sandboxGrantArtifact, sandboxEquipMods, fullHeal, sandboxRespawn, sandboxResetForTest, sandboxRegenerateWorld, sandboxPlaceTerrain / sandboxRemoveTerrain / sandboxMoveTerrain / sandboxScreenToWorld / sandboxGetTerrainCount, sandboxSetDebugOverlay, sandboxSetPostProcessing, sandboxSetFog, sandboxSetNebula, sandboxSetLighting, sandboxSetSpawnRate, sandboxSetLevelConfig, sandboxSetZoneDebug, sandboxSetHubSpokeWireframe, sandboxGetLevelStats, sandboxAddTrigger / sandboxUndoTrigger / sandboxGetTriggerCount, sandboxSpawnBoss, sandboxGetBossState.
  • Test surface — testSetManualPump, testPumpFrame(timestampMs).

DOES NOT

  • Author content. Every stat, curve, weapon, artifact, biome, level kind, planet, boss, event-type weight, affix, and modifier comes from data/* or the run-config pipeline. The bridge consumes; it does not declare.
  • Run physics or input. engine/core/loop.gameLoopTick owns the fixed-step physics step, accumulator, input application, camera follow, and timer tick. The bridge only invokes it once per frame.
  • Resolve collisions or apply damage. engine/combat/collision-resolver resolves; engine/combat/damage is the sole authority for HP / shield reduction. The bridge only invokes them and consumes side-effect flags (_shieldBreakPulse, _dying, _bossLevelCleared, etc.).
  • Spawn enemies on its own. GameMaster.tick and Director.update own spawn cadence; trigger callbacks queue spawns; the bridge only ticks them. Sealed-arena bosses spawn through engine/boss/encounter.
  • Decide what counts as a kill, an elite, or a streak. engine/combat/damage + engine/world/leveling own those.
  • Run the weapon fire pipeline. The bridge calls WeaponManager.fire per slot with an aim angle (auto-aim helper or manual ship-facing+default); the weapons module dispatches, fires, spawns bullets, and updates them via behaviors. The bridge only drives the per-frame for-loop and the manual-fire latch.
  • Run the boss state machine. engine/boss/encounter drives spawn → arena alive → bar live → encounter end; the bridge only dispatches the active boss-def per-frame onUpdate hook + ticks hazard zones + flushes the bar-damage coalescer + detects encounter end.
  • Generate terrain, place hubs/spokes, or compute zones. engine/world/generation + engine/world/chunk-manager (bakeLevel) own that; the bridge only invokes them and clears state on level advance.
  • Roll rewards, build reward choices, banish keys, or generate shooting-star pick categories. engine/world/leveling (and rollArtifactChoices, generateShootingStarChoices, banishKeyForChoice) own those; the bridge only routes by family and stuffs the result onto game.currentReward.
  • Render anything itself. Every draw goes through engine/rendering/* and engine/vfx/*; the bridge only sequences the passes (and runs the sticker-outline composite + the weapon-chest / artifact-orb / portal / boss-bar inline cases that haven’t been extracted yet).
  • Compose audio. engine/audio/* owns the music player, sample/micro SFX, audio bus, weapon chimes; the bridge fires juice cues and lowpass changes.
  • Persist user data. There is one localStorage write (challenge-mode unlocked flag on the first final-boss clear) and nothing else. Settings, profile, ship roster, run history live in the React stores.
  • Reach into Discord, GitHub, Cloudflare, Vercel, or any agent surface. None. The engine is a pure browser/WebGL/Canvas runtime; ops adapters live in .agents/.

Pattern notes

  • The bridge is a closure factory: createMission() builds a closure over per-mission let bindings (_dpr, paused, rAF, deathElapsed, _revivePromptActive, etc.) and returns a MissionHandle whose methods read and mutate them. No class, no central state object — the closure is the state.
  • Cross-submodule state that has to outlive the closure (death debris pool, explosion-flash pool, fog flags, intro fade, illumination/trigger refs, hull class, atlas-patched set, etc.) lives at module scope. The extracted submodules import these directly rather than receiving an explicit state arg, so they’re effectively a free-floating module singleton. bridge-phase-state.ts defines a MissionState shape that consolidates the per-mission lets; it is read by extracted helpers but the closure body still uses the original locals.
  • Shared resources are warmed at mission start: every (archetype × rarity) enemy outline + every boss roster sprite is baked into the atlas once in _bakeAllEnemySprites / _bakeAllBossSprites so the first encounter doesn’t hitch.
  • Dispatch-site override-maps are the dominant per-event-type pattern: separate const maps for audio cue, camera shake, VFX burst tint, debris tint, debris count multiplier. Missing entries fall back to a default; adding a type means adding rows to the maps without touching the dispatch loop.
  • Frame loop uses two time deltas: dt (sim, gated by timeDilation, zero during reward freeze / wheel) and rawDt (wall-clock, used for animation that must play through freezes — reward reveal, particles, dmg numbers, weapon-chest collect, dead-phase countdown). The two are sourced from game._dt and game._rawDt which gameLoopTick writes.
  • Frame scheduling has three modes: rAF (normal), setTimeout(16) (sandbox — Preview throttles rAF when hidden), and manual pump (tests, drive frames by calling testPumpFrame). Pause schedules the next frame so a paused mission still responds to resume without re-entering the loop machinery.
  • The reward queue is single-slot in practice: only one reward dispatches per frame, gated on !game.currentReward && !isRewardActive() && ship.alive && !game._wheelState. Family is preserved on game._rewardFamily so HUD and reroll/banish can route consistently.
  • Level transitions go through _completeLevel() from three call sites (boss-clear flag, timer expiry, vestigial portal entry); it inserts an end-of-level artifact reward when one is available, otherwise falls straight through to level_advance. The portal path is dead — it survives only for legacy dev/test scenarios.
  • Death has three sub-states inside phase==='dead': cinematic playing, revive prompt active, declined / no-defiance fade-to-results. Each ticks rawDt only; the sim is frozen.
  • Boss bar damage is coalesced into a single per-frame popup + camera shake + bar flash via game._pendingBarDamage instead of firing per hit — the encounter can take dozens of hits per frame and one popup per frame reads cleanly.
  • Late-bound adapters: affix code can’t statically import damagePlayer or the prop pool because of a cycle through world/artifacts → affixes/index → data/affixes → runtime, so the bridge installs them at module load via setAffixDamagePlayer(damagePlayer) and setAffixSpawnPropAt(...). Same module also calls initAffixRegistry() once.
  • Dev / playground hooks live behind a PERF_FLAGS.devScenario || runDef.sandbox gate and write to window.__dev, window.__diag, and a singleton boss event log. HMR guards prevent multiple registration.
  • Several per-frame caches are populated speculatively to avoid hot-path allocations: _enemyRegionCache (archetype → rarity → atlas region + rotation offset), _cachedShipDiffuse + _cachedShipAspect + _cachedShipPxRMult, _bossImpactTracers, _hpBarBatch. They get reset on hull change / rarity change / mission start.