ONE FILE, NO BUILD STEP, AND A GREAT MANY THINGS THROWN AWAY

Making-of

This page is about how the thing was built rather than about what happens in it, so it is open from top to bottom. The one place care was needed is the version history, whose later rows in the original build log do spoil the endings; those rows are summarised here rather than transcribed.

ONE FILE

The whole game is a single HTML document of about a hundred and eighty kilobytes. That file holds the geometry, the story state machine, the cutscene engine, the audio synthesis, the input handling for both mouse and touch, the save system and the interface. There is no bundler, no framework, no build step and no server-side runtime, and there is none of that because there is none of it available on the box the site runs on.

Two things stream in from elsewhere. three.js version 0.180.0 arrives from a CDN through an import map, along with three post-processing modules, and twenty-eight character and prop assets arrive from a Polyfork content token. The loading bar you see at the start is those twenty-eight assets, and the caption underneath it names each one as it lands, which is the least decorated loading screen it was possible to write.

Deploying is an rsync. Markdown is excluded from the transfer by design, which is why the design documents have never reached the public web and never will, and which is why this wiki is hand-written HTML rather than a rendered markdown folder. A markdown wiki would simply not deploy.

THE RENDERER, AND ONE FLAG THAT MADE THE TRAILER POSSIBLE

The renderer runs with antialiasing, soft shadow maps, filmic tone mapping at an exposure of 1.12, a bloom pass at half resolution, and a pixel ratio clamped to 1.35 so that a retina display does not quietly quadruple the cost of every frame.

It also runs with the drawing buffer preserved, and that one flag is responsible for the trailer and for every photograph on this wiki that has not been taken yet. Because the frame survives the buffer swap, the canvas can be read straight out of the browser console as an image, with no screenshot tool and no cropping.

copy(document.querySelector('canvas').toDataURL('image/jpeg', 0.92));

The advantage that actually matters is what such a grab does not contain. Every piece of this game’s interface is a DOM overlay sitting above the canvas: the title, the objective line, the subtitle, the prompt, the cutter charge, the interlock pips, the sending bar, the air marks, the act cards, the end cards and the red lean vignette. A canvas grab comes back with none of them, which is exactly what a location plate wants and is how the trailer’s seven silent plates were captured. The consequence for anybody illustrating this wiki is the rule that governs its shot list: anything that includes the interface has to be an ordinary screenshot instead.

THE CORRIDOR REBUILD

This is the best engineering story in the project and it is a story about admitting a sunk cost.

The ship’s corridors were originally assembled from a kit: prefabricated corridor sections, corners, T-junctions and airlock end caps, tiled together. Over roughly a dozen fixes across several versions, that kit produced, in order: sills sixty-two centimetres high across every doorway; mouths panelled shut from the factory, so that the corridor dead-ended visually in all four directions at the junction while collision let you walk straight through; floor plates at four different heights depending on which piece you were standing on; interior heights that disagreed by seventy-seven centimetres between a section and a junction, so their roofs never met; ceilings modelled with their normals facing outward, which renders as nothing at all from inside; and six separate holes to open space at the joins, because the pieces do not butt flush.

Each of those was fixed individually. The corridors were still wrong. So they were thrown away and rebuilt from primitives: an exact two point six metre square section, floor at one centimetre, and openings placed where the collision rectangles already said there were openings, which is the correct way round. Then dressed for the part with structural ribs every three metres, recessed wall panelling, conduit runs under the roof, framed jambs around each doorway, ceiling light panels on their own fixtures, and a lit guide line down the floor, all of it sharing the ship’s power-aware material so that the corridor dies properly when the lights go.

The audit after the rebuild reported zero wall gaps, zero roof gaps, two hundred and twenty-nine floor samples all at the correct height, and one thousand and twenty-seven frames walked with no eye-clipping worse than seven centimetres.

Deleted along with the kit pieces: a sampled height field, a per-frame floor ray, a lateral bevel clamp and every seam collar. None of that machinery had ever been solving a problem the game had. All of it had been solving problems the kit had.

CANTOR’S VISOR, WHICH IS THREE MECHANISMS IN A TRENCH COAT

The visor carries the entire ally system, so it has to be unambiguous from any distance and in any light. The asset it is built on was not designed with that in mind, and getting it to obey took three separate techniques stacked on top of each other.

  1. Material surgery. The model is walked at load time and every material whose colour leans teal, meaning its green and blue channels both exceed its red by a healthy margin, is cloned and given a controlled teal emissive. Cloning matters, because the asset shares materials between meshes and editing one in place would have coloured things that are not the visor.
  2. Vertex-colour surgery. Some of the visor is not a material at all, it is baked into the geometry’s own colour attribute. So the geometry is walked as well, every vertex whose colour falls in the visor range is recorded along with its original value, and the whole set is rewritten in one pass whenever the state changes and restored exactly when it changes back. The knobs the asset is created with pass magenta into the visor and brow slots as a marker colour, purely so that the load-time pass can find them reliably.
  3. An override plate. On top of all that, a small purpose-built box of the game’s own geometry sits over his sensor pane, with a point light behind it. It obeys nothing but the game’s own rules, and it is what guarantees the colour reads at fifteen metres down a corridor.

