feat(physics): R5-V1 — port PositionManager/Sticky/Constraint + TargetManager (Core, unwired)
The retail movement-manager family the R4 MoveToManager port left as do-not-invent seams (decomp §9f/§9g). Faithful C# ports of retail's PositionManager facade + StickyManager + ConstraintManager + the TargetManager voyeur system, with full conformance tests. NO wiring yet — purely additive, no behavior change. Wiring (retiring TS-39 sticky + AP-79 target adapter) is R5-V2/V3. New Core classes (src/AcDream.Core/Physics/Motion/): - StickyManager (0x00555400): follow-a-target steering. adjust_offset's dense x87 mush decoded via ACE (StickyRadius 0.3, StickyTime 1.0, follow speed ×5 / fallback 15) — speed-clamped signed-distance steer + bounded turn-to-face; 1 s watchdog; Ok→initialized / non-Ok→teardown. - ConstraintManager (0x00556090): the server-position rubber-band leash. 90% IsFullyConstrained jump gate + grounded linear brake taper. Structural only — acdream never ARMS it (retail arms from SmartBox::HandleReceivedPosition, which acdream lacks, with two x87 constants BN elided). IsFullyConstrained stays false = TS-35 behavior; leash-arming + the unknown constants are a deferred issue. - PositionManager facade (0x00555160): lazy Sticky/Constraint + fan-out. - TargetManager (0x0051a370) + TargettedVoyeurInfo: the peer-to-peer voyeur subscription system (0.5 s throttle, 10 s staleness, send-on-drift-past-radius, dead-reckon GetInterpolatedPosition). A faithful superset of the AP-79 adapter — SetTarget subscribes ON the target; the target's HandleTargetting pushes updates back. - IPhysicsObjHost: the CPhysicsObj back-pointer seam (position/velocity/ radius/contact/GetObjectA + target-tracking fan-out) the App wires per entity in V2/V3. MotionDeltaFrame: mutable retail-Frame delta accumulator. Supporting: - TargetInfo extended to the full retail 10-field struct (additive defaults keep the R4 4-arg call sites compiling). - MoveToMath: signed CylinderDistanceNoZ, NormalizeCheckSmall, GlobalToLocalVec. - Rename: the misnamed AcDream.Core.Physics.PositionManager (a remote anim+interp per-frame combiner, NOT the retail facade) → RemoteMotion Combiner, freeing the name and removing the ambiguity that breaks every file importing both Physics + Physics.Motion (GameWindow will in V2/V3). Tests: 42 new conformance cases (Sticky/Constraint/Position facade + TargetManager incl. the full cross-entity voyeur round-trip). Full suite 4006 green (+2 skipped), no regressions. Decomp + ACE cross-ref + port plan: docs/research/2026-07-03-r5-managers/. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
517bbfdae4
commit
3d89446d98
25 changed files with 7279 additions and 12 deletions
40
src/AcDream.Core/Physics/Motion/MotionDeltaFrame.cs
Normal file
40
src/AcDream.Core/Physics/Motion/MotionDeltaFrame.cs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
using System.Numerics;
|
||||
|
||||
namespace AcDream.Core.Physics.Motion;
|
||||
|
||||
/// <summary>
|
||||
/// Mutable stand-in for retail's <c>Frame</c> when it is used as the per-tick
|
||||
/// <b>delta accumulator</b> that <c>PositionManager::adjust_offset</c> and its
|
||||
/// three sub-managers (Interpolation / Sticky / Constraint) write into
|
||||
/// (retail arg2, e.g. <c>StickyManager::adjust_offset</c> 0x00555430,
|
||||
/// <c>ConstraintManager::adjust_offset</c> 0x00556180). acdream's
|
||||
/// <see cref="CellFrame"/> is an immutable record — retail's per-tick math
|
||||
/// mutates <c>m_fOrigin</c> in place across the interp→sticky→constraint chain
|
||||
/// (each sub-manager composes on top of the previous one's write), so the
|
||||
/// accumulator needs a mutable shape.
|
||||
///
|
||||
/// <para><see cref="Origin"/> = retail <c>m_fOrigin</c> (the accumulated
|
||||
/// position delta, in the mover's LOCAL frame after
|
||||
/// <c>Position::globaltolocalvec</c>). <see cref="Orientation"/> carries the
|
||||
/// heading retail's <c>Frame::set_heading</c> writes; read/write it as a
|
||||
/// compass heading via <see cref="GetHeading"/> / <see cref="SetHeading"/>
|
||||
/// (P5 convention, degrees).</para>
|
||||
/// </summary>
|
||||
public sealed class MotionDeltaFrame
|
||||
{
|
||||
/// <summary>Retail <c>m_fOrigin</c> — the accumulated per-tick position
|
||||
/// delta (mover-local frame).</summary>
|
||||
public Vector3 Origin;
|
||||
|
||||
/// <summary>Retail <c>Frame</c> rotation — carries the
|
||||
/// <c>Frame::set_heading</c> output.</summary>
|
||||
public Quaternion Orientation = Quaternion.Identity;
|
||||
|
||||
/// <summary>Retail <c>Frame::get_heading</c> (P5 compass degrees).</summary>
|
||||
public float GetHeading() => MoveToMath.GetHeading(Orientation);
|
||||
|
||||
/// <summary>Retail <c>Frame::set_heading(headingDeg)</c> — pure
|
||||
/// yaw-about-Z setter (P5 compass degrees).</summary>
|
||||
public void SetHeading(float headingDeg) =>
|
||||
Orientation = MoveToMath.SetHeading(Orientation, headingDeg);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue