Milestone 1: Proxy actors now equip remote players' right-hand weapons and play armed idle/locomotion poses when weaponDrawn=true. Adds rightHand weapon slot to equippedItems protocol, weapon graph variable support (iSyncGunDown: 0=drawn, 1=holstered), and weapon FSM events (weaponDraw, readyStateEnter, gunDownStateEnter). Fixes two critical animation state churn bugs: frustum-visibility flicker no longer resets animation state on every update tick, and idle proxies no longer register as changed on every frame. Includes WeaponBehavior graph loading via AIProcess::RequestLoadAnimationsForWeaponChange() and manual weapon attachment fallback. New docs/weapon-animation-sync.md reference guide maps animation events and variables from F4-Animation-Research. Experimental alert-state reassertion for armed proxies to test NPC combat state gating of weapon-ready poses.
7.0 KiB
Weapon Animation Sync Reference
Source: F4-Animation-Research unpacked XML (
RaiderRootBehavior.xml,WeaponBehavior.xml)
Overview
Fallout 4 weapon animation is hierarchical:
- RaiderRootBehavior — Master humanoid graph (1058 events, 299 variables)
- WeaponWrappingBehavior — Injury/special-case wrapper
- WeaponBehavior — Gun-specific FSM (state machine)
- Clips — WPN* shared anims + Weapon//* per-weapon overrides
For proxy actors to hold and fire weapons, the animation graph must switch from MTBehavior (unarmed) to WeaponBehavior when a weapon is equipped.
Key Graph Variables
Root Graph (RaiderRootBehavior)
| Variable | Type | Role |
|---|---|---|
iSyncGunDown |
int | Weapon state: 0=ready/drawn, 1=holstered/lowered |
iRifleDrawnStateID |
int | Rifle-specific drawn state (confirm exact values in-game) |
RifleDrawnCurrentState |
int | Current rifle state mirror |
iAttackState |
int | Attack sub-state (0=idle, 1=attacking, etc.) |
isFiring |
bool | Currently firing (true only during fire animation) |
iSyncFireState |
int | Fire state mirror (syncs with attack events) |
IsAttackReady |
bool | Can initiate attack |
GunGripPointer |
(struct) | Hand IK to weapon grip |
WeaponBehavior Graph
Uses similar ints but delegates to RaiderRoot for most state. Primary events drive FSM transitions; graph variables control blending.
Key Animation Events
Events are edge-triggered (fire once on transition); graph must reach the target state to play the corresponding clip.
Draw / Holster Lifecycle
| Event | RaiderRoot | WeaponBehavior | Effect |
|---|---|---|---|
weaponDraw |
fires | accepts | Start draw animation (hand to gun) |
weaponSheathe |
— | — | (WeaponBehavior may handle internally) |
readyStateEnter |
— | fires | Weapon drawn and ready to fire |
gunDownStateEnter |
— | fires | Weapon lowered (walking with gun holstered) |
gunDownStateExit |
— | fires | Exiting lowered state |
unEquip |
fires | — | End draw (return to unarmed) |
Fire / Attack
| Event | RaiderRoot | WeaponBehavior | Effect | Notes |
|---|---|---|---|---|
fireSingle |
fires | accepts | Single shot, hip-fire | Primary for non-ADS |
attackStart |
fires | accepts | Generic attack start (melee also uses) | May be melee fallback |
attackStartAuto |
fires | — | Auto-fire start | Hold-to-fire weapons |
attackStartOver |
— | ? | Attack overflow / dual-wield? | TBD |
attackStartSlave |
fires | — | Upper-body-only fire overlay (while moving) | Combines with locomotion |
attackRelease |
fires | — | End attack (auto-fire release) | Holds until received |
weaponFire |
— | — | (Internal annotation; not an event) | Marks fire frame in clips |
Sighted / ADS
| Event | Status | Role |
|---|---|---|
sightedStateEnter |
TBD | ADS enter |
sightedStateExit |
TBD | ADS exit |
Defer ADS until gun draw + single-shot fire are stable.
Weapon Clip Categories
From F4-Animation-Research extracted/Character/Animations/:
Shared (All guns)
| Clip | Use |
|---|---|
WPNEquip |
Draw animation |
WPNIdleReady |
Idle, gun drawn |
WPNIdleGunDown |
Idle, gun holstered but equipped |
WPNIdleSighted |
Idle, aiming down sights |
WPNFireSingleReady |
Fire animation, hip |
WPNFireAutoReady |
Auto-fire loop, hip |
WPNFireSingleSighted |
Fire, aiming |
WPNReload |
Generic reload |
WPNWalkForwardReady |
Walk with gun ready |
WPNRunForwardReady |
Run with gun ready |
SneakWPN* |
Sneak with gun |
WPNGrenadeThrow |
Thrown weapon |
Per-Weapon Overrides (Animations/Weapon//)
| Folder | Examples | Use |
|---|---|---|
| 44Pistol, 10mm, Pistol | WPNAssemblyPose, WPNFireSingle*Slave |
Grip and fire pose (pistols hold differently than rifles) |
| HuntingRifle, CombatShotgun | Per-weapon-specific fire, reload | Shoulder-fired weapon animations |
| LaserRifle, PlasmaRifle | Per-type variants | Energy weapons (different recoil, charge-up anims) |
| Minigun | WPNMeleeShredder, charge-up |
Spin-up and charging |
| GaussRifle, ChargeWeapons | WPNChargeUp, WPNBoltCharge |
Charge mechanics |
Phase 1 Validation Checklist
Testing on local player (to observe what graph vars actually change when playing animations):
- Draw weapon (right-hand equipped)
- Observe: Which graph vars flip? Which
NotifyAnimationGraphImpl()calls returngraphAccepted=true? - Expected:
iSyncGunDown→ 0,readyStateEnterfires,WPNIdleReadyplays
- Observe: Which graph vars flip? Which
- Holster weapon (lower gun while keeping equipped)
- Expected:
iSyncGunDown→ 1,gunDownStateEnterfires,WPNIdleGunDownplays
- Expected:
- Fire single shot (hip-fire)
- Expected:
fireSinglefires,WPNFireSingleReadyplays,isFiringflips
- Expected:
- Walk / run with gun drawn
- Expected: armed locomotion clips (
WPNWalk*,WPNRun*) play; speed graph var scales movement
- Expected: armed locomotion clips (
- Log output in
CommonwealthOnline.logshould show var names and event accept/reject
Testing on proxy with test weapon equipped (temporary dev code):
- Equip test weapon on proxy actor
- Manually fire same events as local player
- Verify proxy enters same FSM states and plays same clips
- Confirm WeaponBehavior graph is active (check logs for which behavior is managing animation)
Exit Criteria:
Create a small reference table in this file (update below) with confirmed:
- Graph variable names, types, and observed value ranges
- Event names that return
graphAccepted=trueon proxy with weapon equipped - Any variables/events that failed or misbehaved
- Notes on clip naming for armed locomotion
Validation Results
To be filled after Phase 1 testing
Confirmed Variables
| Variable | Type | Values | Notes |
|---|---|---|---|
| (pending) | — | — | — |
Confirmed Events
| Event | Graph Accepted | Notes |
|---|---|---|
| (pending) | — | — |
Observed Issues
(none yet)
Integration Notes (for later phases)
Protocol Fields
rightHand: { slot: "rightHand", formId: "0001F4A6" }— Equipped WEAP form IDweaponDrawn: true/false— Is weapon ready to fire (draw state;iSyncGunDown=0)actionEvents[].eventName— Fire events:"fireSingle","attackStart"(discrete actions)
Proxy Animation Apply Order (per frame)
- Equip weapon (if
rightHand.formIdchanged) → Forces behavior graph reload - Apply draw state (write
iSyncGunDownbased onweaponDrawn) - Fire draw/holster events (if
weaponDrawnedge-triggered) - Apply locomotion (existing Speed/Sprint/Sneak logic)
- Fire locomotion events (existing moveStart/moveStop/etc.)
- Replay action events (fire
fireSingleif queued)
Known Gaps (TBD in later phases)
- ADS / sighted state
- Auto-fire hold duration
- Power armor weapon behaviors
- Melee weapons (separate graph: MeleeBehavior)
- Weapon equip/unequip animations for left hand and off-hand