feat(physics): D4+W1 — entry-restrictions register row + named PvP/missile dispatch terms
Part A (D4): CObjCell::check_entry_restrictions (pc:309576) gate is omitted from FindEnvCollisions. Investigation confirmed the gate requires restriction_obj (per-cell access-lock entity id) + weenie-object-table dispatch (CanMoveInto / CanBypassMoveRestrictions) — neither exist in acdream. CellPhysics has no restriction_obj field; DatReaderWriter models no per-cell access locks. Gap is inert in all dev content (ACE starter area has no access-locked env cells). Documented as AP-50 in the retail divergence register. Part B (W1): Replace the hardcoded-false smell in BspOnlyDispatch with named internal helpers PvpExempt() and MissileIgnore() that return false with retail oracle citations (pc:276808-276841 and pc:274385 respectively). BspOnlyDispatch now folds all three terms in retail's exact predicate structure. Behavior is byte-identical in M1.5 scope (both stubs false ⇒ reduces to HAS_PHYSICS_BSP_PS check alone, same as before). A6.P7 door dispatch unchanged. Tests: 3 new guard tests in A6P7DispatchRulesTests — W1_PvpExempt_ReturnsFalseInM15Scope, W1_MissileIgnore_ReturnsFalseInM15Scope, W1_BspOnlyDispatch_DoorStateStillDispatchesBspOnly. Suite: 1590 pass / 0 fail / 2 skip (was 1587 + 3 = 1590). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
a9f8775110
commit
6c7e3ef1ab
3 changed files with 110 additions and 16 deletions
|
|
@ -642,9 +642,54 @@ public sealed class Transition
|
|||
Environment.GetEnvironmentVariable("ACDREAM_DUMP_EDGE_SLIDE") == "1";
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// A6.P7 (2026-05-25) — retail-binary dispatch rule
|
||||
// A6.P7 (2026-05-25) + W1 (2026-06-24) — retail-binary dispatch rule
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// W1: Named predicate for the PvP-exemption term in retail's
|
||||
/// <c>CPhysicsObj::FindObjCollisions</c> dispatch (pc:276861,
|
||||
/// <c>acclient_2013_pseudo_c.txt:276808–276841</c>).
|
||||
///
|
||||
/// <para>
|
||||
/// In retail <c>ebp_1</c> is non-null when the mover is a player AND
|
||||
/// the target is not impenetrable AND PK/PKLite flags indicate a
|
||||
/// PvP-exempt pairing — i.e. the mover should pass through rather than
|
||||
/// collide. While this is non-null the dispatch takes the cyl+sphere
|
||||
/// path regardless of <c>HAS_PHYSICS_BSP_PS</c>, effectively making
|
||||
/// PvP-exempt players transparent to BSP-only objects.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// M1.5 scope has no PK. Returns <c>false</c> always.
|
||||
/// Wire through mover + target state when PK ships (M2+ / phase TBD).
|
||||
/// Retail oracle: pc:276808–276841.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
internal static bool PvpExempt() => false; // wire when PK ships (M2+) — pc:276808–276841
|
||||
|
||||
/// <summary>
|
||||
/// W1: Named predicate for the <c>OBJECTINFO::missile_ignore</c> term
|
||||
/// in retail's <c>CPhysicsObj::FindObjCollisions</c> dispatch
|
||||
/// (pc:276861, <c>acclient_2013_pseudo_c.txt:274385 + :276858–276861</c>).
|
||||
///
|
||||
/// <para>
|
||||
/// In retail <c>eax_12 = OBJECTINFO::missile_ignore(ebx, this)</c>
|
||||
/// returns non-zero when either the TARGET has <c>MISSILE_PS (0x40)</c>
|
||||
/// set, or the mover has <c>MISSILE_PS</c> set and the target is a
|
||||
/// creature that is not the mover's designated target. When non-zero the
|
||||
/// dispatch takes the cyl+sphere path regardless of
|
||||
/// <c>HAS_PHYSICS_BSP_PS</c> — missiles pass through BSP-only objects.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// M1.5 scope has no missiles. Returns <c>false</c> always.
|
||||
/// Wire through mover OBJECTINFO + target state when missiles ship (F.3).
|
||||
/// Retail oracle: <c>OBJECTINFO::missile_ignore</c> pc:274385;
|
||||
/// dispatch pc:276858–276861.
|
||||
/// </para>
|
||||
/// </summary>
|
||||
internal static bool MissileIgnore() => false; // wire when missiles ship (F.3) — pc:274385
|
||||
|
||||
/// <summary>
|
||||
/// A6.P7 retail-binary dispatch predicate. Returns true when an
|
||||
/// entity's collision queries should go to its BSP exclusively,
|
||||
|
|
@ -660,23 +705,24 @@ public sealed class Transition
|
|||
/// else
|
||||
/// // BSP-only via CPartArray::FindObjCollisions
|
||||
/// </code>
|
||||
/// where <c>ebp_1</c> is the PvP-target-player flag (lines 276808-
|
||||
/// 276841) and <c>eax_12</c> is the <c>OBJECTINFO::missile_ignore</c>
|
||||
/// result (line 274385). The flag is named
|
||||
/// where <c>ebp_1</c> is the PvP-target-player flag (lines 276808–
|
||||
/// 276841, see <see cref="PvpExempt"/>) and <c>eax_12</c> is the
|
||||
/// <c>OBJECTINFO::missile_ignore</c> result (line 274385, see
|
||||
/// <see cref="MissileIgnore"/>). The flag is named
|
||||
/// <c>HAS_PHYSICS_BSP_PS = 0x10000</c> in acclient.h:2833 and
|
||||
/// <c>PhysicsState.HasPhysicsBSP</c> in ACE
|
||||
/// (references/ACE/Source/ACE.Entity/Enum/PhysicsState.cs:24).
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
/// M1.5 scope (walking-vs-static, no PK, no missiles) treats both
|
||||
/// <c>ebp_1</c> and <c>eax_12</c> as <c>false</c>. The predicate
|
||||
/// reduces to <c>(state & HAS_PHYSICS_BSP_PS) != 0</c>. When
|
||||
/// PK ships (M2+ phase) and missiles ship (F.3), wire the
|
||||
/// PvP-exemption and missile_ignore checks through as additional
|
||||
/// parameters following retail's
|
||||
/// <c>references/ACE/Source/ACE.Server/Physics/PhysicsObj.cs:412</c>
|
||||
/// dispatch shape.
|
||||
/// BSP-only iff:
|
||||
/// <c>HAS_PHYSICS_BSP_PS</c> is set on the entity
|
||||
/// AND the mover is not PvP-exempt for this target (<see cref="PvpExempt"/> = false)
|
||||
/// AND the entity is not missile-ignore exempt (<see cref="MissileIgnore"/> = false).
|
||||
/// In M1.5 <see cref="PvpExempt"/> and <see cref="MissileIgnore"/> both
|
||||
/// return false, so the predicate reduces to
|
||||
/// <c>(state & HAS_PHYSICS_BSP_PS) != 0</c> — no behavior change
|
||||
/// from before W1.
|
||||
/// </para>
|
||||
///
|
||||
/// <para>
|
||||
|
|
@ -688,10 +734,13 @@ public sealed class Transition
|
|||
/// <c>PhysicsState</c> value (as stored on
|
||||
/// <c>ShadowEntry.State</c>).</param>
|
||||
/// <returns>True when retail would dispatch BSP-only — i.e. when
|
||||
/// the entity has <c>HAS_PHYSICS_BSP_PS</c> set; cyl/sphere shapes
|
||||
/// must be skipped at the per-entry dispatch site.</returns>
|
||||
/// the entity has <c>HAS_PHYSICS_BSP_PS</c> set AND neither the PvP
|
||||
/// exemption nor the missile-ignore exemption applies; cyl/sphere
|
||||
/// shapes must be skipped at the per-entry dispatch site.</returns>
|
||||
public static bool BspOnlyDispatch(uint entityState)
|
||||
=> (entityState & (uint)PhysicsStateFlags.HasPhysicsBsp) != 0;
|
||||
=> (entityState & (uint)PhysicsStateFlags.HasPhysicsBsp) != 0
|
||||
&& !PvpExempt()
|
||||
&& !MissileIgnore();
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Public entry point
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue