Add detailed design and implementation scaffolding for TiltedEvolution-style animation synchronization. New documentation: animation-architecture-alignment.md, animation-sync-analysis.md, f4-animation-descriptor.md, phase1-3-completion-report.md and updates to dev-log.md describing Phase 1-3 progress. Plugin: introduce F4AnimationDescriptor (plugin/include/F4AnimationDescriptor.h, plugin/src/F4AnimationDescriptor.cpp) and extend remote state handling (plugin/include/F4TRemotePlayerState.h). Integrate protocol/state extensions and refactor points: plugin/src/F4TNetworking.cpp now parses optional actorStateFlags and actionEvents; proxy controller and animation sync files (F4TProxyActorController.cpp, F4TProxyAnimationSync.cpp) updated to support descriptor-based bulk variable snapshots and actor state replication. Server/tools: update server/dev_server_app.py and server/fake_client.py to handle and display the new optional fields. These changes are additive and backward-compatible and set up phases for action capture, dynamic proxy spawn, and action-replay integration.
7.7 KiB
Fallout 4 Animation Graph Variables & Descriptor Mapping
Overview
This document maps Fallout 4's animation graph variable names and indices for the humanoid master behavior graph. This is the foundation for implementing descriptor-based animation synchronization similar to TiltedEvolution's model.
Goal: Replace per-frame string-based graph variable writes (e.g., SetGraphVariableFloat("Speed", 85.0)) with efficient indexed bulk writes from a pre-computed descriptor table.
Animation Graph Variable Categories
Fallout 4's humanoid master behavior graph organizes variables into three types:
1. Float Variables (Locomotion & Direction)
Used to control movement speed, direction, and animation blending.
| Variable Name | Index | Type | Role | Network Sync | Notes |
|---|---|---|---|---|---|
Speed |
TBD | Float | Locomotion blend speed (0-105) | ✅ YES | Primary locomotion driver |
direction |
TBD | Float | Facing/movement direction (degrees) | ✅ YES | Rotation relative to movement |
speedSampled |
TBD | Float | Sampled speed for smoothing | ❌ Derive | Computed from velocity |
speedDamped |
TBD | Float | Damped/smoothed speed | ❌ Derive | Animation system internal |
pitchGunAim |
TBD | Float | Pitch angle when aiming | ❌ No | Combat specific |
weaponAdjust |
TBD | Float | Weapon positioning | ❌ No | Combat specific |
velocityZ |
TBD | Float | Vertical velocity | ❌ No | Handled by Havok |
Speed Buckets (Estimated):
- Idle: 0.0
- Walk: 35-55
- Run: 55-85
- Sprint: 85-105
2. Boolean Variables (State Flags)
Control state transitions and mode changes.
| Variable Name | Index | Type | Role | Network Sync | Notes |
|---|---|---|---|---|---|
isSprinting |
TBD | Bool | Sprint mode active | ✅ YES | Triggers sprint animations |
isSneaking |
TBD | Bool | Sneak/crouch mode | ✅ YES | Triggers sneak locomotion |
isMoving |
TBD | Bool | Any movement active | ✅ YES | Idle ↔ movement transition |
bMotionDriven |
TBD | Bool | Motion-driven locomotion | ❌ No | Engine internal |
bInMoveState |
TBD | Bool | In locomotion state machine | ❌ No | Engine internal |
bSprintOK |
TBD | Bool | Sprint available | ❌ No | Game state dependent |
3. Integer Variables (Equipment & State)
Track equipped items and combat state.
| Variable Name | Index | Type | Role | Network Sync | Notes |
|---|---|---|---|---|---|
iLeftHandType |
TBD | Int | Left hand weapon/item type | ❌ No | Inventory sync separate |
iRightHandEquipped |
TBD | Int | Right hand equipped? (0/1) | ❌ No | Inventory sync separate |
iIsInSneak |
TBD | Int | Sneak state (0/1/2) | ❌ No | Derived from isSneaking bool |
Variable Index Discovery Process
To determine actual indices for FO4, we need to:
1. Extract Indices via AnimationGraphManager
// Pseudocode to dump actual variable indices
void DumpAnimationGraphVariables(RE::Actor* actor) {
auto graphHolder = static_cast<RE::IAnimationGraphManagerHolder*>(actor);
RE::BSTSmartPointer<RE::BSAnimationGraphManager> manager;
if (graphHolder->GetAnimationGraphManagerImpl(manager) && manager) {
// Access manager->behaviorGraph->animationVariables
// Iterate through variable cache and log names + indices
// Compare with known string names to build reverse mapping
}
}
2. Verify via Creation Kit
- Open the humanoid master behavior graph in Behavior Editor
- Right-click variables to see internal indices/cache layout
- Cross-reference with runtime dumps
3. Cross-Reference with CommonLibF4 Headers
- Search
RE/H/BSAnimationGraphManager.hfor hint structs - Look for variable container definitions
Comparison with TiltedEvolution (Skyrim SE)
TiltedEvolution's AnimationGraphDescriptor_Master_Behavior.cpp syncs:
Skyrim SE Synced Booleans:
kIsSprinting(index 50)kIsSneaking(index 186)kbInMoveState(index 98)kbMotionDriven(index 41)kisMoving(index 284)
Skyrim SE Synced Floats:
kSpeed(index 0)kSpeedSampled(index 40)kSpeedDamped(index 183)kDirection(index 1)kSpeedWalk,kSpeedRun(indices 4, 5)
FO4 Likely Similar:
- Speed float: core locomotion
- Direction float: facing
- isSprinting, isSneaking: bool state flags
- velocityZ: vertical velocity (Havok-driven, derived)
Minimum Viable Sync Set
For initial Phase 1-2 implementation, sync only the essential variables needed for basic locomotion:
| Variable | Type | Index | Reason |
|---|---|---|---|
Speed |
Float | TBD | Must have; drives walk/run/sprint |
direction |
Float | TBD | Must have; face remote player's heading |
isSprinting |
Bool | TBD | Should have; sprint visual distinction |
isSneaking |
Bool | TBD | Should have; sneak locomotion + crouch |
isMoving |
Bool | TBD | Should have; idle ↔ movement transition |
Deferred (Phase 2+):
- Combat variables (aiming, weapon adjust, etc.)
- Jumping/falling (vertical velocity)
- Facial expressions / emotion
- IK targets
Current F4T Implementation (Before Refactor)
Current F4TProxyAnimationSync.cpp writes these by string name:
// Per-frame, on every proxy actor:
TrySetGraphFloat(graphHolder, "Speed", desired.graphSpeed);
TrySetGraphFloat(graphHolder, "speed", desired.graphSpeed); // fallback
TrySetGraphFloat(graphHolder, "SpeedLower", desired.graphSpeed);
TrySetGraphBool(graphHolder, "IsSprinting", desired.isSprinting);
Issues:
- String lookup overhead (one
BSFixedStringallocation per write, per frame, per proxy) - No caching of variable indices
- If a variable name is wrong, silent failure (write returns false)
- No explicit velocity injection (character controller velocity = 0)
Proposed F4AnimationDescriptor Model
After Phase 1 research, we'll build:
// plugin/include/F4AnimationDescriptor.h
class F4AnimationDescriptor {
public:
// Per-graph-type lookup
static F4AnimationDescriptor& GetHumanoidDescriptor();
// Bulk read/write by index
void SaveVariablesFromCache(
RE::IAnimationGraphManagerHolder& holder,
AnimationVariableSnapshot& snapshot);
void LoadVariablesToCache(
RE::IAnimationGraphManagerHolder& holder,
const AnimationVariableSnapshot& snapshot);
private:
std::vector<std::string> floatVariableNames;
std::vector<std::string> boolVariableNames;
std::vector<std::string> intVariableNames;
};
Benefits:
- Pre-computed once at startup
- O(1) index lookups instead of O(n) string searches
- Batch reads/writes in one graph manager lock
- Matches TiltedEvolution's proven architecture
Testing Checklist (Phase 1.3)
- Verify
Actor::Move(0.016f, {0,0,0}, false)works on dynamically spawned actors - Verify
SetLinearVelocityImpl()accessible via Move return value - Test with proxy in same cell as player
- Confirm velocity persists across frames
- Log animation graph state transitions (idle → walk → run)
- Verify no crashes with velocity injection
- Document any FO4-specific gotchas vs Skyrim
Next Steps
- Phase 1.1: Use debug logging to extract actual variable indices from running F4
- Phase 1.2: Map TiltedEvolution animation flow into F4T terms (see
animation-architecture-alignment.md) - Phase 1.3: Test character controller velocity injection on dynamic proxies
- Phase 2: Extend
RemotePlayerStatewith actor state flags + action events - Phase 3: Implement
F4AnimationDescriptorclass with bulk read/write
References
- TiltedEvolution:
Code/encoding/Structs/Skyrim/AnimationGraphDescriptor_Master_Behavior.cpp - CommonLibF4:
RE/H/BSAnimationGraphManager.h,RE/H/IAnimationGraphManagerHolder.h - Fallout 4 CK: Behavior Editor (humanoid master behavior graph)