MP live-play wave: collision economy, missiles, radar transform, panel polarity, comm ticker
The interactive 2-node playtest wave -- every fix decomp-grounded and live-verified: COLLISION ECONOMY (the ram one-shot): StaticBounce mutates worldLinearVelocity per contact and ProcessCollisionList walks EVERY touched solid per frame; with 2007 terrain-as-solids the reflections compounded x4-x40 within one frame and a walking bump one-shot a pristine mech for 112,375 pts (62-pt authentic economy). Fix: frameEntryWorldVelocity restore per contact (damage always priced at the real approach speed -- all the binary's physics ever saw); Mech::Reset zeroes the mover motion (respawn = teleport); [collide-tx]/[mp-hdlr] telemetry. Gotcha #16 (engine-facility drift class). MISSILES: peer-visible salvos (the launcher record extension carries a salvo counter + aim point; ForceUpdate actually enqueues it -- the dirty flag alone never serialized), the authentic arc (authored MuzzleVelocity vector + the Seeker's 200m/0.1/300 loft + gain-4 steering, decoded from @004beae4/@004bef78), world-impact bursts (rounds detonate on cave geometry instead of phasing through), contact-only damage (flight-cap expiry = fizzle, no more teleport damage), live re-lead, and ballistic (unguided) shells for autocannons. projweap's stale BTPushProjectile extern (the /FORCE signature trap, gotcha #6 corollary) crashed the Avatar's first AFC100 shot -- fixed + sweep rule recorded. RADAR: two transcription bugs made the scope permanently empty -- FUN_0040b244 is the affine INVERSE (not a copy) and FUN_0040adec writes ONLY the 3x3 rotation (never the translation); worldToView now Invert(view) built rotation-first. CulturalIcons sorted out of the moving grid (the phantom red pips were map props), visible-radius culls on all three draw passes, live pip verified at |delta| x ppm px. Gotcha #17 (verify the FUN_ body, not its call shape). WEAPON PANELS (the frozen-dial hunt): the binary's *(subsystem+0x40) means FAILED -- the recon's 'operating' name was backwards, inverting the destroyed-X lamps, the panel look, the children enable and the ready-lamp gate (which had NEVER executed). Polarity chain corrected end-to-end (failedState, fed by real damage saturation). Root cause of the freezes: MFD page-mode gating -- the dev composite shows ALL pages at once, so off-page dials legitimately stopped; under BT_DEV_GAUGES the 15 page-plane bits stay active (the exclusive secondary trio untouched). The SEH gauge guard now names its kills; repaint-heal resets the incremental arc after panel repaints; [panel]/[arc] probes added. COMM/SCORE: MessageBoard LIVE (the engine already shipped the whole Player__StatusMessage queue; wired the binary's one producer -- the kill branch, victim's name, 6s -- plus the consumer bridge and a lazy source bind); MP DEATHS counted via the observed-death tally (each node scores every pilot from locally observed events, the same model as the KILLS credit) and the -2/-1 engine seed clamped for display. DEV UX: node-tagged window titles (-net port), gauge panel reworked (1320x480, true 4:3 MFD cells, the portrait secondary UNROTATED upright, linear filtering, BT_GAUGE_SCALE), fixed close spawns via BT_SPAWN_XZ, Boreas flies an Avatar (first second-chassis live outing). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
dd27238ceb
commit
bb795e2805
@@ -113,6 +113,14 @@ near the image base, grep the link log for "unresolved external" — the "succes
|
||||
lying.** Corollary: a bridge fn / a `.data` fn-ptr callback MUST have a real (stub) definition.
|
||||
A `SetVideoPathPriority` defined in an anonymous namespace → internal linkage → unresolved in
|
||||
another TU → stubbed by /FORCE → AV in `LoadMissionImplementation`. [T2]
|
||||
**Signature-change corollary (user-hit crash 2026-07-12):** changing a shared free-function
|
||||
bridge's SIGNATURE changes its mangled name — every OTHER TU's local `extern` decl now
|
||||
references a symbol that no longer exists, /FORCE tolerates it, and the crash lands on the
|
||||
first call from the un-updated TU (the missile-arc wave updated `BTPushProjectile` +
|
||||
mislanch.cpp's extern but not projweap.cpp's → first AUTOCANNON shot AV'd). **Rule: after any
|
||||
bridge-signature change, `grep -rn "extern .*<name>"` and update every declaration; then grep
|
||||
the fresh link output for the symbol name** — the pre-existing LNK2019 wall camouflages new
|
||||
entries if you only eyeball it.
|
||||
|
||||
## 7. Dtor-epilogue rule — do not reconstruct compiler glue
|
||||
|
||||
@@ -293,6 +301,50 @@ corrupts the metric.
|
||||
canopies are open lattices. Namespace edge keys by patch identity (and remember l/r patches are
|
||||
MIRRORED — winding handedness flips, so no global winding choice can be right; orient per-face).
|
||||
|
||||
## 16. Engine-facility drift: 2007 terrain-solids amplify 1995 per-contact physics (the MP ram one-shot)
|
||||
|
||||
`Mover::StaticBounce` [T0] MUTATES `worldLinearVelocity` (`+= delta_v`, a ×(1+e) reflection) on
|
||||
every call, and `ProcessCollisionList` calls it once PER CONTACTED SOLID in the frame. In the 1995
|
||||
binary the ground was a heightfield probe (FUN_0040e5f0 lineage) — never a collision-list entry —
|
||||
so a mech's list held ~one solid and the mutation was harmless. The 2007 WinTesla engine models
|
||||
TERRAIN AS COLLISION SOLIDS: a mech touching ground + rock + another mech reflects 2-4× in ONE
|
||||
frame, compounding velocity ×4-×40, and the mech-vs-mech damage dispatch later in the list priced
|
||||
ram damage off the amplified value — a 62-point bump economy produced 1,074- and 112,375-point
|
||||
one-shots (mp_a.log:32651, 2026-07-12: a pristine mech killed by a walking bump). [T2]
|
||||
|
||||
- **Fix pattern:** snapshot the TRUE frame-entry motion (`frameEntryWorldVelocity`, set beside the
|
||||
`ProcessCollisionList` call sites) and restore it at the top of every `Mech::ProcessCollision` —
|
||||
each contact prices damage at the mech's real approach speed, which is all the binary's
|
||||
StaticBounce ever saw. The post-list velocity is discarded anyway (frame-rejection response /
|
||||
next frame's position-delta derive). Also: `Mech::Reset` must zero `worldLinearVelocity` +
|
||||
`localVelocity` (respawn is a TELEPORT; stale death-frame motion must not survive it).
|
||||
- **Tell:** damage amounts orders of magnitude outside the weapon economy (weapons 3-12/hit, rams
|
||||
~13-62), CONSTANT repeated values (a stable grind oscillation), or spikes scaling with how many
|
||||
solids surround the contact. Damage = `0.0005 × (1−e²) × impact² × moverMass` [T0 MOVER.cpp] —
|
||||
invert it to read the implied impact speed; >100 m/s means amplified/garbage velocity, not motion.
|
||||
- **Class rule:** when a 1995 per-event computation reads MUTABLE engine state, audit what ELSE the
|
||||
2007 engine feeds that state within the same event batch. (Family of gotcha #12's frame-pacing
|
||||
trap: the binary's physics assumed its own engine's event granularity.)
|
||||
|
||||
## 17. Engine-helper identity: verify the FUN_ body, not its call shape (the empty-radar bug)
|
||||
|
||||
Two adjacent matrix helpers in the radar's DrawDisplay were transcribed by CALL SHAPE and both
|
||||
were wrong — producing a plausible-looking but broken world→view transform that drew every pip
|
||||
hundreds of pixels off-scope (the radar looked simply "empty"; nothing crashed, nothing warned):
|
||||
- `FUN_0040b244(dst, src)` read as a COPY — it is the full affine INVERSE (cofactor expansion +
|
||||
determinant divide, part_001.c:172). → `worldToView.Invert(view)`.
|
||||
- `FUN_0040adec(matrix, quat)` read as a COMPOSE (`view *= yaw`) — it writes ONLY the 3×3
|
||||
rotation elements and NEVER touches [3]/[7]/[11] (the translation row). The engine's
|
||||
`operator*=(Quaternion)` composes fully (rotates the translation too) — the pre-set center got
|
||||
corrupted BEFORE the invert. → rotation-only assignment first, `SetFromAxis(W_Axis, center)`
|
||||
LAST. [T1 both, verified live: blip at exactly |delta|·ppm px after the fix]
|
||||
- **Tell:** a transform chain whose output is self-inconsistent — check whether the matrix maps
|
||||
its own reference point where it must (here: the viewer's position → the scope origin; it
|
||||
mapped to (−54, −599)). One logged matrix dump falsifies the whole chain in one frame.
|
||||
- **Rule:** for ANY engine-helper FUN_ in a reconstruction, read its BODY once (a 30-line
|
||||
decompile) before assigning it an engine method — a wrong-but-plausible identity survives
|
||||
every compile and every "it runs" test.
|
||||
|
||||
---
|
||||
|
||||
## Diagnostic recipe (the standard loop)
|
||||
|
||||
Reference in New Issue
Block a user