fix(physics): #137 Task 3 — port obstruction_ethereal verbatim; retire AD-7 shim
Retail CPhysicsObj::FindObjCollisions (0x0050f050) only instant-skips when BOTH ETHEREAL_PS (0x4) AND IGNORE_COLLISIONS_PS (0x10) are set (pc:276782). ETHEREAL-alone sets sphere_path.obstruction_ethereal=1 (pc:276806) and continues to the shape dispatch. BSPTREE::find_collisions (0x0053a496) routes Path 1 (sphere_intersects_solid) when the flag is set (pc:323742): the open door has no solid leaf at the doorway, so the test returns OK → player passes through. CEnvCell::find_env_collisions (0x0052c144) clears the flag first so ENV walls are never weakened (pc:309580, "D5 clear"). Changes: - CollisionExemption.ShouldSkip: require BOTH bits for Gate-1 early-out (previously ETHEREAL alone returned true — the AD-7 shim). Divergence register row AD-7 deleted. - SpherePath: add ObstructionEthereal field (mirrors retail SPHEREPATH.obstruction_ethereal). - FindObjCollisionsInternal loop: set sp.ObstructionEthereal=(target&0x4)!=0 before shape dispatch; clear it after (per-object clear pc:276989). Also clear at the null-BSP continue site to keep flag clean. - FindEnvCollisions: clear sp.ObstructionEthereal=false at top (D5 clear pc:309580) — ENV cell walls are always solid. - BSPQuery.FindCollisions Path 1: change `obj.Ethereal` (ObjectInfo.Ethereal, always false — dead code) to `path.ObstructionEthereal`. Gate now correctly mirrors retail pc:323742: PLACEMENT_INSERT || obstruction_ethereal. Consume site change (BSPQuery.cs before/after): BEFORE: if (path.InsertType == InsertType.Placement || obj.Ethereal) AFTER: if (path.InsertType == InsertType.Placement || path.ObstructionEthereal) Mirrors retail pc:323742 exactly. obj.Ethereal was dead code (ObjectInfo.Ethereal is never set true anywhere); the correct flag is SpherePath.ObstructionEthereal. Tests: 1580 pass / 0 fail / 2 skip (was 1576/0/2 + 4 new in ObstructionEtherealTests. CellarUp, CornerFlood, DoorCollision, HouseExitWalk all green — no wall regressions. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
78e5758185
commit
3361a8d776
7 changed files with 382 additions and 30 deletions
|
|
@ -59,23 +59,20 @@ public static class CollisionExemption
|
|||
public static bool ShouldSkip(uint targetState, EntityCollisionFlags targetFlags,
|
||||
ObjectInfoState moverState)
|
||||
{
|
||||
// 1. Target ETHEREAL → walk through.
|
||||
// Retail (acclient_2013_pseudo_c.txt:276782) requires BOTH
|
||||
// ETHEREAL_PS (0x4) AND IGNORE_COLLISIONS_PS (0x10) to wrap
|
||||
// the entire body of FindObjCollisions and skip collision.
|
||||
// ETHEREAL alone takes a different retail path (line 276795
|
||||
// sets sphere_path.obstruction_ethereal = 1 and downstream
|
||||
// movement allows passage despite the contact). We haven't
|
||||
// ported that downstream path yet.
|
||||
//
|
||||
// L.2g slice 1b (2026-05-13): ACE's Door.Open() sends only
|
||||
// ETHEREAL (state=0x0001000C observed live), not the
|
||||
// ETHEREAL|IGNORE_COLLISIONS combo retail servers broadcast.
|
||||
// Pragmatic shortcut: exempt on ETHEREAL alone so doors
|
||||
// become passable when ACE flips the bit. Retail-server
|
||||
// broadcasts (state=0x14+) still hit this branch correctly
|
||||
// because both bits set implies ETHEREAL set.
|
||||
if ((targetState & ETHEREAL_PS) != 0)
|
||||
// 1. Target ETHEREAL + IGNORE_COLLISIONS → instant-skip.
|
||||
// Retail (acclient_2013_pseudo_c.txt:276782):
|
||||
// `if ((state & 4) AND (state & 0x10)) return 1`
|
||||
// BOTH bits are required. ETHEREAL-alone takes the retail
|
||||
// `obstruction_ethereal` path instead (pc:276806): the flag is
|
||||
// set to 1 on the SpherePath and the shape test still runs,
|
||||
// but BSP Path 1 (sphere_intersects_solid) weakens solid-
|
||||
// containment so the player passes through the open door.
|
||||
// ACE's Door.Open() broadcasts ETHEREAL only (0x0001000C) —
|
||||
// this faithful port makes open doors passable via the BSP
|
||||
// sphere_intersects_solid path (no solid leaf at the opening),
|
||||
// which subsumes the former AD-7 shim. Divergence register
|
||||
// row AD-7 retired in the same commit as this change.
|
||||
if ((targetState & ETHEREAL_PS) != 0 && (targetState & IGNORE_COLLISIONS_PS) != 0)
|
||||
return true;
|
||||
|
||||
// 2. Viewer mover + creature target → walk through.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue