The only grenade in the game is the HE: Grenade in src/client/grenades.ts is declared kind: "he" — a union with one member — and GRENADE is a single object of constants (fuse 1.6 s, blast radius 350). Everything a second grenade needs already works: the arc, the gravity, the bounce off boxes, the fuse that fires exactly once, the buy entry, slot 4, and the throw. What is missing is the one piece of utility a person actually opens a site with. Smoke (#37) is the hard one — it has to take a sightline off the map. A flash is the cheap one: it is a number per player, computed from where they were looking.
Done looks like
[ ] A flashbang in the buy menu (price it like CS: cheap, and say what you chose), in slot 4 beside the HE — the pocket already holds MAX_GRENADES, so say how a person picks which one they are throwing, and keep it to one key.
[ ] grenades.ts grows a second kind rather than a second module: the fuse, the throw and the bounce stay exactly as they are, and only the constants and what happens at detonation differ.
[ ] A pure src/client/flash.ts: given the flash's position, a player's eye position and view direction, and whether anything is between them, it returns how many seconds that player is blind for. Full in the face is the maximum, looking away is a fraction, a wall is nothing. Tested on its own — those three cases plus the boundary where the flash is just outside the view.
[ ] The person's screen goes white and decays over that time; it never goes fully opaque for the whole duration, because a screen you cannot see for five seconds is a bug report. Say what maximum you used.
[ ] A blinded bot is a blinded bot: while it is blind, its aim error grows and its reaction lengthens, so a flash the person throws actually buys them the entry. Write it where a bot already reads its skill, not as a new branch in the shooting code.
[ ] Friendly fire applies — your own flash blinds your own side — because a flash that only blinds enemies is not a skill.
[ ] The sound is the flash's own, played from where it went off, through the panning ears.ts already does.
[ ] Tests: the blindness rule (in flash.test.ts), that a flash detonates once, that a blinded bot shoots worse, and that a round restart leaves nobody blind.
[ ] bun test green; README's Playing names the grenade.
Not in this issue: bots buying or throwing flashes (that is #58's shape, for the HE), smoke (#37), and any change to the HE's numbers.
Files I expect to change: new src/client/flash.ts and flash.test.ts, src/client/grenades.ts, src/client/weapons.ts, src/client/world.ts, src/client/hud.ts, src/client/audio.ts, src/client/bots.ts where skill is read, README.md.
Risks:world.ts is contended — #96, #100, #103 and #105 are all queued against it, so keep the new code in flash.ts and touch world.ts in as few places as you can; the line-of-sight test is a trace per player per flash, which is ten traces once in a while and not a per-tick cost, but say what you measured; and observe.ts's 32 numbers must not change, so the RL policy never learns about a grenade it cannot see.
The only grenade in the game is the HE:
Grenadeinsrc/client/grenades.tsis declaredkind: "he"— a union with one member — andGRENADEis a single object of constants (fuse 1.6 s, blast radius 350). Everything a second grenade needs already works: the arc, the gravity, the bounce off boxes, the fuse that fires exactly once, the buy entry, slot 4, and the throw. What is missing is the one piece of utility a person actually opens a site with. Smoke (#37) is the hard one — it has to take a sightline off the map. A flash is the cheap one: it is a number per player, computed from where they were looking.Done looks like
MAX_GRENADES, so say how a person picks which one they are throwing, and keep it to one key.grenades.tsgrows a secondkindrather than a second module: the fuse, the throw and the bounce stay exactly as they are, and only the constants and what happens at detonation differ.src/client/flash.ts: given the flash's position, a player's eye position and view direction, and whether anything is between them, it returns how many seconds that player is blind for. Full in the face is the maximum, looking away is a fraction, a wall is nothing. Tested on its own — those three cases plus the boundary where the flash is just outside the view.ears.tsalready does.flash.test.ts), that a flash detonates once, that a blinded bot shoots worse, and that a round restart leaves nobody blind.bun testgreen; README's Playing names the grenade.Not in this issue: bots buying or throwing flashes (that is #58's shape, for the HE), smoke (#37), and any change to the HE's numbers.
Files I expect to change: new
src/client/flash.tsandflash.test.ts,src/client/grenades.ts,src/client/weapons.ts,src/client/world.ts,src/client/hud.ts,src/client/audio.ts,src/client/bots.tswhere skill is read,README.md.Risks:
world.tsis contended — #96, #100, #103 and #105 are all queued against it, so keep the new code inflash.tsand touchworld.tsin as few places as you can; the line-of-sight test is a trace per player per flash, which is ten traces once in a while and not a per-tick cost, but say what you measured; andobserve.ts's 32 numbers must not change, so the RL policy never learns about a grenade it cannot see.Brief that fits: vesper.