Public: anyone can read this; the crew can change it.
forked from trevato/cs
The numbers the game is tuned by are on the page: a weapons table rendered from the table itself #266
Check · Review · Land · Live done — Landed and live in production.
Pushed with the full suite green (1,178 tests).
shipped production is serving it deploy ae07c2d
Merged main and pushed; the full suite is green (1,184 pass, 0 fail).
/ now carries a weapons section under the game: every weapon in WEAPONS — price, damage, armour penetration, rpm, magazine/spare, reload, carry speed, kill reward — and beside it what one shot does to a person: head, chest and leg against a bare body and against kevlar + helmet, the shots each takes to put that body down, and how far one shot to the head still kills from. The Deagle reads all 8,192 u through a helmet, the AK 2,840 u, the M4A4 never; the three thrown weapons get a sentence each computed from their own blast, flash and cloud.
Nothing on it is typed. src/sheet.ts is the data (no markup, no terminal lines), built from the registry's own fields plus two new pure helpers in src/client/combat.ts: shotCost, which fires the shots into wholeBody through the same applyHit a round uses, and killRange, which binary-searches the kill distance against the simulation and caps it at reachOf — a knife's 64 units, now shared with world.ts instead of a literal there. A body's 100 health and 100 armour became FULL_HEALTH/FULL_ARMOR where the world, the shop and the RL arena set them. src/pages/weapons.test.ts renders the section from a weapons table nobody tuned and fails if one of today's figures survives; combat.test.ts pins the arithmetic to hand calculations (36×4 = 144; 30×4×0.75^(325/500) = 99.5, which is exactly a body, and 326 units is not).
The conflict with main was that both sides gave the terminal a tab. The merge keeps both and keeps main's rule about order: standings, matches, policy, today stay where they were, then runs (the range's board), then weapons last, because it is read rather than played — the tab strip, the cycle in keys.ts and the tty's frame-per-press test all say the same six.
Cost, measured on the merged tree: the section is built once at start-up (3.4 ms) and interpolated per request as a constant — gamePage medians 0.48 ms with it against 0.49 ms without, i.e. the difference is under the noise, which is dominated by the leaderboard's SQLite reads. Bytes are not free: / grew 1,879 gzipped (9,947 raw), so server.test.ts's budget for / went 9,000 → 12,000 with the reason written into its comment, and that comment's stale page figures were retaken (/range and /example had moved with the range board). At 360px both tables scroll inside their own focusable box, never the page.
Beyond the issue: the terminal's weapons tab (AGENTS.md asks that the tty do what the page does) and a short README section. Not done: the spray patterns — recoilOffset would draw them, and that is a picture and its own issue — and the range and the example are untouched by this branch.
🤖 Generated with Claude Code
Pushed with the full suite green (1,178 tests).
/now carries a weapons section under the game: every weapon inWEAPONS— price, damage, armour penetration, rpm, magazine/spare, reload, carry speed, kill reward — and beside it what one shot does to a person: head, chest and leg against a bare body and against kevlar + helmet, the shots each takes to put that body down, and how far one shot to the head still kills from. The Deagle reads all 8,192 u through a helmet, the AK 2,840 u, the M4A4 never; the three thrown weapons get a sentence each computed from their own blast, flash and cloud.Nothing on it is typed.
src/sheet.tsis the data (no markup), built from the registry's own fields plus two new pure helpers insrc/client/combat.ts:shotCost, which fires the shots intowholeBodythrough the sameapplyHita round uses, andkillRange, which binary-searches the kill distance against the simulation and caps it atreachOf— a knife's 64 units, now shared withworld.tsinstead of a literal there. A body's 100 health and 100 armour becameFULL_HEALTH/FULL_ARMORwhere the world, the shop and the RL arena set them.src/pages/weapons.test.tsrenders the section from a weapons table nobody tuned and fails if a single one of today's figures survives;combat.test.tspins the arithmetic to hand calculations (36×4 = 144; 30×4×0.75^(325/500) = 99.5, which is exactly a body, and 326 units is not).Cost, measured on this tree: the section is built once at start-up (3.4 ms, mostly
toLocaleString) and interpolated per request as a constant —gamePagemedians 0.48 ms with it and 0.49 ms without, i.e. the difference is under the noise of the measurement, which is dominated by the leaderboard's SQLite reads. Bytes are not free:/grew 1,879 gzipped (9,947 raw) to 10,032 / 34,300, soserver.test.ts's budget for/went 9,000 → 12,000 with the measurement and the reason written into its comment. At 360px both tables scroll inside their own focusable box, never the page.Beyond the issue: the terminal grew a weapons tab rendering the same sheet as columns (AGENTS.md asks that the tty do what the page does), and the README gained a short section. What I did not do: the spray patterns —
recoilOffsetwould draw them, and that is a picture and its own issue — and the range and the example are untouched.🤖 Generated with Claude Code
Closes #199