Log inGet started
◇
component · drop-in viewer
asset⌬ componentcomponentprimary: init.luau·originates fromworld b0f23b4e-e…

body

The survivor's body, and the record of the run. Attached to `GameDirector` by the scene build.

byPolar Night·posted 1mo ago
What it does

firstlight.body

The survivor's body, and the record of the run. Attached to GameDirector by the scene build.

What it runs, every play frame

  • Where the local player stands: Rules.state.body.indoors is true inside the living hut's footprint; nearFire (0..1) is the stove's warmth reaching the body, full within a metre of the firebox and gone at fireReachM.
  • coreC: loses lossPerDegree per second per degree the felt temperature sits below comfortC — the hut's insideC indoors, the weather's chillC outdoors — multiplied by 1 + 2.5 * wet; gains fireGain * nearFire. At -40 C in still air a warm body dies in about 15 real minutes (1.5 in-game days); by a high stove it is back to normal in three.
  • kcal: Rules.KCAL_PER_DAY_REST per day at rest indoors, toward Rules.KCAL_PER_DAY_WORK moving outdoors.
  • wet: snow and storm soak clothes outdoors; the fire dries them.
  • frostbite below Rules.CORE_C_FROSTBITE: the avatar's CharacterController.moveSpeed is scaled by frostbiteSpeed until the core recovers.
  • Death at Rules.CORE_C_DEATH or Rules.KCAL_DEATH, through firstlight.legacy: the run ends, the last journal line is written, the cache is stashed, the save is written and death { cause, day } is emitted. A death another slice emits (the bear) is handled the same way.
  • Sleep (sleep event): eight hours of rest at the hut's warmth.
  • The journal: a line for the day that ended on every day event.
  • The save: firstlight.persist writes run, body, hut, stores and journal on every day, sleep, death, patch and (throttled) store change, and on leaving play; it reads them back at awake so a reload resumes the same morning. The forecast seed is chosen once per world at the first load.

Methods (call with a colon on entity.find("GameDirector").component.get("body"))

MethodDoesReturns
body:eat(kcal)Adds calories (a tin is about 800).calories held (number)
body:warm(degrees)Warms the core directly (a hot meal).core C (number)
body:newRun()Starts the next run from the death screen: body, clock and stores reset to the start values plus the cache; journal, seed, deaths, patched gaps and drilled hole stay. Emits newRun { deaths, cache }.—
body:save()Writes the save now.—
body:state(){ coreC, kcal, wet, frostbite, indoors, nearFire, alive, day }table

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

firstlight.body — the survivor's body, and the record of the run. Attached to `GameDirector` by the scene build. Every play frame it reads where the local player stands, what the weather and the hut are doing, and moves core temperature, calories and wetness on `Rules.state.body`. Frostbite slows the walk; a core that bottoms out, or an empty stomach, ends the run through firstlight.legacy. It also owns the save: the run is read back at awake and written on every day, sleep, death and store change. Blackboard: writes `Rules.state.body`; owns `Rules.state.run` and `Rules.state.journal` through firstlight.legacy and firstlight.persist.

insideHut(x: number, y: number, z: number) → boolean

Whether a world position is inside the living hut.

argtypedescription
xnumber
ynumber
znumber

feltOutdoorsC( ) → number

The temperature the body feels outdoors. The weather slice writes the chill; until it has, the chill is the air temperature the rules give.

sayOnce(key: string, text: string, seconds: number?) → void

argtypedescription
keystring
textstring
secondsnumber?

resetSaid(prefix: string) → void

argtypedescription
prefixstring

findController(avatar: ?) → any

The character controller on the local avatar, found once per avatar.

argtypedescription
avatar?

applySpeed(frostbite: boolean) → void

argtypedescription
frostbiteboolean

subscribe( ) → void

awake( ) → void

update(dt: number) → void

argtypedescription
dtnumber

onDestroy( ) → void

