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, framerAFhandle, manual-pump flag,_dprsnapshot, 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,resultsand the bookkeeping that flips them (reward dispatch, death detection, boss-clear flag, timer-expiry, portal-entry vestige). - The
MissionHandlesurface 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-configforRunDefinition+ validator + default;data/mission-resultfor the snapshot shape;data/planet-configfor the active planet record;data/shipsfor hull classes + rarity-derived sprite scaling;data/hull-hitboxesfor collision polygons;data/weaponsfor weapon defs + per-level stats;data/enemiesfor collision scale + radius;data/level-configfor default level config + hub typing;data/level-progressionto resolve next-level kind + final-level test;data/bossesfor boss-def per-frame escalation;data/economyfor death-defiance tuning;data/run-historyfor the new-account spawn dampener;data/artifactsfor the artifact catalog;data/modifiersanddata/mod-templates+ the mod grid service for sandbox mod equip;data/affixesindirectly via the affix registry.engine/corefor 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/weaponsfor theWeaponManagerAPI, manual-fire latch, delayed-shot queue tick, fire-rate nerf, bullet-bin size, bullet behavior registry.engine/enemiesforGameMaster,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/combatfor the collision resolver, damage entry points, terrain push-off, XP-orb spawn, death VFX update, hull-poly transform.engine/affixesfor the catalog init, on-spawn/on-update dispatch, late-bound damage and prop-spawn adapter setters.engine/physicsfor terrain collision helpers and the Rapier world/ship/terrain/enemies/debug subsystems.engine/worldfor 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/effectsfor the unified effect engine, status tick, run-effects register/teardown, custom flame-zone draw.engine/playerfor the exclusive-state predicate + tick + apply.engine/abilitiesfor the per-frame ability tick.engine/bossfor sealed-arena + boss-room helpers, encounter spawn/end, shared boss VFX kit;engine/destructiblesfor hazard-zone tick.engine/vfxfor 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/renderingfor 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/audiofor the music player, audio bus, sample SFX, micro SFX, weapon chimes.engine/telemetryfor the collector, sender, sampler, perf observer, long-task observer, FPS tick, refresh-rate sampler, diag log.- Browser surfaces:
requestAnimationFrame/setTimeoutfor scheduling,performance.now()only via the frame scheduler accumulator,localStoragefor the challenge-unlocked flag,crypto.randomUUIDfor the sampler run id, the canvas + 2D context.
PUSHES TO
- The provided
BridgeCallbacks:onPhaseChangeon every transition,onGameOveron results,onRewardShowon each reward open,onRevivePromptwhen the revive prompt arms,onReviveDismissedon prompt auto-dismiss or decline. engine/corestate 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/worldmutation: 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/telemetry—telemetry.beginat mission start, per-frametick, weapon-fire + reward + death + director-phase records,finalize+sendRunTelemetryon results;Sampler.setRun+setRun(null), periodic snapshots, lifecycle events (run_start,level_start,level_complete,boss_spawn,boss_death,player_death,run_end,recover_buttoncrash), explicitflush.engine/worldartifact 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 viaEventSpawner.seedHubs; set active hull + rarity; pre-bake every (archetype × rarity) outline and every boss sprite; apply ship combat stats from RunDef ontoship; mount starting weapons with fire-rate nerf + cooldown derive; install starting artifact (+ dev auto-artifacts); install run-effects + affix registry; build the emptyMissionResult; exposegame.runDef; apply per-level base world knobs with new-account dampener; spawn n weapon boxes fromweaponBoxCount; place supply-level-1 weapon chest near the player; wirephase_changesignal toonPhaseChange; reset tutorial; install dev-playground console API. - Mission start (
handle.start) — flip phase toplaying, 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 usesrequestAnimationFrame; manual-pump mode (tests) suppresses both and waits fortestPumpFrame.pausedshort-circuits to a reschedule. - Per-frame entry —
gameLoopTick(now)(physics, input, camera, timers, fixed-step accumulator); readdtandrawDt; 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_artifactreward, orlevel_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 block —
GameMaster.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_upgradeauto-apply + upgrade-show;artifact_box→ upgrade-only rolls;end_of_level_artifact→ 3 new artifact choices;shooting_star→ 2 category choices;weapon_boxwith slots-full snapshot → auto-upgrade-show fallback or 3 weapon choices; default → modifier + weapon choices); set phaselevelup, freeze, lowpass music, start reward reveal, fireonRewardShow. - Effect + VFX tick —
tickArtifacts,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 + cleanup —
game.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→ fireplayer_deathsampler event, cancel any active reward overlay, flip phase todead, 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; otherwisedeathTimercounts down toresultswhich populatesMissionResult(outcome / performance / progression / combat / economy / exploration / score / reward tier), records death telemetry, finalizes + fire-and-forgets the run telemetry post, firesrun_end, flushes the sampler, firesonGameOver. - 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), firelevel_startsampler, trigger fade-in, flip phase toplaying, 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, fireonGameOver. - Render — context-loss probe (synchronous
isContextLostor 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 todead,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 tocallbacks.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 forphase_change → deadduring boss fights.
Entry points
createMission(canvas, callbacks, runDef)— module-level factory. Returns aMissionHandle.MissionHandle.start— install Rapier + telemetry, flip toplaying, schedule the first frame.MissionHandle.setInput(angle, magnitude, thrusting)— push joystick state intoplayerInputandship.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 inbanishedKeys+ 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-terminatingMissionResultsnapshot for cog-menu exit andbeforeunload.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.gameLoopTickowns 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-resolverresolves;engine/combat/damageis 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.tickandDirector.updateown spawn cadence; trigger callbacks queue spawns; the bridge only ticks them. Sealed-arena bosses spawn throughengine/boss/encounter. - Decide what counts as a kill, an elite, or a streak.
engine/combat/damage+engine/world/levelingown those. - Run the weapon fire pipeline. The bridge calls
WeaponManager.fireper 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/encounterdrives spawn → arena alive → bar live → encounter end; the bridge only dispatches the active boss-def per-frameonUpdatehook + 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(androllArtifactChoices,generateShootingStarChoices,banishKeyForChoice) own those; the bridge only routes by family and stuffs the result ontogame.currentReward. - Render anything itself. Every draw goes through
engine/rendering/*andengine/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
localStoragewrite (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-missionletbindings (_dpr,paused,rAF,deathElapsed,_revivePromptActive, etc.) and returns aMissionHandlewhose methods read and mutate them. Noclass, 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.tsdefines aMissionStateshape that consolidates the per-missionlets; 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/_bakeAllBossSpritesso 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 bytimeDilation, zero during reward freeze / wheel) andrawDt(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 fromgame._dtandgame._rawDtwhichgameLoopTickwrites. - Frame scheduling has three modes: rAF (normal),
setTimeout(16)(sandbox — Preview throttles rAF when hidden), and manual pump (tests, drive frames by callingtestPumpFrame). 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 ongame._rewardFamilyso 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 tolevel_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 ticksrawDtonly; the sim is frozen. - Boss bar damage is coalesced into a single per-frame popup + camera shake + bar flash via
game._pendingBarDamageinstead 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
damagePlayeror the prop pool because of a cycle throughworld/artifacts → affixes/index → data/affixes → runtime, so the bridge installs them at module load viasetAffixDamagePlayer(damagePlayer)andsetAffixSpawnPropAt(...). Same module also callsinitAffixRegistry()once. - Dev / playground hooks live behind a
PERF_FLAGS.devScenario || runDef.sandboxgate and write towindow.__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.