cast
The three who remain in Amagiri: **Hozuki** on the shrine platform, **Ui** in the drowned street, **Kagen** at the foot of the cliff path.
cast
The three who remain in Amagiri: Hozuki on the shrine platform, Ui in the drowned street, Kagen at the foot of the cliff path.
The slice puts three things into game.Game and owns nothing else:
| What | Through | Read by |
|---|---|---|
| five emotion frames per character | Game.registerPortrait | vn |
| one conversation per character | Game.registerDialogue | vn |
| one interactable per character | Game.registerInteractable | traversal |
…and it builds the three bodies under its own slice root.
The pieces
| Module | What it holds |
|---|---|
cast.module | the slice: mounts the other three, wires the event handlers |
cast.scripts | the three dialogue trees, as data |
cast.portraits | the emotion frames and their registration |
cast.figures | the standing bodies, their rings and their lamps |
portraits/ holds the baked frames — <character>_<emotion>.texture, fifteen
of them.
The faces
Each character has five frames, one per Game.EMOTION. Every frame is that
character's own body, so the face is the same face across all five; what changes
between them is the pose, the light and the colour of the air:
| Emotion | The frame |
|---|---|
neutral | square to you, even cold light |
warm | turned in, tilted, lit amber |
hurt | turned away, chin up, cold blue |
angry | chin down, seen from below, hard red |
broken | head far down, eyes lost in shadow, drained to grey |
A portrait spec is the images shape:
local p = Game.portrait("hozuki")
p.images.warm -- "cast.portraits.hozuki_warm", a texture asset identity
p.paths.warm -- "/zero/source/cast/portraits/hozuki_warm.texture"
Hand images[emotion] to an image widget's src:
{ type = "image", props = { src = Game.portrait(id).images[emotion] } }
The conversations
Each tree has a route that ends in the spirit handing their Resonance over
(grant, then done = "granted"), and a route that ends without it
(done = "refused"). Kagen also has done = "left" — he has not finished with
you and the conversation opens again unchanged.
Each also carries startFaded, a much shorter set used when
Game.fading() > Game.tuning.fadedThreshold: by then the spirit has lost most
of what they were willing to say, and there is one question left instead of
three.
Once a conversation resolves, the slice swaps that script's start for an
epilogue, so walking back to a spirit you have already spoken with is a
different, shorter scene. Game.resetRun() puts the openings back.
| Character | Resonance | Opens if you | Closes if you |
|---|---|---|---|
| Hozuki | chime | ask her for the thing rather than for her story, and let her hand it over | treat her brightness as the whole truth, or leave it with her out of pity |
| Ui | hush | tell her the truth gently, neither playing along nor breaking it over her | play along until she stops asking, or say it flatly |
| Kagen | edge | say plainly what the top is for, then ask what his refusal is holding back | use his failure as a lever, or reach for the edge like a gate key |
The bodies
Three generated cel-shaded figures, each standing in a slow ring of its own resonance colour under a lamp of the same, so a spirit reads as a landmark through the fog. They carry no collider: they are spirits, and a body that stops you at the exact spot the interact prompt fires is worse to walk into than a spirit is to walk through. A spirit who has handed their piece over stops holding a light for it.
Rebuilding it
require("game.Game").rebuild("cast")
Scoped to this part · feeds back into the world's score.