# MECHMPPR.CPP / .HPP — reconstruction notes `MechControlsMapper` (: Subsystem) is the mech's control-input subsystem, installed at roster slot 0 via `Mech::SetMappingSubsystem`. It publishes the control-input attributes (StickPosition..PilotArray, IDs 3–0x16) that the streamed control mappings bind to, and — as of Phase 5.3 — interprets those raw inputs into the locomotion/aim demands the mech drive consumes. ## Reconstructed - The attribute table + AttributeIndex + shared-data statics (earlier wave). - The ctor: primes the published inputs to neutral and (Phase 5.3) installs `InterpretControls` as the per-frame Performance. - `InterpretControls(Scalar)` — the per-frame control interpretation (mechmppr.cpp @004afd10, authentic demand math): - throttle → forward speed: `speedDemand = topSpeed · throttle · fwdScale` (reverse thrust inverts and drops the forward scale). `topSpeed`/`walkSpeed` are read from the owner via `Mech::GetReverseStrideLength()/GetWalkStrideLength()`. - soft response: square the stick yaw (sign preserved), cube the pedals. - Basic mode: stick yaw = `turnDemand`; Standard/Veteran: pedals = `turnDemand`. - speed clamp while turning hard (`max_turn` ramps topSpeed → walkSpeed by |turnDemand|); VeteranMode has no clamp. - Demand accessors `GetSpeedDemand()/GetTurnDemand()` (read by `Mech::Simulate`). - `GetMech()` = `(Mech *)GetEntity()`. The mapper ticks in the engine's `Entity::PerformAndWatch` roster walk (slot 0), which runs BEFORE the mech's own Performance (`Simulation::PerformAndWatch` at the tail), so the demands are same-frame — no input latency. ## DEV hook (headless verification) `BT_FORCE_THROTTLE` / `BT_FORCE_TURN` override the pushed raw inputs (the RIO/ keyboard aren't present in the headless smoke test), so the demand math + mech drive are exercisable without hardware. `BT_MECH_LOG` prints a 1 Hz `[mppr]` demand trace. Verified: `throttle=1.0` → speedDemand=30; `throttle=0.3,turn=1.0` → the mech walks a circle; neutral → 0. See MECH.NOTES.md (Phase 5.3 inc 2). ## Torso aim wired (2026-07-21) InterpretControls now routes the stick PITCH (`stick_y`, squared soft response) into the torso weapon-elevation axis every control mode (`Torso::SetAnalogElevationAxis`), and in Standard/Veteran the stick YAW into the torso twist (`SetAnalogTwistAxis`); Basic keeps the stick yaw as the leg turn. `Torso::TorsoSimulation` slews + clamps the elevation/twist (see TORSO.NOTES.md). Verified: `BT_FORCE_ELEV=0.8` → torsoElev clamps at the authentic 20° limit. ## Look-button state machine wired (2026-07-21) The five-state LOOK machine is live: `LookState` enum + `lookState`/ `previousLookState` members; each frame InterpretControls picks the state from the look buttons (left/right/behind/down, priority in that order) and on a CHANGE calls `Mech::CommitLookState(state)`, which re-aims the eyepoint from the mech's authored look angles (see MECH.NOTES.md increment 6). `BT_FORCE_LOOK=<1..4>` dev hook. Verified: look-behind commits yaw=π once and the per-frame eyepoint compose carries it with the live elevation. ## Deferred (the free-aim / camera wave) Still not reconstructed: the HUD free-aim slew (`HUD::SetFreeAimSlew`, the Standard/Veteran torso-disabled path), the torso recenter command, and the weapon-side half of the look commit (per-view fire enables + HUD pip group mask — needs the MechWeapon viewFireEnable/rearFiring members). The skeleton-joint application of the torso angles is deferred with the render wave (TORSO.NOTES.md).