mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
- Document tracer direction fix root cause and solution in TOWER_DEMO.md - Select Hossin as the continent for tower arena demo - Update PROJECT.md with tracer direction fix completion - Update status checklists
188 lines
5.3 KiB
Markdown
188 lines
5.3 KiB
Markdown
# Tower Attack Demo
|
|
|
|
## Overview
|
|
A controlled demonstration of the bot combat system at a single tower location. By manually capturing coordinates, we create a bounded "arena" where bots behave correctly without needing full world geometry.
|
|
|
|
## Why This Approach
|
|
- **Wall shooting problem**: Bots currently shoot through walls (no server-side collision)
|
|
- **Full solution is massive**: UBR mesh extraction + navmesh generation = huge project
|
|
- **POC needs to be demonstrable**: Bots shooting through 4 concrete walls isn't a demo, it's a bug showcase
|
|
- **Scrappy but effective**: Manual coordinate capture gives us a working showcase
|
|
|
|
---
|
|
|
|
## Implementation Plan
|
|
|
|
### Step 1: Choose a Tower
|
|
Pick a tower with good sight lines and clear boundaries:
|
|
- [x] Select continent: **Hossin** (jungle continent with interesting terrain)
|
|
- [ ] Select specific tower location (user to provide)
|
|
- [ ] Capture tower coordinates via `!locrec <note>` command in-game
|
|
|
|
### Step 2: Define Combat Arena
|
|
Capture boundary coordinates by walking the perimeter:
|
|
|
|
```
|
|
/loc at each corner point:
|
|
- Northwest corner
|
|
- Northeast corner
|
|
- Southeast corner
|
|
- Southwest corner
|
|
- Height bounds (ground level, top platform)
|
|
```
|
|
|
|
### Step 3: Implement Arena System
|
|
|
|
```scala
|
|
// Combat arena definition
|
|
case class CombatArena(
|
|
minX: Float, maxX: Float,
|
|
minY: Float, maxY: Float,
|
|
minZ: Float, maxZ: Float,
|
|
name: String = "unnamed"
|
|
)
|
|
|
|
// Check if position is within arena bounds
|
|
def isInArena(pos: Vector3, arena: CombatArena): Boolean = {
|
|
pos.x >= arena.minX && pos.x <= arena.maxX &&
|
|
pos.y >= arena.minY && pos.y <= arena.maxY &&
|
|
pos.z >= arena.minZ && pos.z <= arena.maxZ
|
|
}
|
|
|
|
// Only engage if BOTH bot AND target are in the arena
|
|
// This prevents shooting through walls into/out of the arena
|
|
def findTarget(botState: BotState): Option[Player] = {
|
|
val arena = currentArena // loaded from config
|
|
|
|
zone.LivePlayers.filter { p =>
|
|
isInArena(botState.player.Position, arena) &&
|
|
isInArena(p.Position, arena) &&
|
|
p.isAlive &&
|
|
p.Faction != botFaction &&
|
|
// ... other existing checks
|
|
}
|
|
}
|
|
```
|
|
|
|
### Step 4: Optional - Interior Exclusion Zones
|
|
Define boxes for building interiors where bots won't engage:
|
|
|
|
```scala
|
|
case class ExclusionZone(
|
|
minX: Float, maxX: Float,
|
|
minY: Float, maxY: Float,
|
|
minZ: Float, maxZ: Float,
|
|
name: String = "interior"
|
|
)
|
|
|
|
// Skip targets in exclusion zones
|
|
def isInExclusionZone(pos: Vector3, zones: Seq[ExclusionZone]): Boolean = {
|
|
zones.exists { zone =>
|
|
pos.x >= zone.minX && pos.x <= zone.maxX &&
|
|
pos.y >= zone.minY && pos.y <= zone.maxY &&
|
|
pos.z >= zone.minZ && pos.z <= zone.maxZ
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Demo Scenario
|
|
|
|
### Setup
|
|
1. Spawn 3-5 NC bots around tower perimeter
|
|
2. Player approaches as TR/VS
|
|
3. Bots engage when player enters arena bounds
|
|
4. Combat feels natural - no wall shooting because everyone is in open area
|
|
|
|
### What to Show
|
|
- Bots spot player and react (2-second delay)
|
|
- Bots track and engage target
|
|
- Accuracy/recoil system visible in hit patterns
|
|
- Bots die when killed, respawn after delay
|
|
- Weapon drawn, muzzle flash, sound effects
|
|
|
|
### Known Limitations for Demo
|
|
- [x] ~~No tracers~~ **RESOLVED** - tracers working! (see notes below)
|
|
- [ ] Bots don't navigate around obstacles (random wandering only)
|
|
- [ ] Single hardcoded arena location
|
|
|
|
---
|
|
|
|
## Future: Scaling Beyond One Tower
|
|
|
|
Once the single-tower demo works, the approach can scale:
|
|
|
|
1. **Multiple arenas**: Define several towers/bases as combat zones
|
|
2. **Config file**: Load arena definitions from JSON/YAML
|
|
3. **Auto-generation**: Eventually parse map data for structure bounds
|
|
4. **Full solution**: UBR mesh extraction for complete world collision
|
|
|
|
---
|
|
|
|
## Coordinate Capture Workflow
|
|
|
|
When ready to capture tower coordinates:
|
|
|
|
```
|
|
1. Log into game, go to chosen tower
|
|
2. Walk to each boundary corner, type /loc
|
|
3. Record coordinates in format:
|
|
|
|
Tower: [Name]
|
|
Continent: [home1/home2/etc]
|
|
|
|
Boundary Points:
|
|
- NW: (x, y, z)
|
|
- NE: (x, y, z)
|
|
- SE: (x, y, z)
|
|
- SW: (x, y, z)
|
|
|
|
Height Bounds:
|
|
- Ground: z = [value]
|
|
- Top: z = [value]
|
|
|
|
Optional Interior Exclusions:
|
|
- Room 1: (minX, minY, minZ) to (maxX, maxY, maxZ)
|
|
```
|
|
|
|
---
|
|
|
|
## Tracer Investigation Notes
|
|
|
|
**Status: RESOLVED** ✓
|
|
|
|
### Root Cause
|
|
The client caches player orientation when `ChangeFireStateMessage_Start` is received
|
|
and uses that cached orientation for tracer direction rendering. Our original code
|
|
sent the fire state message BEFORE updating/broadcasting the bot's orientation.
|
|
|
|
### Solution
|
|
In `startFiring()`:
|
|
1. Calculate yaw to face target
|
|
2. Update `player.Orientation` to face target
|
|
3. Broadcast `PlayerState` with correct orientation
|
|
4. **THEN** send `ChangeFireStateMessage_Start`
|
|
|
|
Also fixed `facingYawUpper` in PlayerState to be 0 (relative to body) instead of
|
|
the absolute yaw value.
|
|
|
|
### Key Learnings
|
|
- Tracers use LocalEvents like turrets (`LocalAction.SendResponse(ChangeFireStateMessage_Start)`)
|
|
- The firing flag (`ChangeFireStateMessage_Start`) MUST be sent for tracers to render
|
|
- Orientation MUST be correct BEFORE fire state is sent - client caches it
|
|
- `facingYawUpper` is relative to `facingYaw`, not absolute (0 = looking straight ahead)
|
|
|
|
---
|
|
|
|
## Status
|
|
|
|
- [x] Tracers working correctly
|
|
- [x] Continent selected: Hossin
|
|
- [ ] Tower location selected
|
|
- [ ] Coordinates captured via !locrec
|
|
- [ ] Arena bounds implemented
|
|
- [ ] Exclusion zones defined (optional)
|
|
- [ ] Demo tested and working
|
|
- [ ] Video/screenshots captured
|