# audio.Lines
Who says what, and how it is delivered.
Nineteen lines: the barker's four cards, his three lines as the house warms,
and three lines for each of the four clowns. Each was read once by the
generation service and cached as a `.soundClip` under `game/audio/voice`. Ada
never speaks; her lines are the cards.
The service offers one reading voice, so the four speakers are separated the
way a radio play separates them — by writing, by pitch, by level, and by how
far into the tent each stands. No voice id is invented.
## Where the words live
In `game.Core` — one copy, which the barker's cards, the clowns' lines, the
subtitle strip and these readings all take from. This module holds only who
delivers each line and `ms`, the clip's own measured length, so a subtitle can
be timed before the mixer has decoded anything. The delivered length is
`ms / pitch`; a line with no clip is timed by `Core.readingTime`, the same
clock every other caption in the game runs on.
`Lines.sync()` re-reads every line's words out of Core. Both are modules and
either can be reloaded under the other, and a subtitle that says something its
clip does not is worse than no subtitle — so `game.audio.bus` calls it each
time it installs.
`Lines.forClown(id, which)` and `Lines.forHeat(level)` name the clip for a
clown's `enter` / `laugh` / `die` and for the barker's line at a heat level.
Every line ships with its written form: `game.audio.bus` emits
`voice.line { speaker, text, durationMs, voiced }` whether or not the reading
is there, so a line that failed to generate is printed rather than lost.
# Core
The one table every part of GREASEPAINT reads. It carries the game's
constants — the cards, the four clowns, the barker's lines, the palette and
the fonts — the live state of the night, and the event bus the game talks
over. Every other module requires this and nothing else of each other.
`game.rules.Director` is the **only** writer of `Core.state()`. Everything
else reads the state, listens on the bus, and asks the Director for changes
through `Core.cmd`.
```luau
local Core = require("game.Core")
Core.state().nerve -- read the night
Core.on("clown.hit", function(p) ... end) -- react to it
Core.cmd("playCard", { index = 2 }) -- ask the Director to act
```
## Constants
- `Core.RULES` — Nerve, Breath, hand size, the Laughter ceiling and where the
meter carries to after a laugh, how warm the house can get and what a step
of heat is worth, what a held Grin bites, how many acts a night runs, which
act's interval takes a card away instead of giving one, the starter deck
and the reward pool.
- `Core.CARDS` — the twelve cards, each with `kind` (`gag` / `guard` /
`trick` / `curse`), `cost`, and whatever it does: `dmg`, `block`, `heal`,
`laughter`, `effect` (`weaken` / `reflect` / `burn`), `exhaust` when playing
it takes it out of the act, and the `text` its face prints.
- `Core.CLOWNS` — Pinch, Bello, Slats and Mr. Marrow: `hp`, a looping
`pattern` of intents, and three spoken `lines` (`enter`, `laugh`, `die`).
- `Core.RUN` — the three-clown pool and the finale.
- `Core.BARKER` — the Ringmaster's four narrated lines, and `heat`, the one
he marks each step of the warming house with.
- `Core.PALETTE` / `Core.FONTS` / `Core.ANCHORS` / `Core.SEAT` /
`Core.PHASES` / `Core.EVENTS` / `Core.COMMANDS`.
## State
- `Core.state()` — the live night. Phase, act, turn, Nerve, Breath, Block,
Laughter, the `heat` the house has reached, the `library` (every card the
night owns) and the working piles drawn from it (`deck`, `hand`, `discard`,
`exhaust`), the current `clown`, the `reward` on offer — its `cards`, the
`next` clown it names and its `mode` (`take` or `leave`) — the focused
index, and the `order` the four acts run in.
- `Core.reset()` — replaces the state with a fresh night, in place, so a
reference held across a restart stays valid.
## The bus
- `Core.on(name, fn, tag?) -> unsubscribe` — subscribe. A `tag` makes it
idempotent: registering the same event and tag again replaces the earlier
subscription rather than stacking a second copy, which is what keeps a
reloaded component from handling everything twice.
- `Core.off(name, tag)` — drop a tagged subscription.
- `Core.emit(name, payload)` — fire to every subscriber, in order. A
listener that errors is reported and the rest still run.
- `Core.cmd(name, payload)` — `Core.emit("cmd." .. name, payload)`.
- `Core.listenerCount(name)`, `Core.clearListeners()`.
## Chance
The night's randomness is one stream, seeded per run, so a seed replays a
whole night: the act order, the shuffles, which card the tent paints, which
three cards a reward offers.
- `Core.random()` — the next value in [0, 1).
- `Core.randomIndex(n)` — an integer in [1, n].
- `Core.shuffle(list)` — shuffle in place, return the list.
- `Core.rand(salt)` — a stable value for a salt, independent of the stream.
## The frame
Every screen, plate and card lays out from the live frame, so any shape holds.
- `Core.frame(override?)` — `{ w, h, u, wide }`. `u` is a hundredth of the
short side: the unit every proportion is stated in. `wide` is true from an
aspect of 1.25 up. Pass `{ width, height }` to lay out against a shape the
engine is not running at.
- `Core.rgba(hex, a)` — a palette hex with an alpha, as the `rgba()` string a
widget takes.
- `Core.hairline(n)` — a rule of `n` pixels, never thinner than one whole one.
## Also
- `Core.card(id)` / `Core.clown(id)` — a record, or nil.
- `Core.readingTime(text)` — how long a spoken line should sit on screen, in
milliseconds, when no generated clip has answered for it. Between 1.4 and
9 seconds, whatever the length.