The result is worth the trouble, because the visor is not decoration. It is the only piece of information in the game that a player has to learn to read, and a signal that was ambiguous in a dark corridor would have taken the whole ally system down with it.

THE VOICE PIPELINE

Every line the game can speak has a generated take, produced with ElevenLabs through a batch script rather than one at a time. The casting is on the soundtrack page, along with the one genuinely clever thing the pipeline does, which is a piece of characterisation achieved entirely in the generation parameters rather than in the script. That one sits behind a shutter over there, because describing what it does gives away what it is for.

Takes are keyed by the text they speak. That has one enormous benefit and one sharp edge. The benefit is that a line and its voice can never drift apart silently, because editing the subtitle changes the key. The edge is that the manifest is fetched by a bare filename, and browsers cache bare filenames: a returning player who already had the old manifest was being served it, so seventeen newly voiced lines stayed silent for anyone who had opened the game before, and nothing anywhere reported a problem. The manifest is now fetched with the build number appended, which is also why the build constant is used for two things rather than one.

The other voice bug worth recording is that every spoken line in the game was being cut off for a while. The durations passed to the subtitle system were written for reading speed, before there were any voices, and the takes all run longer than a reader does. The opening line of the game runs nine and a half seconds against an allowance of five, so it was being guillotined at its halfway point. The playback now reports the take’s real length back, the subtitle holds until the speaking has finished, and a cutscene shot holds its camera until the line it started has been spoken.

THE DEBUG HOOKS

The game exposes a set of functions on the window object, which are how the trailer was shot and how everything on this wiki will eventually be photographed. They are listed here because they are also the fastest way for a curious player to look at a part of the game they have already finished.

HOOKWHAT IT DOES
__act(a)Reads or sets the current act, and saves.
__story()Dumps the act, the flags and whether the game is busy.
__save() / __wipe()Write or clear the save.
__walkRefThe walk state. Set its position, yaw and pitch to stand anywhere and face any way.
__storyRefThe story object, for setting flags directly. Seating interlocks from here is how the three ring frames get shot.
__orbitRef / __sceneThe orbit camera, and the whole three.js scene.
__power('out' | 'on')Kills or restores every practical light aboard, over about a second.
__cantor('red')Forces an eight second red episode.
__cantorObjHis group. Worth inspecting, not worth moving: his position is driven every frame by state that is not exposed.
__suits() / __suitState()Where every crew member is, and what each of them is currently doing.
__openAll() / __giveKey()Open all three sealed panels, or put an interlock in your hands.
__crossing() / __reactor() / __lie()Play the Act I, Act II and Act III cutscenes.
__sendNow() / __finish()Start Act IV at the platform, or end the reading immediately.
__pod()Play the escape pod sequence.
__playCine() / __card()The drive bay reveal, and an act card.
__sending()Whether it is active, which stanza, how many marks are gone and how many seconds are left.
__beam() / __navTarget()The cutter beam’s state, and where the arrow is currently pointing.
__WALLS / __walkAt(x, z)The collision rectangles, and whether a given point is standable.
__voCtx()The dialogue audio context, for diagnosing a silent take.

Two URL parameters matter as well. ?ship=abcde selects which districts are built, so ?ship=a gives a bare spine with the command centre and nothing else, which is the cleanest corridor plate available. ?touch forces the touch interface onto a desktop.

THINGS THAT WERE MEASURED RATHER THAN EYEBALLED

A recurring habit in this project is to turn a judgement about how something looks into a number, and then fix the number. Three examples.

THE CORRIDOR WAS BLOWING OUT

Rather than deciding by eye that the corridor looked too bright, the framebuffer was sampled. Facing a corridor wall, twenty-three per cent of the frame was clipped to flat white, and with the ship’s power out it was fifty-eight per cent. The cause was the helmet lamp, which has to be bright enough to be useful down a dark spine and is therefore far too bright against a bulkhead a metre from your eye. The lamp now dims according to how much room its beam actually has, probed against the same wall rectangles the body collides with, which costs a handful of comparisons rather than a raycast. Clipping is now zero in both the lit ship and the dark one, while a dark corridor still reads at 0.36 mean luminance and the open deck stays properly black at 0.085.

THE PATROL ROUTES WERE INSIDE THE WALLS

The crew walk their routes without consulting the collision system, so a waypoint inside a building means somebody strolling through a wall. Measured against the collision rectangles, the old reactor round spent seventy-five per cent of its length inside solid geometry, the hangar apron sixty-seven per cent and the habitat round sixty. All four were re-laid by sampling free deck and checking every segment at twenty centimetre intervals with a seventy centimetre body clearance. All of them are now at zero.

