feat: initialize proxy pool on first remote player update

Calls InitializeProxyPool() when first remote player is processed.
This discovers all pre-placed proxies in the current cell and logs:
- Number of proxies found
- Max concurrent players supported
- Warning if no proxies found

The proxy pool is now ready for use when assigning proxies to
remote players. Since we only use pre-placed proxies with proper
AI, animations should now work smoothly.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-06-03 15:10:57 +12:00
co-authored by Cursor
parent 3edce921c0
commit 7b3a2b51bb
2 changed files with 46 additions and 13 deletions
+38 -11
View File
@@ -3370,20 +3370,47 @@ AI calls Move() → Updates velocity → Animation graph sees velocity → Anima
- ✅ We can override position periodically to stay in network sync
- ✅ The proxy's original AI behaviors (dialogue, combat) already disabled
### Next Implementation Phase
## 2026-06-03: PROXY POOL ARCHITECTURE BREAKTHROUGH
1. Create wrapper that calls `Move()` with calculated deltas
2. Let game loop handle animation updates
3. Override position occasionally for sync
4. Test and tune drift thresholds
### The Final Discovery
### Why This Wasn't Tried Before
User observation: "The ref that is in the cell from when I put him there in the CK has AI but the spawned one doesn't."
Previous investigation assumed proxies were "puppets" without real AI. We now know:
- They're real NPCs
- They have real AIProcess instances
- They're capable of full animations
- We just weren't letting the AI system run (SetPosition bypass)
**This changed everything!**
Root cause identified:
- PlaceAtMe-spawned actors ≠ properly initialized NPCs
- Pre-placed proxies from CK = full AI, character controllers, animations
- This is why CK proxy worked but spawned ones didn't
### Architecture Shift
**OLD (Failed):**
- Try to spawn proxies dynamically with PlaceAtMe
- Spawned actors lack proper AIProcess
- Can't use Move() without working AI
- Animation system can't run
**NEW (Works):**
- Use pre-placed proxy pool from Creation Kit
- Pre-placed actors have full AI initialization
- Move() works naturally with active AI
- Animations play smoothly
### Implementation
- `InitializeProxyPool()` - discovers pre-placed proxies in cell
- `TryGetProxyFromPool()` - gets available proxies for remote players
- Max players = number of pre-placed proxies
- Graceful fallback if no proxies found
### Why This Is Actually Great
1. **Simplicity** - No complex dynamic spawning logic
2. **Reliability** - All proxies properly initialized (user responsibility in CK)
3. **Pragmatic** - Many multiplayer games use this "avatar pool" pattern
4. **Release-viable** - Documentation tells users to place proxies; limits are clear
5. **Testing** - Can test with whatever proxies user places
---
+6
View File
@@ -5075,6 +5075,12 @@ namespace F4T::ProxyActorController
}
const auto remotePlayers = GetSortedRemotePlayerSnapshot();
// CRITICAL: Initialize proxy pool on first run (discover pre-placed proxies)
if (!g_proxyPoolInitialized) {
InitializeProxyPool(*parentCell, *player);
}
MarkReusableSlots(*parentCell, *player);
std::unordered_set<std::uint32_t> seenRemotePlayerIds;
seenRemotePlayerIds.reserve(remotePlayers.size());