/** * The page. The first paint is the match as it stands right now — score, * round, phase, scoreboard — server-rendered HTML, so somebody arriving with * a cold cache or no JavaScript still sees a live match. The client script * then takes the same state over a socket and draws it. */ import { AGENTS } from "../abilities.ts"; import type { Result } from "../db.ts"; import type { MatchState } from "../state.ts"; import { WEAPONS, weaponIds } from "../weapons.ts"; export const escape = (s: string): string => s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c] ?? c); const phaseWord = (state: MatchState): string => state.phase === "buy" ? "buy phase" : state.phase === "live" ? state.spike.planted ? `spike down · ${Math.ceil(state.spike.fuse)}s` : "live" : state.phase === "end" ? "round over" : "match over"; export function gamePage(opts: { state: MatchState; script: string; name: string; env: string; commit: string; ssh: string | undefined; results: Result[]; }): string { const { state } = opts; const board = [...state.players].sort((a, b) => b.kills - a.kills); const row = (side: "atk" | "def"): string => board .filter((p) => p.side === side) .map( (p) => `
The round. Attackers carry the spike to site A or B and plant it; defenders stop them, or defuse it once it is down. Plant and it runs a 45s fuse. First team to 13 rounds wins, and the sides swap at 12.
The teams. You are red or blue; each round one team attacks and the other defends. Team mates carry a name tag over their head, enemies never do.
Controls. WASD move · click the view to capture the mouse and look, Esc releases · click to fire · R reload · hold F to plant, defuse or pick up · Tab holds the big map open · V swaps to the top-down view · B opens the buy · H brings this card back.
Abilities. C and Q are bought in the buy phase and last the round, E is free and comes back on a cooldown, and X is the ultimate, paid for in ult points you earn by playing.
On a phone the view stays top-down: the left thumb walks, the right thumb aims and fires, and the buttons under the map buy and cast.
| player | agent | k | d |
|---|
| player | agent | k | d |
|---|