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>
71 lines
4.3 KiB
Markdown
71 lines
4.3 KiB
Markdown
# GYRO.CPP — reconstruction notes
|
|
|
|
**Status: FULLY RECONSTRUCTED AND WIRED (2026-08-03). The simulation,
|
|
both integrators, both joint writes, all four damage hooks, and the three
|
|
feeds (damage hub, collision crunch, master-perf joint-write dispatch) are
|
|
live; the registered Performance ticks without fault. Deep verification --
|
|
the visible cockpit bounce under fire -- is an operator/rig item. Donor:
|
|
BT411 gyro.cpp (task #56 byte-exact).**
|
|
|
|
## Why this TU is the feel wave's cornerstone
|
|
|
|
The gyro owns the cockpit's physical feel: the eye TRANSLATION spring (the
|
|
steady eye offset + hit bounce, written to the 'jointeye' BallTranslation
|
|
joint that `siteeyepoint` rides) and the body ROTATION spring (the hull tip).
|
|
The 5.3.99 collision block's staged "gyro crunch" feed and the damage hub's
|
|
staged hit-bounce both land here.
|
|
|
|
## The transcription plan (all donor line refs gathered 2026-08-03)
|
|
|
|
1. **Members** (carve `dynamicsState[64]`): eyePosition/eyeVelocity/eyeForce/
|
|
eyeWork (Vector3D), bodyOrientation/bodyVelocity/bodyForce/bodyWork,
|
|
swayAngle/swayBias/swayVelocity/swayActive, placeRot/placePos,
|
|
workMatrix[12], externalPitchPtr (the torso-twist Scalar*), eyeJointNode/
|
|
mechJointNode (Joint*), damageResponse[5] {trans,pitchRoll,yaw,vibration},
|
|
vibrationDirection (fixed up axis). Clamps are ALIASES: eyeClampUpper ==
|
|
posSpring, eyeClampLower == negSpring; body likewise on the rotation pair.
|
|
2. **GyroscopeSimulation** (@004b275c): PowerWatcher::Simulation(dt); the
|
|
impaired pick (HeatModelOff || electrical != Ready || heat == FailureHeat)
|
|
selects percentageOnDestruction vs Normal + swayBias as the sway target;
|
|
slew by rotationPerSecond*dt with no-overshoot clamps, band-clamp into
|
|
[minAnimationNoise, maxAnimationNoise]; IntegrateEyeJoint; IntegrateBody.
|
|
The performance ENDS there — WriteEyeJoint/WriteMechJoint are called from
|
|
the MECH master perf tail (@0x4aaf74/83), i.e. our Simulate gait seam,
|
|
with the death/leg-anim gates.
|
|
3. **IntegrateEyeJoint** (@004b2ec0, byte-exact): both spring terms use
|
|
springConstant; damping OVERWRITES the force accumulator (carries into
|
|
next frame by design); position += velocity with NO dt; per-axis clamp
|
|
min-vs-posSpring then max-vs-negSpring.
|
|
4. **IntegrateBody** (@004b30ec): same shape, three quirks — spring force
|
|
X/Z-CROSSED (k.x*d.z, k.y*d.y, k.z*d.x); damping componentwise uncrossed;
|
|
orientation += velocity CROSSED again (x+=v.z, z+=v.x). Clamp vs the
|
|
rotation spring pair.
|
|
5. **WriteEyeJoint** (@004b33e0): swayAngle onto the EyeJoint node — scalar
|
|
channel scaled for hinge types <3, vector channel scaled for 4/5, write
|
|
only past QuantiseEps. **WriteMechJoint** (@004b34ec): 'jointeye' type-5
|
|
ONLY: SetTranslation(eyePosition) + SetRotation(EulerAngles from
|
|
bodyOrientation), each QuantiseEps-gated.
|
|
6. **Damage hooks**: ApplyDamageImpulse (negate dir, *exageration, +=
|
|
eyeForce); ApplyDamageTorque (same into bodyForce, then bodyForce.y = 0,
|
|
then whole-vector NEGATE); ApplyVerticalImpulse (x-only kick, .y mirrors
|
|
.x). **ApplyDamageResponse** (@004b2980, byte-exact): no-op on Collision
|
|
or zero amount; direction = damageForce or random-horizontal when ~0;
|
|
rotate into the yaw-only torso frame (externalPitchPtr) and re-normalize;
|
|
per-type scale amount/multiplier[type]*response[type].{4 terms}
|
|
(Explosive alone multiplies burstCount); clamp each at 1.3 UPPER only;
|
|
then the four kicks: impulse(dir,trans), torque(dir,pitchRoll),
|
|
vibration along vibrationDirection, vertical(yaw term).
|
|
7. **Wiring**: the damage hub's staged gyro feed (MECH.CPP
|
|
TakeDamageMessageHandler step 1) calls ApplyDamageResponse; the crushable
|
|
CRUNCH branch calls Torque(n,0.4)+Impulse(up,0.2) (already-shaped site);
|
|
Simulate's gait seam calls WriteEyeJoint+WriteMechJoint on the master
|
|
after the gait advances (death/leg gates per the binary tail).
|
|
8. **Family bridge**: Mech::DistributeCollisionDamage already references
|
|
Gyroscope::ClassDerivations directly — no ODR bridge needed in our tree.
|
|
|
|
## Verification plan
|
|
|
|
BT_GYRO_LOG prints the joint writes + NaN sentinel; a live arena run with
|
|
enemy fire should show [gyro-dmg] fan-outs and 'jointeye' translation motion
|
|
on the wire (the cockpit eye rides it — visible as view bounce on hits).
|