THE SENDING COULD NOT BE LOST

A reviewer sat on the platform, issued no input at all for ninety-five seconds, and was given the true ending. Nothing in the loop could end badly: the air regenerated, a broken line cost four seconds against a nine second stanza, and a missed crossing merely restarted it. Standing still was not a losing strategy, it was a stalemate that eventually resolved in the player’s favour. The current encounter was designed against a simulation of the crew’s convergence: a player who never clears the ring stalls at five stanzas of eight when the deadline expires, and a player who cuts finishes at about seventy seconds untouched.

VERSION HISTORY

Summarised from the build log. The rows are the project’s own numbering, and the shipped build stamps itself with a separate scene version which is what the badge in the corner of the game shows.

VERSIONWHAT SHIPPED
v0.1The drive bay, built first, as a standing scene: the spiked core, the three counter-rotating rings, the dais, the bridge and a starfield, with an orbit camera and a spin-up demo.
v0.15The ship around the bay. A spine corridor the length of the hull with districts hung off it, the docking ring, and hull views onto the starfield.
v0.2Walk mode. F to board, walk and run, pointer-lock look with a keyboard fallback, and a walkable deck.
v0.3The light model, and the design rule that came out of it: the ship is lit. Bloom, strip lighting, fake volumetric cones, and the contrast between cold utility light and the wrong red. Then the helmet lamp and the ship power states.
v0.4The Returned. Suits on waypoint rounds through the districts, pausing to tend stations, stopping to look at you inside four and a half metres.
v0.5CANTOR. Follows you on deck, idles by the corridor mouth otherwise, and floods red on his own timer.
v0.55Deck systems: hull collision, the airlock door, and the interaction layer with proximity prompts, the subtitle queue and the objective line.
v0.56The salvage cutter. The asset catalogue contains no handheld tool of any kind, so it is built from primitives, and it staggers without ever killing.
v0.57The story engine: procedural audio with no files at all, the cutscene camera-rail system, save and checkpoints, and the act cards.
v0.6 to v0.9The four acts, built in the order I, III, II, IV. Act II was slotted in after Act III deliberately, so that the reactor reveal was written knowing what Act III would need from it.
v1.0The voice pass. Every spoken line generated, keyed by its own text, played alongside its subtitle.
v1.1The trailer and the listing card.
v1.2The deep polish pass: the prose sweep into house style, the three score cues, the mobile and touch pass, a performance pass that took the worst case from thirty-five to fifty frames a second, and a break test that found a genuine cutscene-reload softlock.
v1.3Six holes to open space, all at corridor joins, each bridged with a collar. Plus the nav arrow, ported from the sibling game.
v1.4Six fixes found by playing rather than reading, including the crossing, which until then had been scored with an eight hundred and eighty hertz square wave and sounded like chiptune.
v1.5Dialogue timing, the title stepping aside while you play, and held keys releasing when the window loses focus.
v1.6Exposure, measured from the framebuffer rather than judged by eye.
v1.7The worst bug in the project. The spine’s side walls ran unbroken past the T-junction, so the entire east and west halves of the ship were unreachable on foot and Act II sent you into an invisible wall. It survived an earlier playthrough because every leg of that playthrough was teleported, and teleporting ignores collision. Walk the routes.
v1.8The kit’s junctions and corners ship with their mouths closed. Also: seventeen spoken lines had no take at all, including every one of Osei’s Act II comms lines, which is why he went silent after the crossing.
v1.9Seeing through walls and floors, from two separate causes with one symptom. The worse of the two was that the ground height functions still described a pit and a ramp that had been paved over, so everybody was walking up to two and a half metres below the floor they could see.
v2.0The corridor rebuild described above.
SinceAct II given its three teaching beats, the three interlock sites rebuilt as interiors you walk into, the sending made losable, and the third end card added.
WHERE THE DOCUMENTS ARE BEHIND THE BUILD The project’s readme and its polish notes both state the shipped version as v0.18.0 and the line count as fifty-two. The build constant in the game reads 0.32.0, and there are seventy-nine takes in the voice folder and seventy-nine entries in the manifest. This wiki takes its numbers from the build and from the log, never from the readme.

WHAT THIS WIKI DELIBERATELY DOES NOT HAVE

There is no bestiary, because the game’s own writing rules forbid sorting the Returned into monsters and a bestiary is a page that does exactly that. They are on the crew page instead, as colleagues.

There is no separate world and lore page, because this game’s lore does not distribute the way its sibling’s did. The rule of the ship is one paragraph and belongs on the front page. Everything else that would fill a lore page is either the ship or the drive, and both of those have pages already.

There is no interactive deck map, and there is no JavaScript anywhere on this site. The spoiler shutters are native details elements, which means they work with scripting disabled, survive a browser’s find-in-page, and are keyboard accessible without anybody having to arrange it.