The Eighth Ketyl
Commits
Every published commit of this world, on every branch, newest first.
e99ff0a216showcase: seven gameplay and interface stills for the world pagee446f6decafix(scene): drop a component field the Screens component no longer declares
The caption band stopped being optional, and the scene kept carrying the
switch. Every reconcile of that component raised 'has no field ownCaptions'.f55e7e2794fix(ui): a card close to square keeps its last row on screen
The type is sized off the shorter screen edge, so a screen only slightly
taller than it is wide sets it as large as a much taller one while having
less room for it, and the tail of the title card ran off the bottom. The
still in elevation now gives that height back as the shape approaches
square, and the display type is bounded by the height as well as by its
column.ffc5758d51fix(ui): the caption band clears the bottom edge on a short screen
Its lift was a share of the shorter screen edge, which on a wide short frame
put the band a third of the way up the picture. It is now a share of the
height, so it sits just above whatever stands under it — the meters during
play, the letterbox during a moment — at every shape.2761ff16bafix: the camera clears the riser, the opening plays, every spoken line is printed, and the still is dark again
Playtest fixes from the final pass:
- the playing camera no longer solves a pose inside plate 1's riser throat
- the opening cutscene is no longer cancelled by a phantom play phase
- the spoken lines are printed on screen again; neither slice was drawing them
- the caption clears the cinematic letterbox, and the HUD leaves the glass for a moment
- menu focus answers a pad, a keyboard and a finger; a resting mouse no longer pins it
- the still is graded back to a near-black interior lit by the radical
- wetness and charge are balanced so eight plates can be climbed
- the on-screen controls no longer carry Jump, Sprint and Crouch
- the HUD meters clear the touch overlay, and end-card words stay in their column
- a pooled sound voice is rebuilt when its entity is gone, instead of raising every drip
- a player-facing README69ed0a52e4core: re-arm and re-install after the core module reloads
Editing KetylCore re-runs that chunk and leaves its dependents alone: the module
table keeps its identity, its functions are replaced, and every local behind
them starts over — including the record of who holds the controls and the table
the conductor leaves its handlers in. Neither component's awake() runs again to
notice, so a mid-session edit left the ketyl still and the bus deaf while every
reading said the game was fine.
Each half now watches for the one reading that says it happened — nobody holding
the controls, an empty handler table — and re-arms or re-installs from update.
Verified by reloading the module under a live run: the pilot re-armed, the
conductor re-installed, and one uiIntent produced exactly one runStart.ebaab636b4core: release core's registrations through modules.onUnload
The run that subscribes to the Still bus and to ketyl.inputMap's controls is
the only one holding the unsubscribers, and a hot-reload replaces it. This
gives that run the engine's own teardown hook instead of parking the handles
on a module nobody reloads, and wires the bus at module load so core's ear
survives a reload with no component having to notice.
KetylPilot takes and gives up the controls in onEnable/onDisable, since
liveness follows who has control rather than what exists.226858daf7presentation: pointerFollow guards a pointer reading that carries no position
ui.pointerWidget() can answer with x and y unset — between touch contacts, and
on the frame after the pointer is released — and ui.hitTest takes numbers, so
the hover-follows-focus pass raised every frame the pointer was at rest.
Caught in the engine log; the screens themselves were unaffected.540503ad88core: the run's rules and the ketyl's hands
Conductor owns the state machine (title/intro/play/cleared/sealed/quenched/
paused), plate progression, the riser, charge and wetness, and is the only
writer of Still.state. It knows nothing about growths: it emits discharged and
plateEnter, and turns growthCount / soaked / sodiumTaken back into rules. A
plate nobody reports opens after a grace window, and says so.
KetylPilot activates ketyl.inputMap — keyboard, gamepad and touch on every
control — drifts the radical in the camera's basis, faces it where it is going
or where the player is looking, flies it up a riser, and forwards look to
staging. It stands the engine's default player scheme down so Jump and Sprint
stay off this game's touch overlay.
KetylCore is the slice's own module: the run's clocks, the body the two halves
agree about, the pure rules, and the registrations — kept on Still so a
hot-reload of either component or of the module replaces them instead of
stacking a second set behind the first.aea32e1099presentation: the title, the how-to card, the HUD, the pause card and both end cards
Every screen the game puts between the player and the still, composed rather
than defaulted, and the focus model that makes all of them reachable from a
gamepad alone.
- ui.Kit — the design system: the palette from Still, a two-face type ramp (EB
Garamond for the laboratory's voice, JetBrains Mono for the instrument's),
panel and backdrop recipes for a dark UI, the drawn column in elevation that
the title card and both end cards are built around, key/pad/touch glyphs, and
the instrument meter. Every size is a fraction of the SHORTER screen edge read
live, so no layout carries a pixel constant.
- ui.Focus — an ordered ring of focusable ids walked by the stick or the d-pad,
acted on by confirm, left by back, and re-pointed by a mouse crossing a row or
a finger tapping it. The held repeat is gated in frames as well as seconds, so
one flick is one step even when a frame carries half a second of dt.
- ui.Menus — the five cards. The title and the end cards put the column beside
the words on a wide frame and above them on a tall one; the how-to card
becomes two columns on a wide frame so its six controls and four steps fit a
television without being cut.
- ui.Hud — the plate ladder down the left edge, the plate number and the growths
left opposite it, charge and wetness across the bottom, a wash that pulses in
as the run gets wet, and the riser prompt naming the key, the pad button and
the touch control at once.
- Screens.component — holds the phase, keeps console.inputMap live exactly while
a card is open, and emits uiIntent. It never runs the game.
Checked with a simulated gamepad twice end to end (title -> how-to -> back ->
begin -> end card, focus read back at every step), with a keyboard, with a mouse
and with a finger, and laid out and captured at 1080x1440 and at 1600x900.ce0301688fblennoma: the growths, their weeping, their burning, and the sodium
The mucous growth as a hero asset and its whole behaviour, plus the sodium
nodes the ketyl takes charge from.
Meshes come from three parametric SDF graphs in /source/growths — a blennoma
(foot, ring-cut waist, sac, three shoulder lobes, two hanging teats, then three
displacement layers for wrinkles, lumps and pores), a lump of cut sodium whose
flat knife face is the whole read, and a falling water bead. bake.luau
evaluates each variant and writes the .mesh assets in place.
Materials are all pbr: wet clearcoat and a short deep subsurface for the
membrane, a hot near-black emissive for the weals a burn opens, half-metal for
the sodium (a full metal in a room with no light in it is black), and a dark
translucent film for the pools.
Five sound effects are synthesised from raw PCM in bake_sfx.luau and registered
into audio.Clips under the ids the game names them by, with a fallback voice so
a growth is never silent for want of the library.
BlennomaField builds a plate's field from a generator seeded on the plate
number alone, so every peer lays the same growths in the same places. It
reports growthCount, growthHurt, growthBurned, dropletSpawn, dropletLand,
soaked and sodiumTaken, and knows nothing about health or charge.bb9e100362sound: the score, the still's ambience and both voices
The music bed counted in eight, the ambience of the still, twenty one-shots,
the mix, the shared clip library, and the sixteen spoken lines.
- audio/Synth.module the bake-time DSP kit: an oscillator/noise voice through
an envelope and a swept filter, whole-track passes, and the two things that
make a loop seamless without loop points (frequency snapping, tail wrapping)
- audio/Script.module the words, the one place they are written
- audio/Clips.module the shared sound library other slices register into, plus
the script read-through staging asks for text, speaker and measured duration
- audio/clips/ bed_music (19.2s), amb_still (12.8s), amb_room (11.0s),
and 20 one-shots
- audio/voice/ all 16 lines, the chemist over a radio, the column pitched
onto a machine's clock and ring-modulated onto a carrier
- Score.component the runtime: three background sources, the voice, ducking,
the bed's arc up the column, the wetness alarm, and the mix
Both looping beds are stored as pcm and loop end to end: the step across the
loop point is 3.8% of the largest step inside the bed.
---
column: the still — eight sieve trays, the glass, the brass, and every light in it
The landmark the camera keeps returning to, built as children of the Column host
from Still.module's geometry.
- env/ColumnGeometry.module the mesh kit: surfaces of revolution, a polar-grid
deck that carries a hole where a riser passes through, tubes, annuli and boxes,
all accumulating into one merged mesh per part
- env/still_metal.shader tarnished brass and blackened iron, with a
perforation field that turns a flat deck into a sieve tray, and a per-instance
lane so one material serves eight risers at eight brightnesses
- env/still_glass.shader the column wall: beaded condensation gated by
vertical run marks, a rim that carries the light, two-sided
- env/still_haze.shader a sleeve of vapour, brightest where the view grazes it
- Column.component eight trays with their weirs, bubble caps, ribs and
skirt brackets; the brass cage of every riser; six hooded wall lamps and eight
pilots per plate; the reboiler and its fire; the condenser head and the seal
It kills the default sky, sets the clear colour to near black, drops the ambient
to a cold violet, adds fog, bloom, an ACES tonemap and a vignette, and bakes the
interior into the reflection environment once — a metal with nothing to reflect
renders black, and this still is all metal.
The annulus between the tray shelf and the wall is left open: it is the channel
the shaft is read through, so a camera near the wall sees the rims of the plates
above receding into the dark.
---
staging: the camera, and the five moments the run is remembered by
The playing shot stands ACROSS the column from the ketyl and solves its own
radius from the axis, so the subject is always the same size, the shaft and the
plate above are always behind it, and the eye never passes through the glass.
Distance and lens come from the live screen: a wide screen holds the same
vertical box and gains margin at the sides, and a screen taller than 3:4 opens
the lens rather than retreating through the wall.
Five cutscenes on core's events: the opening cut to core's own intro clock, the
push onto a lighting riser, the ascent, the seal and the quench. Each cues its
spoken lines by id and never writes the words. Every moment but the opening is
skippable from a key, a pad button and an on-screen button.
Three synthesised camera sounds under the beats.
---
ketyl: the radical as a benzophenone molecule of light — core, rings, corona, trail, discharge and its own hum
---
column: balance the still's value — brass that reads, a riser that is dark until it opens
The closed riser was the brightest fixture in the shaft, which is the signal the
open one is supposed to carry, and the bubble caps were reading as black
silhouettes rather than as brass.
- still_riser_glow a near-black body, so the shut riser is a dark throat and
the violet is entirely the emissive the open state pulses
- still_brass / still_tray more of the light answers as diffuse, so a dome lit
from overhead reads as metal at the shallow angle the gameplay camera holds
- the plate lamp reaches the tray's whole radius, and a second lamp low and off
to one side rakes across it so the perforations and the caps cast their own
length
- the fog sits lighter on the blacks
A 1080x1440 capture standing on plate 1 comes back at luma.spread 93, and 67
from the annulus on plate 4.b1efcd29c3plan: record the ZeroMind survey and the three reference worlds9480aee411plan: THE EIGHTH KETYL — spec, scene skeleton, shared module, input mapsd444b11411plan: THE EIGHTH KETYL — spec, scene skeleton, shared module, input maps