/** * The shape of a match. Types only, so the ability module and the match loop * can both speak about a player without importing each other. */ import type { Track } from "./aim.ts"; import type { Point, Site } from "./map.ts"; import type { WeaponId } from "./weapons.ts"; export type Side = "atk" | "def"; export type Slot = "c" | "q" | "e" | "x"; export type Team = "red" | "blue"; export type Phase = "buy" | "live" | "end" | "over"; export type ZoneKind = "smoke" | "molly" | "wall" | "trip" | "dart" | "flash" | "heal"; /** Anything an ability leaves on the map, with a clock on it. */ export type Zone = { id: number; kind: ZoneKind; owner: string; side: Side; x: number; y: number; r: number; /** Seconds of life left. */ life: number; /** Seconds before it goes off (a flash in the air, a trip arming). */ fuse: number; /** Seconds to the next damage tick or recon pulse. */ beat: number; pulses: number; damage: number; /** Blocks line of sight (smoke, wall). */ blocks: boolean; /** Blocks movement (wall). */ solid: boolean; }; export type Input = { mx: number; my: number; angle: number; fire: boolean; /** Plant, defuse, pick the spike up: one key for all of it. */ use: boolean; reload: boolean; cast: Slot | null; }; export const emptyInput = (): Input => ({ mx: 0, my: 0, angle: 0, fire: false, use: false, reload: false, cast: null, }); export type Player = { id: string; name: string; bot: boolean; agent: string; team: Team; side: Side; x: number; y: number; angle: number; hp: number; armour: number; alive: boolean; credits: number; weapon: WeaponId; /** Kept through a round they survived, reset to the Classic when they die. */ ammo: number; reloadIn: number; fireIn: number; /** Basic charges bought this round, and signature/ult readiness. */ charges: Record; cooldown: Record; ult: number; blind: number; slow: number; haste: number; /** Seconds this player stays visible to the other team however dark it is. */ revealed: number; spike: boolean; planting: number; defusing: number; kills: number; deaths: number; assists: number; damageDone: number; input: Input; /** Bot scratch space: where it is walking and when it last thought. */ goal: Point | null; think: number; /** Bot scratch space: the target it is holding, and how badly. */ aim: Track; /** Bot scratch space: the match clock when it last threw a flash. */ flashedAt: number; spray: number; joinedAt: number; }; export type MatchState = { id: string; phase: Phase; /** Seconds left in the phase. */ clock: number; round: number; score: Record; /** Which team attacks this round. */ attackers: Team; lossStreak: Record; players: Player[]; zones: Zone[]; nextZone: number; spike: { carried: string | null; x: number; y: number; planted: boolean; fuse: number; site: Site | null; defuse: number; checkpoint: number }; orbs: { x: number; y: number; taken: boolean }[]; shots: { x1: number; y1: number; x2: number; y2: number; hit: boolean; age: number }[]; events: { text: string; age: number }[]; result: string | null; seed: number; now: number; };