# torch
<!-- zero:scaffolded-readme -->
<!-- Replace the line below with what this module provides and who
consumes it, then delete both comment lines. -->
TODO: describe this module.
# wiring/shell
The `shell` slice's one hook into the scene. It puts `RunDirector` on the
scene's `director` entity and gets out of the way — everything the run does
lives in that component.
- `attach.director` declares `RunDirector` so a scene rebuild bakes it in.
- `onSceneReady(ctx)` adds it at runtime as well, guarded on the component
already being present, because the far more common case is a scene that
is already built and will never bake anything.
The fields it attaches with: `dockRadius = 9` (metres from the cargo maw
that count as docked for the win check) and `previewInEdit = false` (the
instrument layer stays off the glass while authoring, so another slice's
viewport capture is not covered by a HUD it did not ask for).
Everything the rest of the game needs from `shell` is in `game.rules`: it
writes `state.phase`, `o2`, `integrity`, `banked`, `instability` and
`cutsMade`, emits `phase(newPhase)` and `instability(level)`, and consumes
`severed`, `deposited` and `impact`.
# game.wiring.reset
The reset's entry in the wiring registry.
It attaches nothing: putting the world back is a listener on the run's phase,
not a behaviour belonging to any one entity in the scene. `onSceneReady`
subscribes `game.reset` to the rules bus and restores the skiff's cargo maw if
it is missing.
# look
HULLBREAKER's visual slice. This module is the wiring; the visual pass itself
is `game.dressing`, applied on every scene load in edit and in play.
What it puts on screen:
- **The backdrop.** `art.sky.deep_space` through `art.sky.hullbreaker_void` —
a black void, a three-layer star field on a cube-face grid, a dusty galactic
band, a faint nebula wash and the sun as a hard half-degree pinpoint with no
glow around it.
- **The hull.** `art.hull.hull_steel` — welded panel courses, rivet rows,
plate-thickness variation, rolled grain, grime and oxide, all generated
triplanarly in world space so a truss rib at 3x, a pressure hull at 5x and a
cut plate at 1x share one texel density and no textures at all. Five
materials tune it: `kestrel_hull`, `kestrel_truss`, `salvage_plate` (hazard
striped), `skiff_shell`, `cut_seal` (emissive).
- **The planet.** `art.sky.orbital_body` — continents, ocean shelves, ice caps,
a cloud deck that turns, city lights on the dark side, an atmospheric limb.
- **The light.** One hard cold sun three-quarters behind the player's right
shoulder, near-black ambient, ACES + bloom + vignette.
- **The dust.** Suspended motes through the shaft, lit by the same sun, and a
vent plume off each pressure hull.
## What other slices may call
```lua
local Dressing = require("game.dressing")
Dressing.setNodeHeat(nodeProxy, 0.0 .. 1.0) -- how hot a cut node looks
Dressing.extinguishNode(nodeProxy) -- its seal is gone; kill the glow
```
`look` already extinguishes a whole plate's nodes on `severed`.
# flight
The `flight` slice's wiring. It puts the `Scrapper` suit on the player's
body, by both of the doors a slice has into a scene it does not own:
- **`attach`** bakes `Scrapper` onto the PlayerPrototype's body the next
time the scene builds, so every joining player is cloned with a working
suit.
- **`onSceneReady`** installs the same component on the body this client is
already driving, so a session that is mid-play when the slice lands gets
thrusters without a scene rebuild.
Both paths check first, so a body never ends up with two suits fighting
over one velocity.
What this slice offers the rest of the game is documented on the component
itself — see `game/Scrapper.component`. The short version, for `hazard`:
```lua
entity(bodyId).component.get("Scrapper"):applyImpulse(dx, dy, dz)
```
Nothing outside this slice writes the player's position or velocity.
# game.wiring.hazard
The **hazard** slice's door into the scene. Owned by the hazard slice; no
other agent edits this file.
## What it wires
- `attach.director` → `HazardDirector`, so the wreck's temper is baked onto
the scene's `RunDirector` the next time `build.luau` runs. It is **also**
ensured in `onSceneReady`, because `attach` only takes effect on a scene
rebuild and this slice does not own that file — so the slice works either
way, and adding it twice is guarded.
- `onSceneReady` → `game.hazards.buildRig()`, which spawns everything else at
runtime under one `HazardRig` root: seven `PressureVent`s down the shaft,
six `Debris` cross-braces that are structure until they are not, and
fourteen `Debris` chunks adrift. It runs in **both** edit and play, so a
vent can be looked at and tuned while authoring instead of only existing
once someone presses play.
## The slice, in one line each
- `game/hazards.module` — the numbers, the manifests, the arming gates, and
the two calls a hazard is not allowed to make for itself
(`playerBody`, `impulse`).
- `game/PressureVent.component` — the jets. Rest, glow, blow.
- `game/Debris.component` — braces that let go, and junk that drifts.
- `game/HazardDirector.component` — when a member lets go, how much junk is
awake, and every counter a run can be read by.
## What it takes from other slices
- `state.instability` (written by `shell`) is the only input. 0 is quiet;
vents arm at 1, collapse at 2, debris at 3.
- `state.phase` — hazards stop entirely once the run is `won` or `lost`.
- `flight`'s `Scrapper:applyImpulse(x, y, z)` is the only way this slice moves
the player, resolved off the component's declared surface at runtime.
## What it gives back
`RULES.emit("impact", amount, source)` with `source` in
`"vent"` / `"collapse"` / `"debris"`. Nothing else crosses the boundary.