export type MapXZ = readonly [number, number]; export type MapLayerTone = "danger" | "warning" | "info" | "safe" | "neutral"; export interface MapRoute { id: string; /** World-XZ polyline. */ points: readonly MapXZ[]; tone?: MapLayerTone; /** Dashed rendering — a planned/forecast route rather than a live one. */ forecast?: boolean; /** Line width in map pixels; default `2`. */ width?: number; /** Close the polyline back to its first point (patrol loops). */ closed?: boolean; } export type MapZoneShape = { kind: "circle"; center: MapXZ; radius: number; } | { kind: "rect"; center: MapXZ; w: number; d: number; rotate?: number; } | { kind: "polygon"; points: readonly MapXZ[]; }; export interface MapZone { id: string; shape: MapZoneShape; tone?: MapLayerTone; /** Fill opacity in `[0, 1]`; default `0.25`. */ opacity?: number; /** Dashed outline + no fill — the previewed future state (storm's next ring, incoming hazard band). */ forecast?: boolean; label?: string; } export interface MapCellStates { id: string; /** World-space center of cell (0, 0). */ origin: MapXZ; cellSize: number; /** Sparse cell statuses — pair with `world/cellStates`' `cellsIn`/`counts` output. */ cells: readonly { col: number; row: number; tone: MapLayerTone; opacity?: number; }[]; } /** * Renderer-free overlay data for map surfaces (#285.1-2): zones with live + forecast states, * route polylines, and per-cell status heatmaps. `@jgengine/react/map`'s `Minimap`/`WorldMap` * take these straight in; `pointInMapZone` answers gameplay queries against the same data, * so the HUD and the rules can never disagree about where the storm is. */ export declare function pointInMapZone(zone: MapZoneShape, x: number, z: number): boolean; export declare const MAP_LAYER_TONE_COLORS: Record; export declare function mapLayerColor(tone: MapLayerTone | undefined): string;