Hub Illumination Map
The illuminationMap is a per-hub Map<hubId, boolean> (semantically a set of lit hub IDs) that records which hubs the player has illuminated this run. It is the core progression signal a run produces.
Lifetime
- Per-run. The map is owned by
LevelDataand lives for the duration of one run. - Permanent within the run. Once a hub is set to
truevia lantern activation, it never reverts. There is no “darken” path during play —setIlluminationexists only for playground/debug. - Initialized from level data. When the illumination system is constructed (
createIlluminationSystem), each hub’s lantern is markedactivatedif the level data’silluminationMapalready has that hub set totrue— allowing pre-lit hubs to be seeded by generation.
Writers
Exactly one gameplay writer: tickIllumination in engine/world/illumination.ts. When a lantern’s fill reaches 1 (player standing inside the activation circle for the fill duration), it:
- Marks the
LanternStateasactivated. - Sets
illuminationMap.set(hub.id, true). - Increments
hubsIlluminated. - Fires all registered
onActivatecallbacks (includingonHubIlluminatedinengine/bridge-hub-illumination.ts).
Debug/manual writes go through setIllumination, which also recounts hubsIlluminated.
Readers
Two main consumers consult the map every frame:
- Spawner / zone resolution. Spawn pools and event eligibility branch on whether a hub is
darkvslit.getIlluminatedHubIdsreturns the lit set;isHubLitanswers point queries. The cascade handleronHubIlluminatedimmediately cullsdark_onlyevents in the just-lit hub (idle/failed events spliced out, active events flipped tofailed). - Renderer. Palette swap is driven off the same map — lit hubs and lit spokes render in the illuminated palette, dark hubs in the dark palette.
Spoke illumination
Spokes are not stored in the map directly. isSpokeLit(system, spoke, hubs) returns true if either endpoint hub is in the map — a single lit endpoint is enough to light the whole spoke. This means lighting a hub immediately illuminates every spoke touching it, even if the far endpoint is still dark.
Related
- Lantern activation mechanic — see
engine/world/illumination.tsconstants:ACTIVATION_RADIUS_FRAC = 0.35,DEFAULT_FILL_SECONDS = 4,DRAIN_RATE = 0.5. Fill duration scales withconfig.illuminationSpeed(0 = instant, higher = slower). - Cascade side-effects on activation —
onHubIlluminatedalso pushes nearby enemies away from the hub (force300 * (1 - dist / (hub.r * 2))withinhub.r * 2) and bumpsworld._hubsIlluminatedfor the director.