# 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