eat(kcal: number) → number

Eat: add calories to the body (a tin is about 800). Returns the calories the body now holds.

argtypedescription
kcalnumber

warm(degrees: number) → number

Warm the body directly (a hot meal, a hot drink). Returns the core temperature.

argtypedescription
degreesnumber

newRun( ) → void

Start the next run from the death screen. Keeps the journal, the seed, the patched gaps and the drilled hole; stores restart from the start values plus the cache.

save( ) → void

Write the save now.

state( ) → void

The body as the survivor reads it.

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

15items
▣
module · born here
❒asset
# firstlight.legacy What the world remembers of a survivor. `require("firstlight.legacy")`. - `Legacy.note(text)` — add a line to the current day's journal entry (deduplicated). Any slice may call it for a notable event. - `Legacy.journalLine(day)` — the line for `day`: clock, weather words, stove, stores, frostbite, the bear, the notes. - `Legacy.recordDay(day)` — append that line to `Rules.state.journal`. - `Legacy.die(cause, day?, emitted?)` — end the run: `run.alive = false`, `run.deaths += 1`, the last journal line, the cache (a quarter of every store, on `Rules.state.run.cache`), the save. Emits `death { cause, day }` unless `emitted` says the event is already on the bus. Returns false when the run was already over. - `Legacy.newRun()` — the next run from the death screen. Resets body, clock and stores to the start values plus the cache; keeps journal, seed, deaths, `hut.gaps` and `stores.holeDrilled`. Emits `newRun { deaths, cache }`. - `Legacy.cache()` — the cache the last survivor left, or nil.
▲ 0↑ born
▣
module · born here
❒asset
# firstlight.rules The one module every part of First Light requires: `require("firstlight.rules")`. It holds the game's numbers (day length, temperatures, calorie burn, stove fuel rates, bear ranges, starting stores), the layout of the station and the sites around it, the shared blackboard `M.state`, the event bus `M.events`, and the clock. ## The clock `M.tick(dt)` is called once per play frame by the scene entrypoint. It advances `M.state.run.elapsed`, derives `M.state.clock` (day, fraction of day, hour, sun elevation, twilight openness) and emits `day`, `noon` and `firstLight`. `M.sleepToMorning()` jumps to 07:00 next day; `M.restore(elapsed)` rebuilds the clock from a persisted run. Pure helpers: `sunElevation(day, t)`, `twilightSeconds(day)`, `airC(day, t)`, `windChill(airC, windMs)`, `progress(day)`, `rng(seed, salt)`, `dist2d`. ## The blackboard `M.state` has one section per slice. A slice writes its own section and reads the others: `run`, `clock`, `weather`, `body`, `hut`, `stores`, `bear`, `journal`. ## Events `M.events.on(name, fn)` returns an unsubscribe function; `M.events.emit(name, payload)` calls every listener. The names and payloads are listed at the top of `init.luau`. `M.say(text, seconds)` emits `say` for the HUD.
▲ 0↑ born
▣
module · born here
❒asset
# firstlight.persist The run's durable memory, in the world's runtime data under `firstlight/`. `require("firstlight.persist")`. Persisted sections of `Rules.state`: `run`, `body`, `hut`, `stores`, `journal` — one leaf each (`firstlight/run`, `firstlight/body`, ...). - `Persist.load()` — read the saved sections over the blackboard and restore the clock from `run.elapsed`. Returns whether a save existed. - `Persist.save(reason?)` — write every section now. - `Persist.markDirty()` — ask for a save at the next throttle window. - `Persist.tick(dt)` — per frame; flushes a marked or detected change every few seconds (a store or structural value written straight onto the blackboard is detected by fingerprint). - `Persist.ensureSeed()` — choose `run.seed` once per world and save it. - `Persist.hasSave()`, `Persist.wipe()`.
▲ 0↑ born
backing path · firstlight/body.component

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.