BT410 5.3.110: the gyroscope lives -- the cockpit's springs, the hit bounce, and the crunch, all wired

The feel wave's cornerstone, transcribed from the task-#56 byte-exact donor
per the GYRO.NOTES.md plan:

  THE SPRINGS.  IntegrateEyeJoint (@004b2ec0): the eye TRANSLATION spring
  whose equilibrium (posSpring+negSpring)/2 IS the authentic steady eye
  offset, with the byte-verified quirks intact -- the damping step
  OVERWRITES the force accumulator (it carries last frame's damping and
  the damage impulses by design) and the position step has NO dt.
  IntegrateBody (@004b30ec): the body ROTATION spring, X/Z-crossed on the
  spring force and crossed AGAIN on the orientation step.

  THE SIM (@004b275c): chain the power watch (5.3.109's mirrors), slew the
  sway angle between the powered and impaired percentages -- impaired reads
  the gyro's OWN mirrored alarms: watchdog != Ready or heat == Failure --
  band-clamp, run both integrators.  The Performance ends there.

  THE JOINT WRITES (@004b33e0/@004b34ec) live where the binary calls them:
  the MECH master-perf tail after the gait pass, death-gated -- the idle
  sway onto the EyeJoint, and TRANSLATION <- eyePosition + ROTATION <-
  bodyOrientation onto 'jointeye', the BallTranslation joint the cockpit
  eyepoint rides.  Every write QuantiseEps-gated.

  THE HIT BOUNCE (@004b2980): every non-collision hit shakes the cockpit.
  Direction from the damage force (random horizontal when ~zero), rotated
  into the yaw-only torso frame, per-type priced amount/multiplier*response
  (Explosive alone reads burstCount), clamped 1.3 UPPER only, then the four
  kicks -- impulse, torque (which zeroes .y and negates itself), the fixed
  up-axis vibration, and the vertical mirror.  Fed from the damage hub's
  step 1, BEFORE zone resolution -- an invalid-zone hit still shakes you.

  THE CRUNCH: driving through a crushable prop now kicks the gyro (torque
  0.4 along the contact normal, upward impulse 0.2) -- the 5.3.102 staged
  site, closed.

Resource: the five DamageResponse quads {trans,pitchRoll,yaw,vibration}
appended after the multipliers (record 0x21C, binary-verified layout) --
they were always in the stream; we simply never read them.  The ctor now
zeroes every accumulator (the donor's history records a NaN poison from
exactly that omission), copies the clamp pairs (body doubled), self-points
externalPitchPtr at spare0 until a torso binds it, and REGISTERS the
Performance on the master -- it ticks live, no fault.

Stub census: 19 across 13 files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-08-03 16:42:56 -05:00
co-authored by Claude Fable 5
parent 38cce95641
commit 41fca98f85
5 changed files with 998 additions and 315 deletions
+36 -5
View File
@@ -1078,12 +1078,13 @@ void
Check(this);
Check(message);
if (gyroSubsystem != NULL && getenv("BT_MECH_LOG"))
//
// The RAW record feeds the gyro FIRST -- even an invalid-zone hit shakes
// the cockpit (binary hub order step 1).
//
if (gyroSubsystem != NULL)
{
DEBUG_STREAM << "[gyro] hit feed staged (type="
<< (int)message->damageData.damageType
<< " amt=" << message->damageData.damageAmount << ")"
<< endl << flush;
((Gyroscope *)gyroSubsystem)->ApplyDamageResponse(message->damageData);
}
lastInflictingID = message->inflictingEntity;
@@ -1613,6 +1614,19 @@ void
AdvanceLegAnimation(time_slice);
}
//
// The gyro's joint writes (binary master-perf tail @0x4aaf74/83, AFTER
// the animation pass): the idle sway onto the EyeJoint, and the
// integrated eye offset + body tip onto 'jointeye' -- the joint the
// cockpit eyepoint rides. Gated off during the death clips exactly as
// the tail is.
//
if (gyroSubsystem != NULL && MovementMode() < 5)
{
((Gyroscope *)gyroSubsystem)->WriteEyeJoint();
((Gyroscope *)gyroSubsystem)->WriteMechJoint();
}
//
// THE TURN-IN-PLACE DISPATCHER (master perf @0x4aa505-0x4aa588, decoded
// from raw disasm -- Ghidra never decompiled the function). From
@@ -2009,6 +2023,23 @@ void
localOrigin.linearPosition = post_snap_position;
localToWorld = localOrigin;
MoveCollisionVolume();
//
// The gyro CRUNCH (binary @4aa7ce-4aa871): torque 0.4 along the
// normalized contact force, upward impulse 0.2. The Normalize
// is unguarded in the binary too.
//
if (gyroSubsystem != NULL)
{
Vector3D
crunch_normal;
crunch_normal.Normalize(collision_damage.damageForce);
((Gyroscope *)gyroSubsystem)->ApplyDamageTorque(
crunch_normal.x, crunch_normal.y, crunch_normal.z, 0.4f);
((Gyroscope *)gyroSubsystem)->ApplyDamageImpulse(
0.0f, 1.0f, 0.0f, 0.2f);
}
collision_damage.damageAmount = 0.0f;
if (getenv("BT_MECH_LOG"))