bridge-hub-illumination

Hub illumination cascade handler. Runs when a hub transitions to illuminated state: purges dark_only events still attached to that hub, increments a global illuminated-hub counter consumed by the GameMaster director, and applies a radial outward shove to nearby enemies.

Exports

SymbolKindSignature
onHubIlluminatedfunction(hubId: string, hub: Hub) => void

Imports

SourceSymbols
./core/stateworld
../data/level-configHub (type)

Behavior — onHubIlluminated(hubId, hub)

Executes three sequential side effects on world:

1. Purge dark_only events

Walks world.events in reverse. For each event ev matching ev.hubId === hubId && ev.zoneConstraint === 'dark_only' && ev.phase !== 'done':

ev.phaseAction
idleSplice out of world.events
failedSplice out of world.events
activeSet ev.phase = 'failed' (kept in array)
doneSkipped — the event that just completed keeps its flash animation

The completing event is preserved by the phase !== 'done' guard. Only siblings are purged.

2. Increment illuminated-hub counter

(world as any)._hubsIlluminated = ((world as any)._hubsIlluminated ?? 0) + 1

Untyped sidecar field on world. Read by GameMaster as a director input. Initialized lazily via nullish-coalesce.

3. Enemy flee impulse

For every enemy in world.enemies, computes displacement from hub center (hub.x, hub.y):

  • dx = enemy.x - hub.x, dy = enemy.y - hub.y
  • dist = Math.hypot(dx, dy)

If 0 < dist < hub.r * 2, applies a linear-falloff radial impulse:

  • force = 300 * (1 - dist / (hub.r * 2))
  • enemy.vx += (dx / dist) * force
  • enemy.vy += (dy / dist) * force

Force magnitude is 300 at hub center, 0 at radius 2 * hub.r. Enemies exactly at the hub center (dist === 0) are skipped to avoid NaN.

Constants

ConstantValueMeaning
flee force300Peak velocity impulse at hub center
flee radiushub.r * 2Outer cutoff for the impulse

Coupling

  • Reads/writes world.events, world.enemies, world._hubsIlluminated (untyped).
  • Consumes Hub.x, Hub.y, Hub.r from level-config.
  • Caller: invoked at the hub-illuminated transition (caller site not in this file).
  • Consumer of _hubsIlluminated: GameMaster director.

EXTRACT-CANDIDATE

  • _hubsIlluminated is set via (world as any) cast — should be a typed field on the World interface in core/state, not an untyped sidecar.
  • Flee force 300 and flee-radius multiplier 2 are magic numbers — extract to named constants (e.g. HUB_ILLUMINATION_FLEE_FORCE, HUB_ILLUMINATION_FLEE_RADIUS_MULT) per CLAUDE.md “every number traces to a named constant”.
  • The three side-effect blocks (purge events / increment counter / flee impulse) could each be a named helper if this file grows; currently inline is fine.