Files
TeslaRel410/restoration/source410/BT/MECH4.NOTES.md
T
CydandClaude Fable 5 3790262aad BT410 5.3.101: MECH4 pre-TU notes -- the ProcessCollision decode, two donor hazards that do not apply, and the re-hosting ledger
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>
2026-08-03 14:12:03 -05:00

86 lines
4.7 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.98100) 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:1520615416) reads as the BASE function plus four additions:
1. **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.
2. **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 our `Entity::TakeDamageMessage` ctor as the weapon path does.
3. **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).
4. **The material tail**: the elasticity/friction OUT values from
StaticBounce are compared against `_DAT_004ac048`; sets
`collisionTemporaryState` (+0x44c) to 1, or 2 when both match and the
state was 0. The state is pushed into the `collisionState` StateIndicator
once per frame by the response block (0→1 fires the impact sound). Needs
the `_DAT_004ac048` constant 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) restores
`worldLinearVelocity = initial_velocity` and position PER CONTACT before
each ProcessCollision call, and averages the results. The port's
`frameEntryWorldVelocity` economy 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 | @4aa6304aa6cc | 5.3.98 |
| frame rejection + crash self-damage + knockdown | @4aa6cf4aab0b | 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 the
`runSpeedMax` (+0x7a0) writer, the gyro rumble timer.
* `@004ab430` ReplicantPerformance (1432B) — the replicant-side interior.
* `@004ab1c8` IntegrateMotion — 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. **`+0x598` is a Point3D**
(its replicant branch writes it with a vector subtract), so
`motionEventName` in MECH.HPP is mistyped as CString — fix when this
lands.