context-system: complete migration -> CLAUDE.md is now a 160-line router (zero context lost)
Full migration of the 2236-line monolithic CLAUDE.md into the progressive-context knowledge graph (per spark-lesson / expert-seed.md), so the deep RE knowledge loads on-demand instead of every session. ZERO CONTEXT LOST: - docs/PROGRESS_LOG.md = the complete old CLAUDE.md, VERBATIM (byte-identical) -- the lossless safety net + the "full detail" quick-lookup fallback. - 18 context/*.md topic files (1343 lines) digest every section (§1-3 -> project-overview, §4 -> content-archives, §5 -> asset-formats/bgf-format, §5a -> source-completeness, §5b/§8 -> wintesla-port, §7/§10 -> locomotion, §10a -> build-and-run, §10b -> reconstruction-method, §10c -> combat-damage + reconstruction-gotchas, §10d -> subsystems, render notes -> rendering, gauges -> gauges-hud, MP -> multiplayer, §9 -> open-questions). - reference/glossary.yaml (53 terms). decomp-reference.md = the offsets/ClassIDs/addresses hub. CLAUDE.md (160 lines) = router: identity, answer/reason protocols, quick-lookup table, evidence tiers (T0 engine-truth / T1 decompiled+verified / T2 reconstructed+runtime / T3 guarded / T4 hypothesis), conventions + DO-NOT (the systemic bug classes), structure. Retains the load-bearing work directives (build recipe pointer, "keep current" mandate). Knowledge graph validates CLEAN (scratchpad/checkctx.py -- all [[links]] + quick-lookup + docs refs resolve; [[name]] -> topic file or glossary term). docs/*.md ledgers stay as the detailed logs; context/*.md are the curated digests that route into them. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1cd57ade85
commit
f914fc040a
@@ -0,0 +1,83 @@
|
||||
---
|
||||
id: locomotion
|
||||
title: "Locomotion — gait, the ground model, collision, shadow"
|
||||
status: established
|
||||
source_sections: "PROGRESS_LOG.md §7, §10 (gait/ground/collision/shadow); docs/P3_LOCOMOTION.md"
|
||||
related_topics: [asset-formats, decomp-reference, reconstruction-gotchas, combat-damage, rendering]
|
||||
key_terms: [RootTranslation, ground-model, SequenceController, MechControlsMapper, SLD, joint]
|
||||
open_questions:
|
||||
- "Authentic per-mech turn-rate constant (currently bring-up constant)"
|
||||
- "Body-callback gimp handlers (states 16-19); airborne callbacks"
|
||||
---
|
||||
|
||||
# Locomotion
|
||||
|
||||
Walking, the gait controller, the ground/collision model, and the shadow. All DEFAULT-ON now
|
||||
(`BT_GAIT_CUTOVER`, `BT_GAIT_SM`, `BT_COLLISION`, `BT_REAL_CONTROLS` — set `=0` to fall back). Full
|
||||
detail: `docs/P3_LOCOMOTION.md` + `docs/PROGRESS_LOG.md §7, §10`.
|
||||
|
||||
## Walk speed is animation-driven (not physics)
|
||||
Each `.ANI` has a `[RootTranslation]` where **`.z` = forward root SPEED** (world units/s). The
|
||||
engine `AnimationInstance::Animate(dt, move_joints)` integrates `movement += Δt·rootTrans.z` and
|
||||
moves the body that far → feet plant by construction (no stride constant; k=1). Idle anims have
|
||||
z=0. The `.MOD` physics governed thrust VEHICLES, NOT walk gait. [T1]
|
||||
|
||||
## The two-channel gait (real controls)
|
||||
The BT `SequenceController` (`seqctl.cpp`, from `SelectSequence@004277a8`+`Advance@0042790c`) drives
|
||||
locomotion. Under `BT_REAL_CONTROLS` two channels run:
|
||||
- **LEG channel** writes the skeleton JOINTS from the live demand (a local sim; its joint writes are
|
||||
overwritten by the body).
|
||||
- **BODY channel** is the DISPLAYED motion — travel comes from the SAME Advance that writes the
|
||||
displayed joints (`move_joints=1`), so display == travel BY CONSTRUCTION (v4 fix — killed the
|
||||
desync class). [T2]
|
||||
The gait STATE MACHINE (`AdvanceBodyAnimation`, mech2.cpp) slews `bodyCycleSpeed` toward the demand
|
||||
through walk/run caps (`LoadLocomotionClips`, mech3.cpp:326 — measures `walkStride`/`standSpeed` via
|
||||
`legAnimation.SelectSequence`). Transition callbacks (`Mech::BodyClipFinished @0x4a6d8c`,
|
||||
`LegClipFinished @0x4a6928` — PE-parsed jump tables) alternate walk 6↔7 / run 12↔13 + walk→run. [T2]
|
||||
⚠ **Aliasing bug class (namedClip):** `namedClip[]`@0x5e0 == `animationClips[]`@0x5cc+0x14 (ONE array);
|
||||
`gimpBaseClip`@0x64c == `animationClips[0x20]`; `bodyAnimationState`@0x728 == `bodyStateAlarm.level`.
|
||||
Declared-separate members don't see each other's writes — alias them.
|
||||
|
||||
## The AUTHENTIC 1995 ground model (default-on, `BT_GROUND_REAL`)
|
||||
Decoded by the 10-agent `ground-model-decode` workflow (binary `FUN_004a9b5c` = the master perf).
|
||||
**NO GRAVITY anywhere** — accelerations zeroed every frame. Vertical position = an ABSOLUTE per-frame
|
||||
ground SNAP:
|
||||
1. ctor lifts `collisionTemplate->minY` by 5% of volume X-width (the probe height + wall-vs-floor separation).
|
||||
2. per frame `MoveCollisionVolume()` re-finds the containing node in the zone's **BoundingBoxTree**
|
||||
(BOXTREE.cpp — NOT a heightfield).
|
||||
3. probe `q = origin + (0, lift, 0)` → `FindBoundingBoxUnder(q, &h)` (h = distance down to the highest
|
||||
solid top; −1 = miss).
|
||||
4. snap gate `h > 1e-4`: `origin.y -= (h − lift)` ⇒ y = surfaceY exactly. **MISS ⇒ NOTHING** (y holds,
|
||||
no runaway). Up-slope bounded by the lift window (implicit step allowance); walk-offs drop instantly.
|
||||
5. `GetCurrentCollisions` → `ProcessCollisionList` → `Mech::ProcessCollision` (@0x4abb40, vtbl+0x3c):
|
||||
BoxedSolid resolver → StaticBounce → owner classification. Crushable icon (flags&0x8000) = damage
|
||||
0.00123f sentinel = move stands; damage>0 = **FULL FRAME REJECTION** (walls block, never slide);
|
||||
impactVel²>40 = crash-anim (SetLegAnimation(0x20)). [T2]
|
||||
KEY: `FindSmallestNodeContainingColumn`/`FindBoundingBoxUnder` (`FUN_0040e36c`/`0040e5f0`, BOXTREE.CPP)
|
||||
are ALIVE in the 2007 engine — the "heightfield" labels were wrong (caused two reverted attempts). A
|
||||
master mech needs a **CollisionAssistant** (GetCurrentCollisions iterates it unchecked). BT solids
|
||||
ship ZERO tiles (h never negative). [T2]
|
||||
|
||||
## Knockdown / crash + the desync/stutter fixes
|
||||
Wall impacts iv²>40 (~6.3 u/s) bind the `bmp` stagger clip. Two documented bug fixes: (a) the
|
||||
knockdown must stagger BOTH channels (`SetBodyAnimation(0x20)` + `SetLegAnimation(0x20)`) or display
|
||||
+ travel split permanently (foot-slip); (b) a contact-hysteresis gate (0.4 s `gBlockCooldown`)
|
||||
stops the knockdown re-firing on sustained/glancing contact. `localVelocity` is zeroed while crashed
|
||||
(spec-faithful) so a knocked mech can't keep advancing. [T2]
|
||||
|
||||
## Controls (`BT_REAL_CONTROLS`, default-on)
|
||||
`MechControlsMapper` (mechmppr.cpp @004afbe0; btl4mppr.cpp mappers) interprets input → `speedDemand`
|
||||
/ `turnDemand`. ⚠ **WndProc NEVER receives WM_KEYUP** (the engine's per-frame reader `GetMessage`s
|
||||
them out) → poll `GetAsyncKeyState` per frame, gated on foreground. Virtual controls: W/S sweep a
|
||||
persistent throttle LEVER with a zero detent; A/D a momentary auto-centering stick. [T2]
|
||||
|
||||
## Shadow (default-on, `BT_SHADOW_TILT`)
|
||||
BT 4.10's shadow is the flat `*_tshd.bgf` proxy drawn as blend-pass geometry, posed by `jointshadow`
|
||||
(terrain tilt) + `jointtshadow` (torso twist). Terrain-tilt samples the collision surface gradient;
|
||||
a depth-bias (`D3DRS_DEPTHBIAS`, decal-style) stops it z-fighting/vanishing on inclines. Polar maps
|
||||
have STUB `*_tshd` (shadow authored-off on snow). Also the visual-ground conform (`btvisgnd.cpp`,
|
||||
render-only lift to the visible terrain triangles — presentation only, never touches localOrigin). [T2]
|
||||
|
||||
## Key Relationships
|
||||
- Detail: `docs/P3_LOCOMOTION.md`. Uses: [[asset-formats]] (SKL/ANI), [[decomp-reference]] (offsets).
|
||||
- Feeds: [[combat-damage]] (collision→damage), [[rendering]] (shadow/visual-conform).
|
||||
Reference in New Issue
Block a user