Torso elevation (pitch aim) wired: the pod stick's Y axis lives
The mechs could always tilt their aim up/down -- Torso models the full vertical axis (currentElevation, rate, VerticalLimitTop/Bottom, recenter) and EVERY 1995 control mode routes stickPosition.y into Torso::SetAnalogElevationAxis -- but the desktop bridge hard-zeroed stick Y, so the axis was dead on a keyboard rig. The one pod control the remap left unwired. - btinput: JoystickY axis -> elevTarget/elevActive/elevAbsolute - mech4 shim: sElev integrator (same walk/spring model as the twist; X recenters pitch too via gBTElevRecenter) - mechmppr bridge: feeds stickPosition.y every bridged frame (the old unconditional zero removed); both mode branches covered - CONTROLS.MAP (+ numpad profile + compiled default): R/F = aim up/down, pad LeftStickY = elevation (was unused) - torso.hpp: CurrentElevation()/ElevationVelocity() accessors (diag) - [mppr] trace gains stickY (note: the trace reads AFTER the next frame's device push re-zeroes the stick -- input flows regardless) Verified live: R held -> torso elevation climbs at the authored rate and clamps at 0.349066 rad = exactly 20.0 deg (the Blackhawk's VerticalLimitTop); release holds the aim. The eyepoint correctly stays level -- pitch aims the GUNS and reads on the HUD's vertical elevation tape, as in the pod. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
0a77d8e54b
commit
1271d3bc76
@@ -46,7 +46,8 @@
|
||||
# ---- WASD CLASSIC (the shipped default) ----------------------------------
|
||||
|
||||
# Driving: W/S sweep the throttle lever (sticks, detent at zero); A/D are
|
||||
# the turn pedals (spring back); Q/E twist the torso; X = all stop.
|
||||
# the turn pedals (spring back); Q/E twist the torso; R/F aim the torso
|
||||
# up/down (elevation); X = all stop (recenters twist AND pitch).
|
||||
key W axis Throttle rate 0.7
|
||||
key S axis Throttle rate -0.7
|
||||
key Up axis Throttle rate 0.7
|
||||
@@ -57,6 +58,8 @@ key Left axis LeftPedal deflect 1
|
||||
key Right axis RightPedal deflect 1
|
||||
key Q axis JoystickX deflect -1
|
||||
key E axis JoystickX deflect 1
|
||||
key R axis JoystickY deflect 1
|
||||
key F axis JoystickY deflect -1
|
||||
key X action AllStop
|
||||
|
||||
# Fire: the pod joystick's four buttons.
|
||||
@@ -83,6 +86,7 @@ key F9 action Reconnect
|
||||
# Left stick steers (the pedals), right stick twists the torso and pushes
|
||||
# the throttle lever; triggers fire.
|
||||
padaxis LeftStickX axis Pedals deadzone 0.24
|
||||
padaxis LeftStickY axis JoystickY deadzone 0.24
|
||||
padaxis RightStickX axis JoystickX deadzone 0.24
|
||||
padaxis RightStickY axis Throttle rate 0.75 deadzone 0.24
|
||||
pad RightTrigger button 0x40 # Main
|
||||
|
||||
@@ -21,6 +21,8 @@ key NumPad4 axis LeftPedal deflect 1 # turn left
|
||||
key NumPad6 axis RightPedal deflect 1 # turn right
|
||||
key NumPad7 axis JoystickX deflect -1 # torso twist left
|
||||
key NumPad9 axis JoystickX deflect 1 # torso twist right
|
||||
key Home axis JoystickY deflect 1 # torso aim up
|
||||
key End axis JoystickY deflect -1 # torso aim down
|
||||
key NumPad5 action AllStop
|
||||
key Shift axis Throttle rate 0.75 # throttle up (alt)
|
||||
key Ctrl axis Throttle rate -0.75 # throttle down (alt)
|
||||
@@ -82,6 +84,7 @@ key OemCloseBrackets button 0x30 # hotbox
|
||||
|
||||
# ---- Xbox controller (same as the default profile) ----------------------
|
||||
padaxis LeftStickX axis Pedals deadzone 0.24
|
||||
padaxis LeftStickY axis JoystickY deadzone 0.24
|
||||
padaxis RightStickX axis JoystickX deadzone 0.24
|
||||
padaxis RightStickY axis Throttle rate 0.75 deadzone 0.24
|
||||
pad RightTrigger button 0x40
|
||||
|
||||
@@ -44,7 +44,10 @@ press = `buttonGroup[a].Update(a+1, modeMask)` (mask saved), release = `Update(-
|
||||
button <addr>|axis <axis> deflect|rate <n>|keypad pilot|external <0-15>|pckey <char>|action
|
||||
<name>`; `pad <button>` same targets; `padaxis <src> axis ... [invert] [deadzone d] [rate n]`.
|
||||
Axes: Throttle (lever, rate-walks + sticks), LeftPedal/RightPedal/Pedals (turn, springs),
|
||||
JoystickX (torso twist). Emissions mirror the RIO conventions above exactly; the four fire
|
||||
JoystickX (torso twist), **JoystickY (torso ELEVATION — pitch aim; every 1995 control mode
|
||||
routes it to Torso::SetAnalogElevationAxis; keys R/F + pad LeftStickY in the default map;
|
||||
verified to the authentic VerticalLimitTop clamp, 20° on the Blackhawk; aims the GUNS — reads
|
||||
on the HUD elevation tape, the eyepoint stays level)**. Emissions mirror the RIO conventions above exactly; the four fire
|
||||
buttons (0x40/45/46/47) publish as levels to the bring-up fire channels instead of buttonGroup
|
||||
(avoids double-fire once the streamed ChooseButton mappings are exercised). XInput loads
|
||||
dynamically (xinput1_4 → 9_1_0; disconnected-pad probing rate-limited to 1 Hz). **Keys claimed by
|
||||
|
||||
@@ -47,7 +47,7 @@ enum BTAxisID
|
||||
BTAxisRightPedal,
|
||||
BTAxisPedals, // signed convenience alias: + = right pedal
|
||||
BTAxisJoystickX, // the pod stick X = torso twist (Standard mode)
|
||||
BTAxisJoystickY, // parsed + tracked; no consumer yet
|
||||
BTAxisJoystickY, // the pod stick Y = torso ELEVATION (pitch aim)
|
||||
BTAxisCount
|
||||
};
|
||||
|
||||
@@ -240,6 +240,8 @@ static const char *sDefaultProfile =
|
||||
"key Right axis RightPedal deflect 1\n"
|
||||
"key Q axis JoystickX deflect -1\n"
|
||||
"key E axis JoystickX deflect 1\n"
|
||||
"key R axis JoystickY deflect 1\n"
|
||||
"key F axis JoystickY deflect -1\n"
|
||||
"key X action AllStop\n"
|
||||
"key D1 button 0x40\n"
|
||||
"key Space button 0x40\n"
|
||||
@@ -258,6 +260,7 @@ static const char *sDefaultProfile =
|
||||
"key F8 action Generator4\n"
|
||||
"key F9 action Reconnect\n"
|
||||
"padaxis LeftStickX axis Pedals deadzone 0.24\n"
|
||||
"padaxis LeftStickY axis JoystickY deadzone 0.24\n"
|
||||
"padaxis RightStickX axis JoystickX deadzone 0.24\n"
|
||||
"padaxis RightStickY axis Throttle rate 0.75 deadzone 0.24\n"
|
||||
"pad RightTrigger button 0x40\n"
|
||||
@@ -953,6 +956,14 @@ void
|
||||
next.twistTarget = twist;
|
||||
next.twistActive = axisActive[BTAxisJoystickX];
|
||||
next.twistAbsolute = axisAbsolute[BTAxisJoystickX];
|
||||
// stick Y = torso ELEVATION (pitch aim) -- every 1995 control mode routes
|
||||
// it to Torso::SetAnalogElevationAxis (mechmppr InterpretControls)
|
||||
float elev = axisDeflect[BTAxisJoystickY];
|
||||
if (elev > 1.0f) elev = 1.0f;
|
||||
if (elev < -1.0f) elev = -1.0f;
|
||||
next.elevTarget = elev;
|
||||
next.elevActive = axisActive[BTAxisJoystickY];
|
||||
next.elevAbsolute = axisAbsolute[BTAxisJoystickY];
|
||||
next.leverRate = axisRate[BTAxisThrottle];
|
||||
|
||||
gBTInput = next;
|
||||
|
||||
@@ -34,8 +34,11 @@ struct BTInputState
|
||||
int turnActive; // any turn input held (else spring-center)
|
||||
float twistTarget; // torso-twist deflection target [-1,1]
|
||||
int twistActive;
|
||||
float elevTarget; // torso-elevation (pitch) target [-1,1]
|
||||
int elevActive;
|
||||
int turnAbsolute; // pad stick overrides the integrator outright
|
||||
int twistAbsolute;
|
||||
int elevAbsolute;
|
||||
|
||||
// the four pod joystick fire buttons (levels)
|
||||
int fireTrigger; // 0x40 Main
|
||||
|
||||
@@ -654,6 +654,8 @@ static int gBTPinkyKey = 0; // key '4' = the pod's 4th fire butto
|
||||
int gBTModeCycle = 0; // 'M' edge: cycle the control mode (mapper consumes)
|
||||
int gBTLookBehind = 0; // 'V' held: the pod's rear-view button (task #68)
|
||||
float gBTTwistAxis = 0.0f; // Q/E torso-twist deflection (assisted-mode stick X)
|
||||
float gBTElevAxis = 0.0f; // R/F torso-elevation (pitch aim, stick Y)
|
||||
int gBTElevRecenter = 0; // X edge: zero the pitch axis
|
||||
int gBTTorsoRecenter = 0; // 'X' edge: pulse the authentic torso recenter (mapper consumes)
|
||||
static int gBTConfigKey = 0; // task #6: HOLD 'G' = the weapon-configure button
|
||||
static int gBTGenSelKey = 0; // task #12: F5..F8 = SelectGeneratorA..D, F9 = mode toggle
|
||||
@@ -2625,9 +2627,57 @@ void
|
||||
{
|
||||
sTwist = 0.0f;
|
||||
gBTTorsoRecenter = 1; // mapper consumes -> CommandRecenter()
|
||||
{
|
||||
extern int gBTElevRecenter;
|
||||
gBTElevRecenter = 1; // pitch axis zeroes below
|
||||
}
|
||||
}
|
||||
sPrevXT = xtNow;
|
||||
gBTTwistAxis = sTwist;
|
||||
|
||||
// TORSO ELEVATION (pitch aim -- the pod stick's Y
|
||||
// axis; every 1995 control mode routes it to
|
||||
// Torso::SetAnalogElevationAxis). Same integrator
|
||||
// model as the twist: keys walk the axis, release
|
||||
// springs the RATE to 0 (position holds, the sim's
|
||||
// vertical limits clamp); a pad stick is absolute.
|
||||
{
|
||||
extern float gBTElevAxis;
|
||||
static float sElev = 0.0f;
|
||||
if (gBTInput.elevAbsolute)
|
||||
{
|
||||
sElev = gBTInput.elevTarget;
|
||||
}
|
||||
else if (gBTInput.elevActive)
|
||||
{
|
||||
sElev += gBTInput.elevTarget * kStickRate * dt;
|
||||
if (sElev > 1.0f) sElev = 1.0f;
|
||||
if (sElev < -1.0f) sElev = -1.0f;
|
||||
}
|
||||
else if (sElev != 0.0f)
|
||||
{
|
||||
const float estep = kStickCenterRate * dt;
|
||||
if (sElev > estep) sElev -= estep;
|
||||
else if (sElev < -estep) sElev += estep;
|
||||
else sElev = 0.0f;
|
||||
}
|
||||
extern int gBTElevRecenter; // set by the X edge above
|
||||
if (gBTElevRecenter)
|
||||
{
|
||||
gBTElevRecenter = 0;
|
||||
sElev = 0.0f; // X recenters pitch too
|
||||
}
|
||||
gBTElevAxis = sElev;
|
||||
if (getenv("BT_INPUT_LOG"))
|
||||
{
|
||||
static float s_eacc = 0.0f; s_eacc += dt;
|
||||
if (s_eacc >= 1.0f) { s_eacc = 0.0f;
|
||||
DEBUG_STREAM << "[input] elev tgt="
|
||||
<< gBTInput.elevTarget << " act="
|
||||
<< gBTInput.elevActive << " axis="
|
||||
<< sElev << "\n" << std::flush; }
|
||||
}
|
||||
}
|
||||
}
|
||||
// gBTDrive.fire = "any weapon trigger down" (feeds the bring-up
|
||||
// damage dispatcher + the beam-visual keepalive)
|
||||
@@ -3158,6 +3208,7 @@ void
|
||||
<< " pre=" << preThrottle
|
||||
<< " rev=" << mppr->reverseThrust
|
||||
<< " stickX=" << mppr->stickPosition.x
|
||||
<< " stickY=" << mppr->stickPosition.y
|
||||
<< " -> speedDemand=" << mppr->speedDemand
|
||||
<< " turnDemand=" << mppr->turnDemand
|
||||
<< " mode=" << mppr->controlMode
|
||||
|
||||
@@ -719,6 +719,14 @@ void
|
||||
gBTModeCycle = 0;
|
||||
CycleControlModeNow();
|
||||
}
|
||||
// TORSO ELEVATION (pitch): the pod stick's Y axis -- every
|
||||
// control mode routes stickPosition.y into
|
||||
// Torso::SetAnalogElevationAxis below, so the bridge feeds
|
||||
// it in BOTH branches (keys R/F or a pad stick via btinput).
|
||||
{
|
||||
extern float gBTElevAxis;
|
||||
stickPosition.y = gBTElevAxis;
|
||||
}
|
||||
if (controlMode == BasicMode)
|
||||
{
|
||||
stickPosition.x = key_turn;
|
||||
@@ -751,7 +759,8 @@ void
|
||||
}
|
||||
}
|
||||
}
|
||||
stickPosition.y = 0.0f;
|
||||
// (stickPosition.y no longer zeroed here -- the bridge above
|
||||
// feeds the elevation axis every bridged frame, 2026-07-18)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,6 +831,15 @@ void
|
||||
{
|
||||
torso->SetAnalogElevationAxis(stick_y); // raw torso+0x1f4 (500)
|
||||
torso->SetAnalogTwistAxis(0.0f); // raw torso+0x1f0
|
||||
if (getenv("BT_INPUT_LOG"))
|
||||
{
|
||||
static float s_eacc2 = 0.0f; s_eacc2 += time_slice;
|
||||
if (s_eacc2 >= 1.0f) { s_eacc2 = 0.0f;
|
||||
DEBUG_STREAM << "[input] mppr elev in=" << stick_y
|
||||
<< " torsoElev=" << torso->CurrentElevation()
|
||||
<< " vel=" << torso->ElevationVelocity()
|
||||
<< "\n" << std::flush; }
|
||||
}
|
||||
}
|
||||
if (cockpit)
|
||||
{
|
||||
|
||||
@@ -171,6 +171,10 @@ class Joint; // engine skeleton node (JOINT.h); the twist target
|
||||
// Address of the twist scalar (task #56: the binary bt_mech stream tail
|
||||
// re-points gyro+0x258 to torso+0x1D8; the gyro damage-response reads it).
|
||||
Scalar* CurrentTwistAddr() { return ¤tTwist; }
|
||||
// Current vertical (pitch) torso aim in radians (binary torso+0x1e4) --
|
||||
// elevation-axis bring-up diagnostics (2026-07-18).
|
||||
Scalar CurrentElevation() const { return currentElevation; }
|
||||
Scalar ElevationVelocity() const { return elevationVelocity; }
|
||||
protected:
|
||||
// Resolve a named skeleton node to its live Joint* via the owning Mech
|
||||
// (the ctor @004b6b0c inlines Mech::ResolveJoint == FUN_00424b60). Defined
|
||||
|
||||
Reference in New Issue
Block a user