poe2-bot/docs/simulator.md
2026-03-07 09:53:57 -05:00

180 lines
6.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Nexus.Simulator — Standalone Game World
## Purpose
Test bot systems (combat, navigation, threat assessment) without the real game. Replaces the memory-reading pipeline with a procedural game world. Bot systems run unmodified — they see identical `GameState` objects and emit actions to `IInputController`.
## Architecture
```
SimWorld (game tick loop)
├── SimPoller (60Hz background thread)
│ ├── FlushToWorld() → transfer input to SimWorld
│ ├── Tick(dt) → advance simulation
│ ├── SimStateBuilder.Build() → SimWorld → GameState
│ └── Push to GameDataCache
├── SimInputController (captures bot actions)
│ ├── WASD → MoveDirection vector (45° isometric conversion)
│ ├── Skills → QueueSkill(scanCode, targetWorldPos)
│ ├── Mouse → track position, screen↔world conversion
│ └── Flash timers for input visualization
├── Bot Logic Thread (60Hz)
│ ├── GameStateEnricher.Enrich(state)
│ ├── All 6 systems: Threat, Movement, Navigation, Combat, Resource, Loot
│ ├── NavigationController.Update()
│ └── ExecuteActions() → SimInputController
└── Render Thread (ImGui + Veldrid)
├── TerrainRenderer (diamond cells, isometric)
├── EntityRenderer (player, enemies, health bars)
├── EffectRenderer (melee cones, AOE circles, projectile lines)
├── PathRenderer (A* waypoints)
├── InputOverlayRenderer (keyboard + mouse state)
└── DebugPanel (system toggles, stats, spawn controls)
```
## SimWorld — Game Loop
### Tick (dt-based, 60Hz)
```
1. CheckAndExpandTerrain() → expand when player within 50 cells of edge
2. MovePlayer(dt) → WASD direction × speed × dt, collision with terrain
3. ProcessSkills() → dequeue skill casts, dispatch by scan code
4. UpdateProjectiles(dt) → move, check terrain/enemy collisions
5. UpdateEffects(dt) → decay visual effects (0.3s duration)
6. UpdateEnemies(dt) → AI state machine per enemy
7. UpdateRespawns(dt) → cull far enemies, spawn new groups
```
### Terrain
- Procedural: all walkable with scattered obstacles (rock clusters, wall segments, pillars)
- 500×500 initial grid, `WorldToGrid = 23/250`
- **Infinite expansion**: Expands 250 cells per side when player within 50 cells of edge
- Preserves existing data via array copy with offset adjustment
### Player
- Position (Vector2), Health/Mana with regen (5 HP/s, 10 MP/s)
- Move speed: 400 world units/s
- Collision: slide-along-X / slide-along-Y fallback if direct move blocked
### Skills
| Scan Code | Type | Behavior |
|-----------|------|----------|
| Q (0x10), R (0x13) | AOE | Damage all enemies within 250u of target position |
| E (0x12), T (0x14) | Projectile | Spawn projectile, 1200 speed, 800 range, 80u hit radius |
| LMB, RMB | Melee | 150u cone, 120° angle from player toward target |
Base damage: 200 per hit. Configurable via SimConfig.
### Enemy AI
```
State machine per SimEnemy:
Idle → wander randomly within 200u of spawn, new target every 2-5s
│ player within 600u (aggro range)
Chasing → move toward player at 75% player speed
│ player within 100u (attack range)
Attacking → stand still, deal 30 damage every 1.5s
│ player escapes attack range
▼ back to Chasing
│ health ≤ 0
Dead → visible for 2s → queue for respawn (5s delay)
```
### Enemy Spawning
- **Groups**: 3-7 enemies per spawn, leader keeps rolled rarity, rest are Normal
- **Rarity distribution**: 70% Normal, 20% Magic, 8% Rare, 2% Unique
- **HP multipliers**: Magic=1.5×, Rare=3×, Unique=5× base (200)
- **Spawn ring**: 800-2000 world units from player
- **Direction bias**: ±90° cone ahead of player's movement direction
- **Culling**: Remove enemies > 3000u from player
- **Population**: Maintain 25 enemies, spawn new groups as needed
## Bridge Layer
### SimPoller
Replaces MemoryPoller. Background thread at 60Hz:
1. `FlushToWorld()` — transfer accumulated input
2. `world.Tick(dt)` — advance simulation (dt clamped to 0.1s max)
3. `SimStateBuilder.Build()` — convert to GameState
4. Push to GameDataCache (same fields as production)
### SimStateBuilder
Converts SimWorld state → GameState:
- Each SimEnemy → EntitySnapshot (with rarity, threat level, AI state, HP)
- SimPlayer → PlayerState (position, vitals, skills)
- Camera matrix: orthographic projection (12800×7200 world units → 2560×1440 screen)
### SimInputController
Implements IInputController, captures actions instead of sending Win32 input:
- WASD → direction vector (with 45° isometric inversion)
- Skills → `SimWorld.QueueSkill(scanCode, worldPos)`
- Mouse → screen position tracking, inverse camera transform for world coords
- Input visualization: flash timers for keyboard/mouse overlay
## Rendering
### ViewTransform (Isometric Camera)
45° counter-clockwise rotation matching the game's camera:
```
World → Grid: gx = worldX × WorldToGrid
Grid → Screen: rx = (gx - gy) × cos(45°)
ry = -(gx + gy) × cos(45°)
Screen = canvasOrigin + viewOffset + (rx, ry) × zoom
```
### Renderers
| Renderer | Draws |
|----------|-------|
| TerrainRenderer | Diamond cells (rotated grid), explored overlay, minimap |
| EntityRenderer | Player (green circle), enemies (colored by rarity), health/mana bars |
| EffectRenderer | Melee cones (red triangle fan), AOE circles (blue), projectile lines (cyan) |
| PathRenderer | Cyan waypoint lines and dots from A* path |
| InputOverlayRenderer | Keyboard (3 rows: 1-5, QWERT, ASDF) + mouse (L/R/M buttons) |
| DebugPanel | Pause/speed, player stats, enemy counts, system toggles, threat info |
### VeldridImGuiRenderer
Custom ImGui backend for Veldrid 4.9.0 + D3D11:
- HLSL shaders compiled at runtime via D3DCompiler P/Invoke
- Dynamic vertex/index buffers, font texture from ImGui atlas
- Alpha blending pipeline with scissor rect support
## SimConfig
```
Terrain: 500×500, WorldToGrid=23/250, ExpandThreshold=50, ExpandAmount=250
Player: Speed=400, HP=1000, MP=500, HPRegen=5/s, MPRegen=10/s
Enemies: Count=25, Aggro=600u, Attack=100u, Speed=75%, HP=200, Damage=30
Spawning: Ring=800-2000u, Groups=3-7, Cull=3000u
Skills: Melee=150u/120°, AOE=250u, Projectile=1200speed/800range, Damage=200
Rarity: Normal=70%, Magic=20%, Rare=8%, Unique=2%
Simulation: SpeedMultiplier=1×, Pauseable
```
## Running
```
dotnet run --project src/Nexus.Simulator
```
Dependencies: Core, Data, Systems, Pathfinding, ImGui.NET, Veldrid, Veldrid.StartupUtilities
Does NOT depend on: Memory, Input, Screen, Game, Bot, Ui, Trade