Files
Commonwealth-Online-Public/docs/f4-animation-descriptor.md
T
andrew a6b2505242 Add animation sync docs and descriptor infra
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.
2026-06-03 16:52:47 +12:00

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.h for 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 BSFixedString allocation 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

  1. Phase 1.1: Use debug logging to extract actual variable indices from running F4
  2. Phase 1.2: Map TiltedEvolution animation flow into F4T terms (see animation-architecture-alignment.md)
  3. Phase 1.3: Test character controller velocity injection on dynamic proxies
  4. Phase 2: Extend RemotePlayerState with actor state flags + action events
  5. Phase 3: Implement F4AnimationDescriptor class 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)