Public: anyone can read this; the crew can change it.
forked from trevato/cs
Radio: three calls a person makes, and four teammates who go #386
Check · Review · Land · Live done — Landed and live in production.
You can now make three radio calls to your own side: **go A** (<kbd>Z</kbd>), **go B** (<kbd>Q</kbd>) and **hold** (<kbd>H</kbd>). A call overrides the round's plan for your side for 20 seconds, then the bots go back to the rolled plan on their own. `bun run test` passes (typecheck and 1579 tests), and the app boots and serves `/` with the new buttons.
shipped production is serving it deploy ae07c2d
Sign in to join this conversation.
new above
offline
You can now make three radio calls to your own side: go A (<kbd>Z</kbd>), go B (<kbd>Q</kbd>) and hold (<kbd>H</kbd>). A call overrides the round's plan for your side for 20 seconds, then the bots go back to the rolled plan on their own.
bun run testpasses (typecheck and 1579 tests), and the app boots and serves/with the new buttons.src/plan/call.ts, which sits besideplan.ts.liveCallfinds the call standing for a side in the current round and ignores it once 20 seconds have passed.steerturns a site call into everyone on that site at once, at a rush.heedthen does what a plan can't express on its own:- A site call also pulls in the lurker that a stack or fake would send to the other site, so all four teammates go. - A hold stretches every bot's existing wait to the end of the call. The bomb carrier still moves, because the bomb never waits.
jobOfinsrc/client/bots.tsnow re-cuts a side's jobs when the plan or the live call changes. When a call expires it counts as a change, so the jobs are cut from the plan again. With no call, the check isnull === null, so behaviour is unchanged and every existing replay digest is still the same.src/client/radio.tsrefuses a call from a dead player or between rounds. Otherwise it stores the call onworld.radio, putsRadio — <name>: go Aon the HUD's message line, and adds aradiosound.hearslets only the caller's side hear that sound, andaudio.tsplays it as an unplaced static-and-blip.CS_KEYS, the three actions are inCS_TAP, and they are on the phone's left pad (crouch, jump, use, go A, go B, hold).main.tshandles them inonAction. It plays your own call's sound straight away, because the call happens at the exact time the last frame already played sounds up to, so the normal per-frame sound pass would skip it.CALL_SCRIPTmakes a CT player say "go B" one second into the live round of the seeded de_forge round. It is played under the local plan and pinned asCALL_ROUND(36 seconds, so the run includes the expiry). A second test shows the same run without the call matches it second for second until the call.Not done:
radiois added at the end of the protocol's list of sound names rather than in alphabetical order, so no existing sound's number changes.Tests changed because behaviour was added, not because they were wrong: the
CS_TAPexpectation inbinding.test.tsnow includes the three calls. The audio test's list of sounds leaves outradio, which gets its own test, because the shared test expects every sound to get quieter with distance and the radio doesn't.To try it: start a match, press <kbd>Z</kbd> during the freeze or the live round and watch the message line and your side on the minimap. Press <kbd>H</kbd> and your side stops moving. On a phone, use the left pad.
🤖 Generated with Claude Code
Closes #290