mirror of
https://github.com/2revoemag/PSF-BotServer.git
synced 2026-01-20 02:24:45 +00:00
314 lines
11 KiB
Markdown
314 lines
11 KiB
Markdown
|
|
# PlanetSide Bots - Handoff Document
|
||
|
|
|
||
|
|
> **Read this first** if you're a new Claude instance or agent picking up this project.
|
||
|
|
|
||
|
|
## What Is This Project?
|
||
|
|
|
||
|
|
We're adding **bot players** to PlanetSide 1 via the PSForever server emulator. The goal is to make the game world feel alive even with low real player population.
|
||
|
|
|
||
|
|
### The Vision
|
||
|
|
- Hundreds of bots per server (scaling down as real players join)
|
||
|
|
- Bots that feel like real players, not mechanical turrets
|
||
|
|
- V-menu chatter, teamwork, attitude/personality systems
|
||
|
|
- Infantry first, vehicles later
|
||
|
|
|
||
|
|
### Key Stakeholder
|
||
|
|
The user is a **veteran PlanetSide player** (decade+ experience) and serves as the expert on "game feel". They have detailed notes on how bots should behave. Always defer to them on gameplay questions.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Project Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
PSF-LoginServer/
|
||
|
|
├── bot-docs/ ← Bot project documentation
|
||
|
|
│ ├── HANDOFF.md ← YOU ARE HERE - Start here
|
||
|
|
│ ├── PROJECT.md ← Overview, goals, status
|
||
|
|
│ ├── GAME_FEEL.md ← Behavioral spec (vision, movement, V-menu, classes, etc.)
|
||
|
|
│ ├── ARCHITECTURE.md ← Technical design decisions
|
||
|
|
│ ├── CODEBASE_MAP.md ← Key files with line numbers (CRITICAL REFERENCE)
|
||
|
|
│ ├── POC_PLAN.md ← Phased implementation milestones
|
||
|
|
│ ├── DEV_SETUP.md ← Development environment setup
|
||
|
|
│ └── SKETCHES/ ← Conceptual code (not production)
|
||
|
|
│ ├── BotActor_v1.scala
|
||
|
|
│ └── BotSpawner_v1.scala
|
||
|
|
├── src/main/scala/net/psforever/
|
||
|
|
│ └── actors/bot/ ← Bot implementation code
|
||
|
|
│ ├── BotManager.scala
|
||
|
|
│ └── BotAvatarActor.scala
|
||
|
|
└── ... ← Rest of PSForever server codebase
|
||
|
|
```
|
||
|
|
|
||
|
|
### Read Order for New Instance
|
||
|
|
1. **HANDOFF.md** (this file) - Context and decisions
|
||
|
|
2. **CODEBASE_MAP.md** - Where things are in the code
|
||
|
|
3. **GAME_FEEL.md** - How bots should behave
|
||
|
|
4. **SKETCHES/** - Conceptual code to understand approach
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Key Technical Decisions Made
|
||
|
|
|
||
|
|
### 1. BotActor Approach (NOT SessionActor)
|
||
|
|
We decided to create a new `BotActor` rather than emulating `SessionActor` because:
|
||
|
|
- SessionActor's main job is handling network packets from clients
|
||
|
|
- Bots have no client, so no incoming packets
|
||
|
|
- BotActor can be optimized specifically for AI needs
|
||
|
|
- Less overhead, better scalability
|
||
|
|
|
||
|
|
### 2. Server-Side Native Bots
|
||
|
|
Bots are first-class server entities, not fake clients connecting from outside.
|
||
|
|
- Bots use existing `Player` and `PlayerControl` code
|
||
|
|
- No network overhead
|
||
|
|
- Actions broadcast through same services as real players
|
||
|
|
|
||
|
|
### 3. Bot Identity
|
||
|
|
Bot characters use:
|
||
|
|
- **High positive IDs** (900000+) to avoid collision with real DB players
|
||
|
|
- **No special characters in names** - use `xxBOTxxName` format (not `[BOT]Name`)
|
||
|
|
- Predefined loadouts per class
|
||
|
|
|
||
|
|
### 4. Tick Rate
|
||
|
|
- 10-20 FPS for bot AI decisions (not 60)
|
||
|
|
- Can reduce further for bots far from real players
|
||
|
|
- Server load monitoring will inform final values
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Bot Architecture Summary
|
||
|
|
|
||
|
|
```
|
||
|
|
BotManager (per zone)
|
||
|
|
├── Monitors real player population
|
||
|
|
├── Spawns/despawns bots to maintain target count
|
||
|
|
└── Manages one Ace per faction (last to logout)
|
||
|
|
|
||
|
|
BotActor (per bot)
|
||
|
|
├── 10 FPS tick loop
|
||
|
|
├── Vision cone detection (60-90 degrees)
|
||
|
|
├── Decision making (attack, retreat, objective, help)
|
||
|
|
├── Movement execution
|
||
|
|
├── State broadcasting
|
||
|
|
└── Controls a Player entity
|
||
|
|
|
||
|
|
BotAvatarActor (stub)
|
||
|
|
└── Minimal - just accepts messages PlayerControl sends
|
||
|
|
|
||
|
|
Player + PlayerControl (existing code)
|
||
|
|
├── Player entity with Vitality, inventory, etc.
|
||
|
|
└── PlayerControl handles damage/death (already exists)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Spawn Flow (Critical Path)
|
||
|
|
|
||
|
|
```scala
|
||
|
|
// 1. Create avatar (HIGH POSITIVE ID - 900000+)
|
||
|
|
val avatar = Avatar(900000 + botNum, BasicCharacterData(name, faction, sex, head, voice))
|
||
|
|
|
||
|
|
// 2. Create player entity
|
||
|
|
val player = new Player(avatar)
|
||
|
|
player.Position = spawnPosition
|
||
|
|
player.Spawn()
|
||
|
|
|
||
|
|
// 3. Create typed stub avatar actor (MUST be typed ActorRef)
|
||
|
|
val typedSystem = context.system.toTyped
|
||
|
|
val botAvatarActor: ActorRef[AvatarActor.Command] =
|
||
|
|
typedSystem.systemActorOf(BotAvatarActor(), s"bot-avatar-$botId")
|
||
|
|
|
||
|
|
// 4. Register GUIDs (ASYNC - use registerAvatar, NOT registerPlayer!)
|
||
|
|
TaskWorkflow.execute(GUIDTask.registerAvatar(zone.GUID, player)).onComplete {
|
||
|
|
case Success(_) =>
|
||
|
|
// 5. Join zone population
|
||
|
|
zone.Population ! Zone.Population.Join(avatar)
|
||
|
|
// 6. Spawn player (creates PlayerControl actor)
|
||
|
|
zone.Population ! Zone.Population.Spawn(avatar, player, botAvatarActor)
|
||
|
|
// 7. Broadcast to clients
|
||
|
|
zone.AvatarEvents ! AvatarServiceMessage(zone.id, AvatarAction.LoadPlayer(...))
|
||
|
|
case Failure(ex) =>
|
||
|
|
log.error(s"Failed: ${ex.getMessage}")
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Broadcasting (How Bots Appear to Real Players)
|
||
|
|
|
||
|
|
Bots broadcast their state via the same channels real players use:
|
||
|
|
|
||
|
|
```scala
|
||
|
|
// Position updates (10-20 times per second)
|
||
|
|
zone.AvatarEvents ! AvatarServiceMessage(
|
||
|
|
zone.id,
|
||
|
|
AvatarAction.PlayerState(guid, pos, vel, facing, crouch, jump, ...)
|
||
|
|
)
|
||
|
|
|
||
|
|
// Weapon fire
|
||
|
|
zone.AvatarEvents ! AvatarServiceMessage(
|
||
|
|
zone.id,
|
||
|
|
AvatarAction.ChangeFireState_Start(playerGuid, weaponGuid)
|
||
|
|
)
|
||
|
|
|
||
|
|
// V-menu voice commands
|
||
|
|
// (Need to investigate ChatMsg format)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Bot Classes (From User's Notes)
|
||
|
|
|
||
|
|
| Class | Role | Behavior |
|
||
|
|
|-------|------|----------|
|
||
|
|
| Driver | Vehicle operation | Low priority for gunning, wants to drive |
|
||
|
|
| Support | Heal & Repair | LOVES gunning (can heal vehicle), prioritizes healing |
|
||
|
|
| Hacker | Infiltration | Door unlocking, base capture |
|
||
|
|
| AV | Anti-Vehicle | Tank hunters |
|
||
|
|
| MAX | Heavy Exosuit | AI/AV/AA variants, switches based on intel |
|
||
|
|
| Vet | Versatile | Jack of all trades, ADAD movement, vengeance system |
|
||
|
|
| Ace | Empire Leader | ONE per empire, last to logout, uses Command Chat |
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Implementation Status
|
||
|
|
|
||
|
|
### COMPLETED (POC Working!)
|
||
|
|
- [x] BotAvatarActor stub (typed actor, absorbs messages)
|
||
|
|
- [x] BotManager (spawns bots, handles async GUID flow)
|
||
|
|
- [x] `!bot` chat command for testing
|
||
|
|
- [x] Bot spawns visible to players
|
||
|
|
- [x] Bot takes damage from players (PlayerControl works!)
|
||
|
|
- [x] Bot movement (10 tick/sec, random wandering, PlayerState broadcasts)
|
||
|
|
- [x] Multiple bots work independently
|
||
|
|
|
||
|
|
### KNOWN ISSUES (Expected for POC)
|
||
|
|
- No backpack on death (likely because bot has no items/loadout)
|
||
|
|
- Walks through walls (no collision detection)
|
||
|
|
- No Z-height adjustment (melts into stairs, terrain)
|
||
|
|
- Walk speed slightly fast for animation (4 units/sec, try 3)
|
||
|
|
|
||
|
|
### NOT YET IMPLEMENTED
|
||
|
|
- [ ] Bot loadout/equipment
|
||
|
|
- [ ] Bot shooting (weapon fire broadcasts)
|
||
|
|
- [ ] Bot death/respawn cycle
|
||
|
|
- [ ] Terrain following (Z height from map data)
|
||
|
|
- [ ] Collision avoidance
|
||
|
|
- [ ] Pathfinding
|
||
|
|
- [ ] V-menu voice command sending
|
||
|
|
- [ ] Celebration coordination system
|
||
|
|
- [ ] Vengeance/attitude system
|
||
|
|
- [ ] Population scaling (spawn/despawn based on real players)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Resolved Questions (Through Trial & Error)
|
||
|
|
|
||
|
|
1. **Avatar IDs**: Must be POSITIVE. Negative IDs break packet encoding (32-bit unsigned). Use 900000+.
|
||
|
|
2. **PlayerControl + stub AvatarActor**: WORKS! BotAvatarActor just absorbs messages, PlayerControl functions normally.
|
||
|
|
3. **GUID Registration**: Must use `registerAvatar()` not `registerPlayer()` - locker needs GUID for PlayerControl init.
|
||
|
|
|
||
|
|
## Open Questions for PSForever Devs
|
||
|
|
|
||
|
|
1. **Bot identification**: Should we add `isBot: Boolean` to Player?
|
||
|
|
2. **Spawn point access**: Best way to find valid faction spawn locations?
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Spawn Location Logic (For Future Implementation)
|
||
|
|
|
||
|
|
When a player dies, they choose from up to 3 spawn options (all must be friendly-owned):
|
||
|
|
|
||
|
|
1. **Nearest Tower** - Guard towers scattered across continents
|
||
|
|
2. **Nearest AMS** - Advanced Mobile Station (deployable spawn vehicle)
|
||
|
|
3. **Nearest Base/Facility** - The main base spawn tubes
|
||
|
|
|
||
|
|
**Special Cases:**
|
||
|
|
- **Sanctuary** (home2, home1, home3): Only one spawn option (the sanctuary itself)
|
||
|
|
- **Warpgates**: Can spawn at warpgates your faction owns
|
||
|
|
|
||
|
|
**For Bots:**
|
||
|
|
- Currently: Respawn at original spawn position (simple)
|
||
|
|
- Future: Query zone for valid faction spawn points, pick nearest or random
|
||
|
|
- Need to find: `SpawnPoint` instances, check faction ownership, calculate distance
|
||
|
|
|
||
|
|
**Code References to Investigate:**
|
||
|
|
- `SpawnPoint.scala` - Spawn point trait and calculations
|
||
|
|
- `Zone.spawnGroups` - Map of building -> spawn points
|
||
|
|
- `Building.Faction` - Check ownership for spawn eligibility
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Important Behavioral Notes
|
||
|
|
|
||
|
|
### From GAME_FEEL.md (Key Points)
|
||
|
|
- **Vision**: 60-90 degree FOV, distance-based spotting time
|
||
|
|
- **Movement**: Newbies run straight, Vets do ADAD + crouch spam
|
||
|
|
- **Retreat**: Vets retreat at low HP, Drivers save vehicles, everyone retreats when out of ammo
|
||
|
|
- **V-menu**: "Needs" always fire, celebrations are coordinated (1-6 responders, staggered timing)
|
||
|
|
- **Vengeance**: Vets remember who killed them, may seek revenge, taunt on success
|
||
|
|
- **Panic**: Non-combat bots (repairing) panic when shot, run to cover while swapping weapons
|
||
|
|
- **Chaos**: The goal is authentic battlefield chaos - spam bullets, grenades, voice commands
|
||
|
|
|
||
|
|
### What NOT to Do
|
||
|
|
- No bunny hopping (almost no one jumps except MAX dodging AV)
|
||
|
|
- No laser accuracy (bots should miss)
|
||
|
|
- No instant reactions (bots need reaction time)
|
||
|
|
- No perfect coordination (spread out, don't stand on same pixel)
|
||
|
|
- No mechanical behavior (turrets are terrible, we want human-like chaos)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Development Environment
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Server codebase
|
||
|
|
cd PSF-LoginServer
|
||
|
|
sbt compile # Compile
|
||
|
|
sbt server/run # Run server
|
||
|
|
|
||
|
|
# Requirements
|
||
|
|
- Java 8 JDK
|
||
|
|
- sbt (Scala Build Tool)
|
||
|
|
- PostgreSQL 10+
|
||
|
|
- PlanetSide client (version 3.15.84.0)
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Context for Future Agents
|
||
|
|
|
||
|
|
If you're a **coding agent** tasked with implementation:
|
||
|
|
1. Read `CODEBASE_MAP.md` for file locations
|
||
|
|
2. Read `SKETCHES/` for conceptual starting points
|
||
|
|
3. Start with Milestone 1: spawn a static bot that appears in-game
|
||
|
|
4. Test empirically - compile, run, connect with client, observe
|
||
|
|
|
||
|
|
If you're a **research agent** investigating something:
|
||
|
|
1. The PSF-LoginServer codebase is in `./PSF-LoginServer/`
|
||
|
|
2. All server code is under `src/main/scala/net/psforever/`
|
||
|
|
3. Tests are under `src/test/scala/`
|
||
|
|
4. Use grep/glob to find patterns
|
||
|
|
|
||
|
|
If the user says **"update the docs"**:
|
||
|
|
1. Update the relevant .md files
|
||
|
|
2. Keep `CODEBASE_MAP.md` current with any new discoveries
|
||
|
|
3. Add line numbers when referencing code
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Last Session Summary
|
||
|
|
|
||
|
|
**Date**: 2024 (context creation date)
|
||
|
|
|
||
|
|
**Accomplished**:
|
||
|
|
- Analyzed PSF-LoginServer codebase architecture
|
||
|
|
- Mapped spawn/broadcast/GUID flows
|
||
|
|
- Created behavioral spec from user's notes
|
||
|
|
- Sketched BotActor and BotSpawner concepts
|
||
|
|
- Documented key files with line numbers
|
||
|
|
|
||
|
|
**Next Steps**:
|
||
|
|
- Set up dev environment
|
||
|
|
- Start Phase 1: spawn a static bot
|
||
|
|
- OR wait for dev team answers on open questions
|