feat(R3-W4): ground transitions + lifecycle verbatim; K-fix18 DELETED (closes J8, J10, J11-shape, J12, J13, J18, J19)
Core (dedicated agent, independently reviewed): HitGround 0x00528ac0 / LeaveGround 0x00528b00 verbatim (creature+gravity gates, the RemoveLinkAnimations seam — K-fix18's retail mechanism — velocity via GetLeaveGroundVelocity with the autonomous flag, jump-state resets, apply_current_movement re-sync); enter_default_state 0x00528c80 per A8 (fresh states, InitializeMotionTables seam, sentinel APPENDED without draining pending_motions — pinned, Initted=1, LeaveGround tail); Initted gates; the A3 IsThePlayer dual dispatch in apply_current_movement / ReportExhaustion / SetWeenieObject / SetPhysicsObject (a remote player routes INTERPRETED — the ACE-divergence pin); set_hold_run 0x00528b70 + SetHoldKey 0x00528bb0 (XOR guard, None-only-from-Run); adjust_motion creature guard wired (TS-34 retired); PhysicsBody.LastMoveWasAutonomous + set_local_velocity(autonomous). Port discovery: retail's apply_raw_movement 0x005287e0 / apply_interpreted_movement 0x00528600 ARE the already-shipped D6.2a/funnel functions — the dual dispatch composes them instead of duplicating. App cutover (orchestrator): the skipTransitionLink flag + both K-fix18 call sites DELETED (AP-74 retired). MotionInterpreter.DefaultSink routes apply_current_movement's interpreted branch through the REAL funnel dispatch when a sink is bound — so a remote's LeaveGround engages Falling via the contact-gated funnel, replacing the forced SetCycle (J19); the per-remote MotionTableDispatchSink is now PERSISTENT (EnsureRemoteMotionBindings: DefaultSink + RemoveLinkAnimations + InitializeMotionTables seams, idempotent from both the UM and VectorUpdate paths; wire velocity re-applied after LeaveGround so it stays authoritative). Player: seams bound to the player sequencer; the controller's grounded→airborne EDGE now fires LeaveGround (jump() clears OnWalkable and the same frame's transition detection fires it — retail's order; walk-off-a-ledge gets the momentum fallback + link strip it never had); the manual jump-block LeaveGround deleted; LastMoveWasAutonomous set at the controller chokepoint (W6 refines). Trace S8 re-expressed as the retail mechanism (Falling dispatch + RemoveAllLinkAnimations = same final state the flag produced). 43 new lifecycle tests. Registers: TS-34 + AP-74 retired; TS-38, AP-77, AP-78 added. Full suite: 3,665 passed. Live smoke: in-world clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
af4764443f
commit
e214acdf23
8 changed files with 1575 additions and 124 deletions
|
|
@ -245,6 +245,24 @@ public sealed class PhysicsBody
|
|||
/// </summary>
|
||||
public bool IsFullyConstrained { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// R3-W4 — retail <c>CPhysicsObj::last_move_was_autonomous</c>, read by
|
||||
/// <c>CPhysicsObj::movement_is_autonomous</c> (0x0050eb30, decomp §7a
|
||||
/// @276443: <c>return this->last_move_was_autonomous;</c>). Gates the
|
||||
/// A3 dual-dispatch predicate in <c>MotionInterpreter.apply_current_movement</c>/
|
||||
/// <c>ReportExhaustion</c>/<c>SetWeenieObject</c>/<c>SetPhysicsObject</c>:
|
||||
/// true means the last motion on this body was locally-simulated
|
||||
/// (player input / local prediction), false means it was a
|
||||
/// server-driven dead-reckoning update. Set true at the local-player
|
||||
/// input chokepoint (App layer — <c>PlayerMovementController</c>);
|
||||
/// left false (the safe default — routes to
|
||||
/// <c>apply_interpreted_movement</c>) for DR-applied remote updates.
|
||||
/// <see cref="MotionInterpreter.LeaveGround"/> also sets this true
|
||||
/// itself: retail's <c>set_local_velocity(&var_c, 1)</c> call passes
|
||||
/// the autonomous flag literal <c>1</c> (raw @305763-305765).
|
||||
/// </summary>
|
||||
public bool LastMoveWasAutonomous { get; set; }
|
||||
|
||||
// ── convenience helpers ────────────────────────────────────────────────
|
||||
|
||||
public bool HasGravity => State.HasFlag(PhysicsStateFlags.Gravity);
|
||||
|
|
@ -324,10 +342,23 @@ public sealed class PhysicsBody
|
|||
/// worldY = col0.y*localX + col1.y*localY + col2.y*localZ
|
||||
/// worldZ = col0.z*localX + col1.z*localY + col2.z*localZ
|
||||
/// We replicate this as a Quaternion rotation, which is equivalent.
|
||||
///
|
||||
/// <para>
|
||||
/// R3-W4: retail's <c>set_local_velocity</c> takes a second
|
||||
/// <c>autonomous</c> arg (<c>CPhysicsObj::set_local_velocity</c>,
|
||||
/// stores it to <see cref="LastMoveWasAutonomous"/> — read by
|
||||
/// <c>CPhysicsObj::movement_is_autonomous</c>, the A3 dual-dispatch
|
||||
/// predicate). Defaults to <c>false</c> to preserve every pre-W4 call
|
||||
/// site's behavior (server/interpreted-driven callers never asserted
|
||||
/// autonomy); <see cref="MotionInterpreter.LeaveGround"/> is the one
|
||||
/// caller that passes <c>true</c> (raw @305763-305765,
|
||||
/// <c>set_local_velocity(&var_c, 1)</c>).
|
||||
/// </para>
|
||||
/// </summary>
|
||||
public void set_local_velocity(Vector3 localVelocity)
|
||||
public void set_local_velocity(Vector3 localVelocity, bool autonomous = false)
|
||||
{
|
||||
var worldVelocity = Vector3.Transform(localVelocity, Orientation);
|
||||
LastMoveWasAutonomous = autonomous;
|
||||
set_velocity(worldVelocity);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue