Went to source animationClips[] and found two things: a bug in what 5.3.91
committed, and a naming trap that has already cost BT411 a shipped defect.
THE BUG, MINE. I sized animationClips[AnimationCount] -- 0x1d, from the enum.
Wrong. The name table stops at 0x1d but the ARRAY does not: slot 0x20
(mech+0x64c) is the bump/crash clip the mech binds on a hard wall impact. So
the array is [AnimationSlotCount] = 0x21 and Set*Animation's Verify bounds
against that instead. Sizing a real array off a name table that stops earlier
reads fine and corrupts whatever sits next door; caught by reading the clip
loader, not by the compiler.
THE SLOT MAP, recovered from LoadLocomotionClips and now written down in full
(suffix, meaning, and which measured constant each clip yields):
5 swr stand -> walk standSpeed
6/7 wwr/wwl forward walk CYCLE walkStrideLength = (s6+s7)/(d6+d7)
8/9 wsr/wsl walk -> stand
10/11 wrr/wrl walk -> run reverseSpeedMax
12/13 rrr/rrl run CYCLE reverseStrideLength
14/15 rwr/rwl run -> walk
16/17 sbr/sbl stand -> back gimpSpeedMax
18/19 bbr/bbl reverse CYCLE gimpStrideLength (NEGATED here)
20/21 bsr/bsl back -> stand
22/23 wgl/wgr walk -> limp gimpLeft/RightSpeedMax
24/25 ggr/ggl limp CYCLE gimpLeft/RightStrideLength
26/27 gsl/gsr limp -> stand
0x20 bmp bump / crash stagger
THE TRAP: THE "gimp*" MEMBERS ARE THE REVERSE FIGURES, NOT THE LIMP ONES.
gimpSpeedMax and gimpStrideLength are measured from sbr and bbr/bbl -- the
reverse gait. The real limp has its own gimpLeft*/gimpRight* pair. This is
the same bad naming that produced the states-16-19 misreading recorded in
5.3.91, and it has now caused the same error twice from two directions.
Also settled: gimpStrideLength's negative sign is applied AT MEASUREMENT, not
authored into the data -- which is where the fold in the transition machines
comes from. And the limp clips are OPTIONAL: the loader probes for wgl and
leaves hasGimpClips 0 with slots 22-27 unfilled if the model lacks it, so the
deferred gimp branch must check that before routing into the limp machine.
THE ENUM IS NOT THE SLOT MAP, and MECH.HPP now says so at the enum itself.
The names are verbatim from the binary and authoritative AS NAMES, but slot
0x0e takes the run-to-walk clip while the table calls it RightReverseAnimation,
and the forward walk alternates 6/7 rather than the pair the WalkForward names
suggest. Read the slot map for "what does this play"; read the enum for "what
did the original call this index".
ATTRIBUTION NOTE: the four clip helpers (ResolveAnimationClip @004a7f50,
MeasureClipStride @004a8054, LoadLocomotionClips @004a80d4,
LoadLocomotionClipsExt @004a86c8) are exactly the four addresses the manifest
lists under mech2.cpp that BT411 files under mech3. The manifest's attribution
comes from the binary's own file tagging, so they belong here -- which also
accounts for all 12 of mech2's functions.
BT 51/51. Still nothing calls the gait.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>