PARALLAX (#16): the pick/fire ray was anchored at mech.y+5.0 (a port improvisation) while the sight line ran from the eyepoint (y=6.23) -- two parallel rays whose constant offset grew into the reported low-miss as range closed (measured ry +0.072 @50u -> +1.54 @2.7u). The decomp's sight and pick share the eye origin (HudSimulation @4b7830 chain). Fix: the viewpoint mech's cockpit eye owns the aim-camera publish in BOTH views, origin = its own eye translation; leveling + deliberate elevation untouched; chase view now converges to cockpit ballistics (V cannot change where shots land). After: pick pinned to the crosshair (ry <= 5e-6) from 50u to point-blank; 26 laser + 8 missile center-mass hits at 3/4-screen. Awaiting the reporters' approach-test. VERDICT INSTRUMENTATION (#4 closed authentic, #5 verdict posted): BT_RANGE_LOG per-frame pick tracing + BTGroundRayHitExact analytic cross-check (0/8000 arena fall-throughs; cavern 6/8400 single-frame grazes -- the 'crazy sliding' is the authentic world-pick + 500 m/s slide over depth discontinuities); BT_AUD_TAIL StopNote/fade timing + BT_FIRE_PULSE single-shot driver (the energy 'buzz' is the AUTHORED charging loop: crescendo through recharge, 1.309s authored release, measured within one frame). CAVERN.EGG: solo cavern test egg. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
d7158f1f82
commit
70eea6c1a4
@@ -79,11 +79,39 @@ jointtorso — NO explicit eye-side compose exists, one briefly added on false "
|
||||
probe readings double-rotated the view and is retired, see [[cockpit-view]]); the crosshair sits
|
||||
at screen center (`gBTAimX = 0` — the old `BTTwistToReticleX` slew was THE bug: the camera
|
||||
already yawed, so the crosshair counter-slid to HULL-forward, "twisting leaves the crosshairs
|
||||
behind"; `BT_AIM="x y"` still pins it for headless tests) → `BTGetAimRay` (the ACTIVE eye
|
||||
behind"; `BT_AIM="x y"` still pins it for headless tests) → `BTGetAimRay` (the BORESIGHT eye
|
||||
publishes pos+basis via `BTSetAimCamera`, leveled in pitch, the twist yaw riding in the basis) →
|
||||
`Mech::PickRayHit` (world ray → local frame → `BoundingBox::HitBy` slab test vs the collision
|
||||
template's ExtentBox → world hit point).
|
||||
|
||||
**PICK-RAY ORIGIN = the TRUE EYEPOINT (Gitea #16 "shots land LOW, worse up close" — FIXED
|
||||
2026-07-20) [T1 evidence / T2 fix].** The task-#48 publish anchored the pick ray at
|
||||
`mech.y + 5.0` (a port improvisation) while the crosshair's sight line runs from the eyepoint
|
||||
(~y 6.2 on the DEV mech) — two parallel rays with a constant vertical offset, so the pick point
|
||||
slid DOWN the reticle as range closed (measured pre-fix via `BT_PARALLAX_LOG`, the pick point
|
||||
back-projected through the RENDER view: ry +0.07 @ 50u → +0.17 @ 16u → +0.32 @ 10u → +1.5 @
|
||||
2.7u; lasers AND missiles consume the pick, so both landed low). The binary's sight math is
|
||||
EYE-ORIGINATED [T1]: HudSimulation's designator HotBoxVector = target position transformed by
|
||||
`inverse(eyeSegToWorld)` ∘ `inverse(R(EyepointRotation))` where eyeSegToWorld = the HUD's mount
|
||||
SEGMENT frame × mech localToWorld (`@004b7830` part_013.c:5688-5702 — Ghidra drops the segment
|
||||
arg, disasm shows `hud+0xdc`; the seg→world composer is `FUN_00424da8` @00424da8); the VIEW is
|
||||
`inverse(jointtorso→jointeye→siteeyepoint)` (`FUN_004c22c4` part_013.c:11742); and the fired
|
||||
beam CONVERGES from the muzzle segment to the picked point `mech+0x37c` (`@004bace8`
|
||||
part_013.c:7742-7752) — so pick ray and sight line share the eye origin (the pod's division
|
||||
card cast from the view per Auric; the 0x37c/0x388 writer itself is in the un-exported gap).
|
||||
**The fix:** the viewpoint mech's cockpit `siteeyepoint` eye is marked the **BORESIGHT eye**
|
||||
(`DPLEyeRenderable::SetBoresightEye`, set in btl4vid.cpp) and owns the `BTSetAimCamera`
|
||||
publish in BOTH views (it executes in the mech's draw traversal every frame), origin = its own
|
||||
eye translation (eyeW row 4 — the exact frame the crosshair projects from); the leveling +
|
||||
`gBTEyeElev` re-application are unchanged. Chase ballistics are therefore IDENTICAL to cockpit
|
||||
(verified: chase-view pick lands at y=6.23076 = the cockpit eye height while the chase camera
|
||||
sits at y=11); the legacy `+5` anchor survives only as the no-boresight-eye fallback
|
||||
(spectator). Verified after: ry ≤ 5e-6 from 50u to point-blank 2.2u in cockpit AND glass
|
||||
builds; 26 laser `[dmghit]`s + 8 missile hits at range 1.7-2.2 on center-mass/upper zones with
|
||||
the lock ring on the target chest (`scratchpad/i16_laser.png`/`i16_missile.png`). Diags:
|
||||
`BT_PARALLAX_LOG` (pick→render-view back-projection via `BTProjectToRenderView`),
|
||||
`BT_GOTO_STOP`/`BT_GOTO_THR` (approach-test stop radius / walk throttle).
|
||||
|
||||
**THE WORLD-PICK TARGET MODEL (task #41, the reconciliation — binary + pod-video evidence).**
|
||||
The target slot `mech+0x388` holds **whatever entity is downrange of the torso boresight** — a
|
||||
mech OR a WORLD entity (terrain/mesa/building). Evidence: (a) the weapon fire path is DOUBLY
|
||||
@@ -387,6 +415,18 @@ thing: an EXPLICIT `JointedMover::~JointedMover()` in the reconstructed `~Mech`
|
||||
chain TWICE (the dtor-epilogue rule, [[reconstruction-gotchas]] §7) → a double-free of `collisionLists`
|
||||
+ the segment table. Removing it fixed BOTH the death-row crash AND app-exit crashes. [T2]
|
||||
|
||||
**⚠ The SILENT death-crash (Gitea #12, FIXED 2026-07-20) was NOT a mech-teardown bug at all — it
|
||||
was the DEATH-EXPLOSION AUDIO.** A silent hard crash (no WER/markers) a few seconds after ANY mech
|
||||
death — solo dummy, MP self-death, MP peer PEER_DOWN — deterministic on the first kill. Root cause:
|
||||
the death boom is the **AllExplosion preset (25 layered zones)**, but the port's OpenAL
|
||||
`SourceSet.sources[]` array was only **5** wide, so acquiring channels for it overwrote adjacent
|
||||
heap; the corruption turned fatal seconds later at the death Explosion's own audio-entity teardown
|
||||
(`FryDeathRow → Explosion::~Explosion → …DestroyEntityAudioObjects → ~Dynamic3DPatchSource →
|
||||
operator delete`) or the next sequenced virtual dispatch (`AudioControlSequence::RunSequence →
|
||||
Send`, garbage vtable). Fixed by sizing `sources[]` to the real max — see [[reconstruction-gotchas]]
|
||||
§21 (Gitea #12). NOT the held #16 boresight-eye dtor (exonerated), NOT the `rev=-64` mppr value
|
||||
(a `ControlsButton` negative = release, benign). [T2]
|
||||
|
||||
## Death SEQUENCE reconstruction — the map (2026-07-08)
|
||||
Full decomp map of the death path. Two tiers:
|
||||
**EXPORTED (reconstructable) [T1 read]:**
|
||||
|
||||
Reference in New Issue
Block a user