MP: world structures (garages/walls) TARGETABLE -- boresight ray-tests the static collision tree (task #50)
The boresight's non-mech pick only sampled the VISUAL heightfield (BTGroundRayHit), which on arena1 is a single flat 'sky'-named ground mesh (and class-42 BuildTables likewise holds only 'sky') -- so shots passed THROUGH the garages/walls and only mechs moved the HUD range axis (user-reported regression: "buildings used to move the range axis; now only mechs do, and you can only fire at a peer"). Real fix: the boresight now ALSO ray-tests the ZONE'S STATIC COLLISION SOLID TREE -- the same geometry that already blocks the mech's walk. Authentic engine mechanism: Mover::FindBoxedSolidHitBy already tests the static world via zone->GetCollisionRoot()->FindBoundingBoxHitBy(line). Factored its "static world" tail into Mover::FindStaticSolidHitBy(Line*) (static solids only, no movers), wrapped by Mech::WorldStructurePick(start,dir,range,&hit) (builds the world-space Line, reads the entry point back via line->FindEnd since HitByBounded clips line->length=enter). Boresight pick order is now: closest MECH (PickRayHit, damage zones + lock) -> closest STRUCTURE (WorldStructurePick; occludes a mech BEHIND it; designates the gBTTerrainEntity sentinel + entry point, so the range caret reads the structure distance and NO lock ring draws, mech4.cpp:4529) -> flat ground (BTGroundRayHit) -> sky (fire-at-nothing). Also un-skips arena1's misnamed-'sky' flat ground so the ground tier works (btvisgnd geometry-aware skip + [mapent]/[rendent] census). Verified headless: a BT_WSWEEP horizontal ray-fan on arena1 tracks position (3/24 hits near the boundary -> 17-21/24 inside the interior garage cluster -> 3/24 past it = DISCRETE interior solids, not an enclosing box), no crash/assert/AV. Interactive aim (BTGetAimRay) can't run headless (no window -> noRay), so the sweep is the headless proof; interactive aim is user-verified. Note: FindBoundingBoxUnder (the ground/containedByNode BoundingBoxTree) is DOWNWARD-only (gravity/ground-snap: *height = FindDistanceBelowBounded), useless for a horizontal boresight; the static SOLID tree's FindBoundingBoxHitBy is the only ray-vs-world query. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ee6e19e86e
commit
de8f6d02c1
@@ -104,6 +104,32 @@ bug was fixed en route: every
|
||||
renderable rebuild stomped `mCamera` back to the chase eye (btl4vid `mViewInside` now persists
|
||||
the chosen view — the aim camera feed and the V toggle both depend on it).
|
||||
|
||||
**WORLD STRUCTURES ARE TARGETABLE via the STATIC COLLISION TREE (task #50, 2026-07-15) [T2].**
|
||||
The `BTGroundRayHit` "terrain" tier only samples the VISUAL heightfield, which on arena1 is a
|
||||
single flat `'sky'`-named ground mesh (`[visgnd] sampler ready: 1 terrain instances`) — and the
|
||||
class-42 map-instance stream (`BuildTables`) likewise holds only `'sky'`. So the garages/walls
|
||||
were invisible to the pick → shots passed through them, and only mechs moved the range axis (the
|
||||
user-reported regression). The FIX: the boresight now also ray-tests the **zone's static collision
|
||||
solid tree** — the SAME geometry that blocks the mech's walk. Mechanism is authentic engine code:
|
||||
`Mover::FindBoxedSolidHitBy` (MOVER.cpp) already tests movers, doors, AND the static world
|
||||
(`application->GetInterestManager()->GetInterestZone(interestZoneID)->GetCollisionRoot()->FindBoundingBoxHitBy(line)`).
|
||||
We factored its "test against the static world" tail into **`Mover::FindStaticSolidHitBy(Line*)`**
|
||||
(static solids only, no movers), wrapped by **`Mech::WorldStructurePick(start,dir,range,&hit)`**
|
||||
(mech.cpp — builds the world-space `Line`, reads the entry point back via `line->FindEnd` since
|
||||
`FindBoundingBoxHitBy`→`HitByBounded` clips `line->length = enter`). The pick order in mech4.cpp is
|
||||
now: closest MECH (`PickRayHit`, damage zones + lock) → closest STRUCTURE (`WorldStructurePick`,
|
||||
occludes a mech BEHIND it) → flat ground (`BTGroundRayHit`) → sky (fire-at-nothing). A structure
|
||||
hit designates `mech+0x388 = gBTTerrainEntity` (the no-damage-zone sentinel) + `0x37c` = the entry
|
||||
point, so the range caret reads the structure distance and NO lock ring draws (mech4.cpp:4529, the
|
||||
`des != hotTarget` branch), exactly the reported authentic behavior. ⚠ There is NO ray query
|
||||
against the ground/`containedByNode` `BoundingBoxTree` — `FindBoundingBoxUnder` is DOWNWARD-only
|
||||
(gravity/ground-snap: `*height = FindDistanceBelowBounded`), useless for a horizontal boresight;
|
||||
the static SOLID tree (`BoxedSolidTree::FindBoundingBoxHitBy`) is the only ray-vs-world query.
|
||||
Verified: a `BT_WSWEEP` horizontal ray-fan on arena1 tracks position (3/24 hits near the boundary
|
||||
→ 17-21/24 inside the interior garage cluster → 3/24 past it — discrete interior solids, not just
|
||||
an enclosing box), no crash. The interactive boresight (`BTGetAimRay`) can't be exercised headless
|
||||
(no window → `noRay`), so the SWEEP is the headless proof; interactive aim is user-verified.
|
||||
|
||||
## Firing arc + muzzles
|
||||
There is NO firing-arc field in the binary (`Emitter::FireWeapon` fires whenever HasActiveTarget) —
|
||||
the 1995 game got away with it because it was **cockpit-only** (a beam behind you is off-camera). The
|
||||
|
||||
@@ -154,6 +154,17 @@ register. ⚠ The audit also flags the damage-economy item as SELF-CONTRADICTOR
|
||||
centred); (c) pre-burial, the pick still
|
||||
tests the sinking wreck's collision box at its parked position (pre-existing wreck-targeting
|
||||
behavior).
|
||||
- **✅ WORLD STRUCTURES (garages/walls) now targetable (task #50, 2026-07-15)** — the world-pick's
|
||||
non-mech tier previously only sampled the visual heightfield (`BTGroundRayHit`), which on arena1
|
||||
is a single flat `'sky'` ground mesh → shots passed THROUGH the garages and only mechs moved the
|
||||
range axis (user-reported regression). Resolved by ray-testing the **zone's static collision
|
||||
solid tree** (the geometry that already blocks the walk) via the authentic engine query
|
||||
`Mover::FindBoxedSolidHitBy`'s static-world tail — factored into `Mover::FindStaticSolidHitBy` +
|
||||
`Mech::WorldStructurePick`. See [[combat-damage]] "WORLD STRUCTURES ARE TARGETABLE". This also
|
||||
closes the old "0x388 writer is un-exported / unknown world-pick mechanism" residue: the
|
||||
authentic non-mech world pick is the static-solid-tree ray query (`BoxedSolidTree::FindBoundingBoxHitBy`),
|
||||
the same one `FindBoxedSolidHitBy` uses for mover-vs-world collision. Interactive aim is
|
||||
user-verified (headless has no `BTGetAimRay`); the `BT_WSWEEP` ray-fan is the headless proof.
|
||||
- **Cockpit HUD leftovers (tasks #35-#38 residue, 2026-07-08)** — the reticle + 7 weapon pips +
|
||||
ALL the instrument dynamics are LIVE (the Execute @004cdcf0 gap was RECOVERED via capstone
|
||||
disasm, task #37; the authentic Lock producer + the simple-X mode landed in #38 — see
|
||||
|
||||
Reference in New Issue
Block a user