/** * LANE-UI — the house voice. * * Register: OSHA-poster deadpan (lore §8). Everything horrifying is labelled like * routine industrial equipment. Nothing here apologises, explains itself, or uses an * exclamation mark. The player is an employee who has already read the placard. * * All copy in the UI comes from this file so the tone stays in one place. */ import type { SimEvent } from '../contracts'; /** * Flavor lines for the inspector, keyed by MachineDef.id. * * TEMPORARY: hand-transcribed from docs/FKTRY_LORE.md §4 by LANE-UI. These belong in * data/machines.json as a `flavor` field owned by LANE-DATA — CONTRACT REQUEST filed in * NOTES. Unknown ids fall back to `GENERIC_FLAVOR`, so new machines never crash the * panel, they just sound like a filing cabinet until the codex line lands. */ const MACHINE_FLAVOR: Record = { 'seam-extractor': 'Chews the payload seam and spits raw ore. Do not place hands in the seam. ' + 'The seam has no policy regarding hands.', belt: 'Moves things. Moving things is the entire job. Back-pressure is a normal ' + 'operating condition and is not a grievance.', demuxer: 'Cleaves raw ore into luma and chroma. One intake, four chutes, no apologies. ' + 'Contents were never yours.', quantizer: 'Rounds coefficients to zero. The dial goes to CRIME. Material leaking from the ' + 'seams is HF DUST and is not glitter. Do not lick the machine.', 'mosh-reactor': 'A decoder sealed in a vessel and starved of anchors until it hallucinates. ' + 'The hallucination is the product. Certified vessel. Uncertified hallucination.', 'decode-asic': 'Handles standard profiles only. Cool, efficient, incurious. Generates bandwidth ' + 'by declining to be interesting.', shipper: 'Composites shipped freight onto THE SCREEN. All deliveries final. ' + 'All sins permanent. Congratulations.', }; const GENERIC_FLAVOR = 'Industrial equipment. Operates within tolerances. Tolerances not disclosed.'; export function machineFlavor(defId: string): string { return MACHINE_FLAVOR[defId] ?? GENERIC_FLAVOR; } /** Toast copy for events the player should notice without reading a manual. */ export function eventToast(ev: SimEvent, machineName: (id: number) => string): string | null { switch (ev.kind) { case 'jammed': return `${machineName(ev.entity)} HAS STOPPED. ${ev.reason.toUpperCase()}.`; case 'brownout': return ev.on ? 'BUFFER UNDERRUN. THIS SECTOR IS NOW A STILL LIFE.' : 'BUFFER RESTORED. RESUME SINNING.'; case 'commissionDone': return 'FAX SENT. THE COLLECTOR DOES NOT SAY THANK YOU.'; default: return null; // shipped/crafted/placed/removed are too frequent to toast } } export const COPY = { bandwidth: 'BANDWIDTH', brownout: 'BROWNOUT', shipped: 'SHIPPED', paused: 'HALTED', running: 'RUNNING', tick: 'TICK', buildBarTitle: 'REQUISITION', inspectorEmptyRecipe: 'NO PROCESS ASSIGNED. UNIT IS BEING PAID TO EXIST.', inspectorInput: 'INTAKE', inspectorOutput: 'OUTPUT', inspectorProgress: 'PROCESS', inspectorJamPrefix: 'FAULT: ', inspectorClose: 'X', faxHeader: 'INCOMING FAX', faxSubheader: 'GLITCH ACQUISITIONS — UNSOLICITED', faxNoCommission: 'NO ACTIVE COMMISSION. THE FAX MACHINE IS RESTING.', faxStamp: 'FAX SENT', /** Shown on the build bar when the player has something selected. */ placingHint: 'LMB PLACE · R ROTATE · ESC CANCEL', idleHint: '1-9 SELECT · SPACE HALT · TAB MANIFEST', /** Inspector fallback when no entity is under the cursor. */ manifestEmpty: 'NO UNITS ON RECORD. THE FLOOR IS AUDITED AND EMPTY.', } as const; /** Direction names for the rotation readout. Dir 0..3 = N,E,S,W clockwise. */ export const DIR_NAME = ['N', 'E', 'S', 'W'] as const;