Captures the @004abb40 decode (base head + Mover-family branch with the separating gate and mech-vs-mech ram + CulturalIcon branch with the 0x8000 stopping flag and the 0.00123f walk-through sentinel + the material tail) before implementation, so the analysis survives session boundaries. Also records two hazards BT411 fought that do NOT apply to this engine -- the compounded-reflection economy guard (our ProcessCollisionList restores velocity per contact, MOVER.CPP:1203) and the AlarmIndicator ODR split -- plus the ledger of master-perf pieces currently re-hosted in Mech::Simulate at STAGED seams, for the day mech4.cpp exists and they move home. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
4.7 KiB
MECH4 — pre-TU reconstruction notes
Status: no MECH4.CPP exists yet. The ground snap, frame rejection,
knockdown stagger and collision economy that the binary keeps in mech4's
master performance are currently RE-HOSTED inside Mech::Simulate
(MECH, 5.3.98–100) at seams marked STAGED. This file carries the decode
work for the pieces not yet written, so it survives session boundaries.
Mech::ProcessCollision (@004abb40) — decoded, not yet reconstructed
The override of the engine's protected virtual (MOVER.CPP:1354), called
per contact by Mover::ProcessCollisionList. The decomp
(part_012.c:15206–15416) reads as the BASE function plus four additions:
-
The base head, verbatim:
collisionVolume->ProcessCollision(collision, worldLinearVelocity, lastCollisionList, &damage->surfaceNormal, &penetration); on a miss NOTHING runs. Clamp penetration to the slice, ratio = pen/dt,damage->damageAmount = StaticBounce(old, dt, r, normal, &elasticity, minimumBounceSpeed, &friction)with the elasticity/friction locals seeded from the mover's coefficients. -
The Mover-family branch (owner = the collided solid's owner entity, solid+0x1c; family test FUN_0041a1a4 against the "Mover" derivation GUID @0x4e4518):
- SEPARATING-CONTACT GATE:
(ourWorldVel − other->WorldVel[vtbl+0x20]) · normal < −1e-4(_DAT_004ac044) → return, no damage, no dispatch. - If the other's classID == 0xbb9 (mech), build a TakeDamage message
(raw wire shape
{id, len, inflictor = DAT_0050b9ac global, zone −1, the Damage verbatim}) and Dispatch it AT THE OTHER — the mech-vs-mech ram. Use ourEntity::TakeDamageMessagector as the weapon path does.
- SEPARATING-CONTACT GATE:
-
The CulturalIcon branch (GUID @0x4e7038):
stopping = other->instanceFlags & 0x8000(the StoppingCollisionVolume flag, entity+0x28).- Same separating gate against a ZERO other-velocity (icons are static).
- Dispatch the crunch TakeDamage at the icon (crushable props have no zones → their base handler no-ops it, but the dispatch is real).
- If NOT stopping:
damage->damageAmount = 0.00123f(bits 0x3aa137f4) — the WALK-THROUGH SENTINEL. The caller (the response block in Simulate) must treat exactly 0.00123f as "the move stands": restore the post-snap saves, zero the amount, feed the gyro crunch (torque 0.4 along the normalized force, upward impulse 0.2 — binary @4aa81e/@4aa86c).
-
The material tail: the elasticity/friction OUT values from StaticBounce are compared against
_DAT_004ac048; setscollisionTemporaryState(+0x44c) to 1, or 2 when both match and the state was 0. The state is pushed into thecollisionStateStateIndicator once per frame by the response block (0→1 fires the impact sound). Needs the_DAT_004ac048constant identified before writing (likely the default-material coefficient — check the literal pool at 0x4ac048).
Two hazards the donor fought that DO NOT apply here
- Compounded StaticBounce reflections: our engine's
Mover::ProcessCollisionList(MOVER.CPP:1203) restoresworldLinearVelocity = initial_velocityand position PER CONTACT before each ProcessCollision call, and averages the results. The port'sframeEntryWorldVelocityeconomy guard has no counterpart hazard in this engine — do not import it. - The AlarmIndicator ODR split: a port-only problem; our tree reads
MovementMode()/ the alarms directly.
Already re-hosted in Mech::Simulate (move here when mech4.cpp exists)
| piece | binary | landed |
|---|---|---|
| ground probe + snap | @4aa630–4aa6cc | 5.3.98 |
| frame rejection + crash self-damage + knockdown | @4aa6cf–4aab0b | 5.3.99 |
| collision economy divert + distributor | @0x4a0368 → @0049ffcc | 5.3.100 (in the damage hub, where the binary has it) |
| status→mode limp promotion | master perf (un-decompiled) | 5.3.97, STAGED |
| forwardCycleRate re-pick (ground/airborne) | IntegrateMotion head | partially — the ctor sets it once; the per-frame re-pick needs +0x3f4 |
Still to decode
FUN_004a9b5c— the master performance. Ghidra never decompiled it (objdump territory). Owns: the turn-in-place dispatcher (arms state 4 on both channels in lockstep), the status→mode promotion, likely therunSpeedMax(+0x7a0) writer, the gyro rumble timer.@004ab430ReplicantPerformance (1432B) — the replicant-side interior.@004ab1c8IntegrateMotion — decoded (see 5.3.95 notes) but only partially re-hosted: the local-velocity/orientation integration and the dead-reckon latency fold (+0x778/+0x77c) remain.+0x598is a Point3D (its replicant branch writes it with a vector subtract), somotionEventNamein MECH.HPP is mistyped as CString — fix when this lands.