SI spawn placement visualizer
Matches the 2026-08 workspace (inf_nav_team_nearest 1): the extension runs one multi-source reverse Dijkstra, recording for every Nav area "the path distance to the nearest available survivor + its owner". The plugin searches ten fixed distance layers from near to far, consuming each layer front-to-back by Flow. Gray walls are unwalkable, making it obvious that path distance ≠ straight-line distance. Survivors can be dragged directly; the distance field is then recomputed for the current state.
2D mode: left-drag grabs a survivor directly, dragging empty space pans the view, the wheel zooms around the cursor, and double-click resets the view; select "Draw wall / Erase wall" and hold-drag to paint (built-in grid only).
3D mode: left-drag rotates (smoothed), right-drag or Shift+left-drag pans, the wheel zooms toward the cursor, and double-click resets the camera; place survivors back in 2D, hovering still highlights them.
Graph mode 2D: dragging a survivor snaps to the nearest Nav area center, dragging empty space pans; "Block areas" clicks/sweeps toggle dynamic blocking (simulating elevators/doors/nav_block), and blocked areas are removed from the distance field and candidates.
Graph-mode visibility: once geometry data is loaded, real raycasts are performed against the BSP triangles (all world+disp triangles occlude, including floors/ceilings; invisible walls do not block sight; only pairs within 1800u straight-line distance are tested). Without geometry it falls back to the heuristic (straight-line ≤1500, |Δz| ≤120, detour ratio ≤1.6). Exported data only contains ground connections (no ladder edges). Real map data is exported on the server with the sm_navgraph_export command, then loaded via "Import map JSON".
Third-party maps need no server: drop a .vpk / .zip / bare .bsp+.nav onto the canvas, or click "Parse local map". Parsing stays in the browser and nothing is uploaded; .7z/.rar are not supported (unzip to a vpk first). The result is the map-file preset set: no Anne stripper blockers, no Director round items, and flow is a self-computed approximation. For official maps or runtime truth, keep using the dropdown / "Import map JSON" with an sm_navgraph_export dump.
Survivor states (click to toggle, drag to move)
Current search state
Scene saves (browser local)
Search log (matching the [FIND]/[SpawnPerf] wording)
The full pipeline of one normal spawn attempt (team-nearest branch)
How this page maps to the real implementation / simplifications
| Real implementation | This demo |
|---|---|
| AnneSpawn_NavCandidatesPrepareTeam / CollectTeam (multi-source Dijkstra; owner = the survivor providing the shortest path, ties go to the lower index) | 8-direction grid Dijkstra recording dist+owner per cell, ties to the lower index; 1 cell = 50u |
| TEAM_NAV_LAYER_EDGES 10 layers ∩ class [classMin, min(finalMax, inf_SpawnDistanceMax×2)], half-open bands with a closed final band | Identical (clipped to the selected class, empty bands skipped) |
| flowOrder within a band: descending Flow (front first); team mode does no tercile interleaving and no shuffling | Identical (Flow = horizontal progress) |
| Exclusion within a straight-line max(250, inf_SpawnDistanceMin) of any survivor; visibility trace; stuck check; path re-validation | Exclusion ring + grid line of sight (Bresenham wall test); stuck and path re-validation omitted |
| inf_score_behind_reject_gap 8 / _hjc 4; with owner progress ≥90 it only penalizes without hard rejecting | Identical |
| SpawnScore_BuildCandidate multi-factor scoring + best pick from a 12-candidate budget | Front bonus − behind gradient − distance deviation − kernel density; hard-reject within 100u; best of a 12-candidate budget |
| SI_Target_limit: limit = (SI cap / mobile survivors) + 1, leader ×2 (spawn-capacity accounting only) | Identical; each spawn adds 1 to the owner count, and at the limit the member leaves the participant set and the distance field is rebuilt |
| Bands exhausted → Director Range fallback (DIRECTOR_FALLBACK_MAX_TEAM_DISTANCE = 2000 straight line) | Indicative marker (a random feasible far point) |
| Kernel density (in-fight SI ignored, radius shrinks with the SI cap) / hard separation (fixed 100u) / Nav cooldown / teleport supervision | Cooldown, hard sep 100u, and kernel density (radius shrinks with the SI cap) are implemented; teleport supervision is omitted |
| Real map Nav graph (exported by sm_navgraph_export: area centers/corners/flow/attribute bits/directed edges) | Graph mode: the same state machine runs on the imported adjacency list; with geometry data loaded, visibility uses real triangle raycasts (still slightly different from engine traces: no dynamic props, no glass material semantics), and falls back to the heuristic (straight-line ≤1500, |Δz| ≤120, detour ratio ≤1.6) without geometry; no ladder edges, and the endgame branch of IsValidFlags is not replicated |
| The blocked snapshot is read live from the engine every frame by the extension (dynamic blockers such as elevators/doors/nav_block) | Graph mode uses manual "Block areas" marking; Dijkstra and candidate collection simply skip blocked nodes |
| The item/blocking entity layer is a runtime snapshot taken after map load (so it naturally includes stripper additions/removals/changes); at round start the Director may prune some pre-placed spawn points based on item density | The visualizer renders item icons and blocking boxes exactly as captured in the snapshot, does not simulate the Director pruning, and requires v2 export data |