/** * This game's map from above: the engine's board (`engine/topdown.js`) with * the Valorant things on it — site letters, spawn tints, the orbs, the ability * zones, the spike and its defuse bar, an agent's colour round a dot, the * spike on the carrier and a blinded player's white eye. */ import { disc, drawTopdown as drawBoard } from "./engine/topdown.js"; import { AGENT_COLOUR } from "./scene.js"; const TILE_COLOUR = { "#": "#20242d", A: "#2c2a22", B: "#2c2a22", a: "#2a2024", d: "#1e2630", ".": "#171a21", }; const tile = (cell) => TILE_COLOUR[cell] ?? "#171a21"; const label = (cell) => cell === "A" || cell === "B"; const trim = (p) => AGENT_COLOUR[p.agent] || "#888"; /** Orbs, then every zone but smoke, then the spike: what lies under the bodies. */ function under(ctx, snap, s) { for (const orb of snap.orbs) { ctx.fillStyle = "#c9a0ff"; ctx.beginPath(); ctx.arc(orb.x * s, orb.y * s, Math.max(2, 9 * s), 0, 7); ctx.fill(); } for (const zone of snap.zones) if (zone.k !== "smoke") drawZone(ctx, zone, s); if (snap.spike.x !== null) { const x = snap.spike.x * s; const y = snap.spike.y * s; const r = Math.max(2.5, 7 * s); ctx.fillStyle = snap.spike.planted ? (Math.floor(Date.now() / 250) % 2 ? "#ff5b4a" : "#8a2a22") : "#c8b45c"; ctx.fillRect(x - r, y - r, r * 2, r * 2); if (snap.spike.planted && snap.spike.defuse > 0) { ctx.fillStyle = "#4fd6a0"; ctx.fillRect(x - 20 * s, y + 12 * s, 40 * s * (snap.spike.defuse / 7), 3); } } } /** Smoke last: on this view it hides what is under it, as it should. */ function over(ctx, snap, s) { for (const zone of snap.zones) if (zone.k === "smoke" && zone.f <= 0) drawZone(ctx, zone, s); } /** The spike on a carrier's back, and the white eye of somebody blinded. */ function badges(ctx, p, x, y, r) { if (p.spike) { ctx.fillStyle = "#f0d060"; ctx.fillRect(x - r * 0.4, y - r * 1.8, r * 0.8, r * 0.8); } if (p.blind) { ctx.fillStyle = "rgba(255,255,255,0.8)"; disc(ctx, x, y - r * 1.6, r * 0.35, true); } } export function drawTopdown(ctx, map, snap, look, box, opts = {}) { drawBoard(ctx, map, snap, look, box, { ...opts, tile, label, under, over, trim, badges }); } function drawZone(ctx, z, s) { const x = z.x * s; const y = z.y * s; const r = z.r * s; ctx.lineWidth = Math.max(1, s); if (z.k === "smoke") { ctx.fillStyle = "rgba(190,195,205,0.72)"; disc(ctx, x, y, r, true); } else if (z.k === "molly") { ctx.fillStyle = "rgba(230,110,50,0.45)"; ctx.strokeStyle = "#f08a4b"; disc(ctx, x, y, r, true, true); } else if (z.k === "wall") { ctx.fillStyle = "rgba(120,200,255,0.55)"; disc(ctx, x, y, r, true); } else if (z.k === "flash") { ctx.fillStyle = z.f > 0 ? "#ffe9a8" : "rgba(255,255,255,0.9)"; disc(ctx, x, y, z.f > 0 ? 5 * s : 30 * s, true); } else if (z.k === "dart") { ctx.strokeStyle = "rgba(90,220,170,0.7)"; disc(ctx, x, y, r, false, true); } else if (z.k === "trip") { ctx.strokeStyle = "rgba(230,200,90,0.8)"; disc(ctx, x, y, r, false, true); } else if (z.k === "heal") { ctx.fillStyle = "rgba(120,230,140,0.5)"; disc(ctx, x, y, 14 * s, true); } }