feat(physics): port retail projectile integration

Add a pure Core projectile driver for retail clock quanta, final-state acceleration, 50-unit velocity clamping, world-space angular integration, full-3D AlignPath, and oriented Setup-local sphere sweeps. Preserve exact success versus set_frame-only failure semantics, independent Contact/OnWalkable state, and full-cell identity across all landblock directions.

Port OBJECTINFO::missile_ignore with explicit weenie/creature metadata, remove the invented transition-step cap, retain PathClipped without arming PerfectClip, and keep authoritative target identity optional. Add malformed-shape/clock, thin-wall, terrain, target-exclusion, frame-spike, failure-state, and boundary conformance coverage.

Retire TS-2 and synchronize the architecture, milestones, roadmap, research oracle, and durable physics memory.

Co-Authored-By: Codex <noreply@openai.com>
This commit is contained in:
Erik 2026-07-14 11:43:11 +02:00
parent 542dcfc384
commit f02b995e4f
21 changed files with 1669 additions and 263 deletions

View file

@ -15,7 +15,7 @@ namespace AcDream.Core.Tests.Physics;
/// as <c>HasPhysicsBSP = 0x00010000</c>.
///
/// <para>
/// For non-PvP, non-missile movers (M1.5 scope — walking-vs-static), an
/// After the whole-object PvP and missile exemption gates, an
/// entity with HAS_PHYSICS_BSP_PS in its state tests its BSP exclusively
/// — the foot cyl is NEVER tested. The closed cottage door (state
/// <c>0x10008</c> = <c>STATIC | REPORT_COLLISIONS | HAS_PHYSICS_BSP</c>)
@ -59,8 +59,8 @@ public class A6P7DispatchRulesTests
/// else
/// → BSP-only path
/// </code>
/// For M1.5 scope <c>ebp_1</c> (PvP-target-player) and <c>eax_12</c>
/// (missile_ignore) are treated as false. The predicate reduces to:
/// The PvP and missile terms are whole-object early exits in the port.
/// Once shape dispatch is reached, the predicate is therefore:
/// "BSP-only iff <c>HAS_PHYSICS_BSP_PS</c> is set".
/// </summary>
[Theory]
@ -76,44 +76,28 @@ public class A6P7DispatchRulesTests
Assert.Equal(expected, Transition.BspOnlyDispatch(entityState));
}
// -----------------------------------------------------------------------
// W1 (2026-06-24) — named PvP/missile terms are false in M1.5
// -----------------------------------------------------------------------
/// <summary>
/// W1: <see cref="Transition.PvpExempt"/> must return false in M1.5.
/// When PK ships (M2+) this stub will accept mover + target state;
/// the test pins the current named-false value as a guard.
/// Retail oracle: <c>CPhysicsObj::FindObjCollisions</c> pc:276808276841.
/// </summary>
[Fact]
public void W1_PvpExempt_ReturnsFalseInM15Scope()
{
// PvP hasn't shipped (M1.5); the stub always returns false.
Assert.False(Transition.PvpExempt());
}
/// <summary>
/// W1: <see cref="Transition.MissileIgnore"/> must return false in M1.5.
/// When missiles ship (F.3) this stub will accept mover OBJECTINFO +
/// target state; the test pins the current named-false value as a guard.
/// A non-missile mover does not trigger the retail missile exemption.
/// Retail oracle: <c>OBJECTINFO::missile_ignore</c> pc:274385;
/// dispatch use pc:276858276861.
/// </summary>
[Fact]
public void W1_MissileIgnore_ReturnsFalseInM15Scope()
public void NonMissileMover_DoesNotIgnoreOrdinaryTarget()
{
// Missiles haven't shipped (M1.5); the stub always returns false.
Assert.False(Transition.MissileIgnore());
var mover = new ObjectInfo();
Assert.False(mover.MissileIgnore(
targetEntityId: 1u,
targetPhysicsState: 0u,
targetFlags: EntityCollisionFlags.HasWeenie));
}
/// <summary>
/// Guard: with both W1 terms false, a BSP-flagged entity still
/// dispatches BSP-only — A6.P7 door behavior is unchanged after W1.
/// Guard: a BSP-flagged entity that reaches shape dispatch still uses
/// only its BSP — A6.P7 door behavior remains unchanged.
/// This protects the A6.P7 cottage-door / dungeon-wall fix.
/// </summary>
[Fact]
public void W1_BspOnlyDispatch_DoorStateStillDispatchesBspOnly()
public void BspOnlyDispatch_DoorStateStillDispatchesBspOnly()
{
// Cottage door state from A6.P7 investigation: 0x10008 = STATIC | REPORT | HAS_BSP
const uint doorState = 0x00010008u;