Danger Zones
Danger zones are rectangular ring areas surrounding each chunk's baseplate. They serve as the spawnable region for enemies and trigger insanity effects for players.
Ring Creation
For each baseplate, 4 rectangular parts are created by subtracting the inner rect (baseplate) from the outer rect (baseplate + 300 stud padding):
┌──────────────────────┐
│ Danger Zone │
│ ┌──────────────┐ │
│ │ Baseplate │ │
│ │ (inner) │ │
│ └──────────────┘ │
│ │
└──────────────────────┘
(outer)
subtractRect(outer, inner) from quadtree.ts returns up to 4 non-overlapping rectangles.
Spatial Indexing
- Octree stores all danger zone parts for fast radius queries
- Region3 computed per zone for world.store atom integration
- Baseplate mapping tracks which zones belong to which chunk (for cleanup on unload)
Player Detection
Server-Side
ChunkService checks player positions against danger zones every 0.25s:
- Query octree for nearby danger zones
- Check if player position is within zone's Region3
- Update
dangerZonePlayersatom - Apply insanity increment on client
Client-Side
The dangerZonePlayers atom syncs to clients, driving:
- Insanity increase rate
- Vignette intensity
- Audio distortion (future)
Distributed Creation
For performance, danger zone creation is deferred:
Chunk created
→ task.defer() → createDangerZoneDistributed()
→ Create ring parts (4 rectangles)
→ Register in octree
→ Define Region3 per zone
→ Map zones to baseplate
Cleanup
When a chunk unloads:
- Remove all danger zone parts for that baseplate
- Clean up octree nodes
- Remove from baseplate mapping
- Remove Region3 entries
Key Files
| File | Purpose |
|---|---|
danger-zone-manager.ts | Ring creation, octree, Region3, cleanup |
quadtree.ts | subtractRect() for ring computation |
chunk-service.ts | Player detection in heartbeat |