No new machines. Only new owners.
Real-time-with-pause tactical mech combat. See WRECKRIGHT_DESIGN.md
for the full design and build specification; CLAUDE.md holds the
agent working rules; docs/HOSTING.md covers publishing it.
Play it: published as a Cloudflare static-asset Worker from main, and
playable in Safari on a phone as well as on a desktop. See
docs/HOSTING.md for the build settings and how to deploy
without pushing.
The product, source repository (icarusdlqx/Wreckright), Worker
(wreckright.ligand-ave.workers.dev), diagnostic hook, downloads, and release
tooling use the Wreckright name.
Browser storage and serialized playtest identifiers deliberately retain their
original ironline.* values. They are non-visible compatibility contracts: the
first Wreckright deployment already wrote them, and keeping them stable protects
existing saves and rollback safety.
Authored data ids remain stable because they are save and simulation contracts, not product branding. The earlier project remains independent in its original repository and deployment.
src/sim pure, deterministic simulation (no DOM, Pixi or React)
src/data all game content as JSON
src/schema Zod schemas + the validating content loader
src/render shared art description — blueprints, palettes, silhouettes
src/render3d Three.js tactical renderer — reads sim state, never mutates it
src/ui React shell, Zustand store, fixed-step game loop and input
src/ui/mechbay loadout editor, refit validation, heat calculator
src/campaign economy, salvage, refit, repair, roster, time, save/load
src/headless CLI balance harness
tests architecture tests + the browser playthrough harness
npm install
npm test # Vitest: determinism, schemas, architecture boundaries
npm run lint # ESLint, including the /sim purity rules
npm run typecheck
npm run dev # Vite dev server
# Headless balance harness
npm run sim -- --iterations=100 --seed=1337
npm run sim -- --mission=skirmish_ridge --iterations=500 --seed=1337 --out=./reports/skirmish.json
# Drive the real page in Chromium and assert the Phase 2 acceptance test
npm run verify:uiHarness flags: --mission, --iterations, --seed, --max-ticks, --out, --verbose.
Iteration i runs on seed <seed>:<i>, so any single battle can be replayed on its own.
- Phase 0 — Foundation: complete. Vite + TypeScript strict, ESLint with the
/simimport boundary andMath.randomban, Vitest, seeded xorshift128 RNG with a determinism test over 10,000 draws, Zod schemas for chassis/weapon/ equipment, and three chassis, eight weapons and six equipment items insrc/data. - Phase 1 — Headless simulation core: complete. Terrain grid, A* pathfinding,
locomotion with facing and turn rates, line of sight with obstruction and
elevation, weapon cooldowns, to-hit and hit location, damage with transfer and
location destruction, heat with shutdown, ammo tracking and explosions with
Blowout Cells, and an advance-and-engage placeholder AI.
npm run simruns complete 4v4 battles and prints a results table. - Phase 2 — Tactical renderer: complete. PixiJS tilemap with elevation relief, chassis-silhouette mechs with facing and component-loss damage state, selection, move/run/attack/called-shot orders, beams and tracers and arcing missiles, explosions and smoke, fog of war with remembered ground and last-known-position ghosts, paper-doll damage display, heat bar with threshold markers, weapon groups with cooldown rings, camera pan/zoom, and pause that freezes the sim while still accepting orders.
- Phase 3 — Mechbay: complete. Construction weight tables in
/data/rules, a loadout calculator that enforces tonnage, slots, hardpoint types, armour maxima and heat-sink minimums, drag-to-hardpoint editing with live validation, per-location armour sliders, a heat efficiency calculator verified against headless sim runs, and build save/load/export. All seven shipped designs are legal builds. - Phase 4 — Campaign shell: complete. Node-based operational map with branching prerequisites, contract negotiation trading payout against salvage rights, credit economy with pilot salaries, salvage resolution keyed to how each enemy was taken out, refit from stores, repair queue with day advancement, pilot XP and injuries, and save/load that round-trips exactly including the campaign random stream.
- Phase 5 — Objectives & support: complete. Mission scripting from JSON — capture zones, five objective types, and triggers on elapsed time, zone capture, objective completion or losses, firing spawns, resource awards, messages and reveals. Resource Points earned from zones and objectives pay for sensor probes, air strikes, repair trucks, or an authored mission reserve. Mission success and failure conditions, a briefing screen and an in-battle objective tracker.
- Phase 6 — AI depth & balance: complete. Utility-scoring target selection,
lance focus fire, cover and elevation seeking, flanking, graduated heat
discipline that sheds the least efficient weapon group rather than going dark,
called shots at the legs to leave salvage on the field, withdrawal and
disengagement, and four difficulty tiers that change behaviour and pilot skill
but never hit points or damage. Torso twist so guns bear independently of the
hull. Content pass to twenty-four weapons, ten equipment items and sixteen
chassis spanning 25 to 100 tons.
npm run simreports damage-per-ton-per-heat against each class median. - Setting. WRECKRIGHT is set on Tessell, where the Aurelian Continuance has
returned to repossess every surviving walker root. An independent company
fights through the Great Recall while deciding who owns the finite machines
that kept this world alive. The setting is in
src/data/lore, readable in-game under Field Manual. - Phase 7 — Polish: in progress.
Both criteria are asserted in src/sim/balance.test.ts:
- Weapon balance.
damagePerTonPerHeat = dps / (tonnage + heatPerSecond / dissipationPerSink)— a mount costs its own tonnage plus the heat sinks needed to keep it firing, and accuracy is folded into the numerator so Burst and Seeker launchers pay for their aim. Both heat load and cycle time affect the score. All 24 weapons remain inside the ±20% band around their class median. - AI strength.
mirror_ridgefields identical lances on mirrored spawns; the tactical controller and thebaselinecontroller (nearest target, range bracket, heat discipline — nothing else) swap sides every other run so no corner of the map flatters either. Two hundred deterministic matches feed a one-sided confidence gate, so ordinary seed noise does not decide the build.
Known finding: light mechs are near-unsurvivable in a stand-up 4v4, because
lanceFocus correctly concentrates on the weakest target. That is doctrine
working as intended rather than a balance fault — lights belong on scouting and
flanking work — but it means a line lance should not be built around one.
Skirmishes are outfitted at the briefing: each berth has a design picker (stock builds plus anything saved from the bay), a pilot picker, and a Customise button that opens the bay on that machine. The lance must fit the mission's drop tonnage, and the loadout is remembered per mission.
A campaign contract is fought with what you decide to take. Signing one and pressing Deploy opens the dropship manifest rather than launching:
- The profile — how many berths the dropship has, how many tonnes it will carry, and what the contract is. The lance is limited by weight as well as by berths, so fielding the hundred-tonne hull means leaving something behind.
- The crew — every fit pilot, what their skills buy in the units you see on the field, and which machine they are in. Pilots can be reseated into any hull and held back from a drop.
- The loadout — Refit opens the bay on that machine, stocked from the company's own stores. What you take off goes back on the shelf; what you bolt on comes off it; a refit the company cannot pay for is refused.
Everything there is a trade. A heavier machine costs a berth's worth of allowance, a better gun costs tonnage that was buying armour, and the pilot who sees furthest is not the one who shoots straightest.
| Input | Action |
|---|---|
| Left click / drag | Select a friendly mech; Shift-click toggles it, and Shift-drag adds a box selection |
| Right click | Attack a hostile or move to open ground; hold Shift on ground to append a waypoint |
| 1–9 / Ctrl or Cmd+1–9 | Recall a control group / bind the current selection to one |
| E | Select the whole lance |
| Numbered weapon badge | Toggle that weapon group across the current selection |
| T | Reactor governor (heat safety) on or off |
| Space | Pause / resume — orders are still accepted while paused |
| M / R / A / F / C / J | Move, Run, Attack Move, Attack, Called Shot, Jump |
| H / G | Hold Fire / hold position |
| Q / V / X | Target nearest contact, pilot ability, alpha strike |
| Tab | Cycle through your lance |
| Arrow keys / Centre | Pan or centre the selection · wheel zooms under the pointer · middle-drag pans · minimap click jumps |
| , / . | Lower / raise battle speed |
| P | Toggle the performance graph |
| Esc | Cancel targeting and clear the selection |
Shift also appends destinations placed with Move, Run, or Attack Move. Support calls are picked from the palette and then placed with a left click; an air strike uses a press-drag to set its run-in. Esc cancels an armed call.
On touch, tap a friendly to select it, open ground to move, or a hostile to attack. Drag the ground to pan, pinch around the fingers to zoom, or tap Centre to find the selection. Commands take their next target from a tap. Tap an armed support call again to cancel it; press and drag an air strike across the field to choose its run-in.