User observation (acdream observing a retail player's server MoveTo): walk-distance approaches correct; run-distance plays the run cycle AND moves toward the target in slow motion. Root cause, raw-verified (apply_run_to_command 0x00527be0, raw 305062-305076): retail's rate chain is weenie ? (InqRunRate() ?: my_run_rate) : 1.0 Every placed retail object HAS a weenie; a REMOTE's weenie fails InqRunRate (no local skill data) and the chain lands on my_run_rate - the exact field retail's mt-6/7 unpack writes with the wire's MoveToRunRate (M13; observed 4.50). Our port had the branch verbatim but remote interps carried NO weenie at all, taking the else-1.0 branch retail reserves for weenie-less detached objects: observer-side run dispatches went out at speed 1.0, so the run cycle's pace AND get_state_velocity's chase speed both crawled. Walk was unaffected - walk speed is never rate-scaled (the discriminating symptom). Fix: RemoteWeenie (Core) - the minimal stand-in for retail's per-object ACCWeenieObject: InqRunRate fails (-> my_run_rate), InqJumpVelocity fails, IsThePlayer default false (also ends the fragile "null weenie counts as the player" reading of the A3 dual dispatch for remotes), IsCreature default true (doors carry it too; their force-asserted Contact keeps the creature ground-gate moot - documented on the class). RemoteMotion's interp now constructs with it. Tests: RemoteWeenieRunRateTests pins both branches against the raw - RemoteWeenie + MyRunRate=4.5 promotes WalkForward->RunForward @ 4.5; weenie-less keeps the verbatim degenerate 1.0. Full suite green: 3,963. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
54 lines
2.3 KiB
C#
54 lines
2.3 KiB
C#
namespace AcDream.Core.Physics;
|
|
|
|
/// <summary>
|
|
/// R4-V5 (#160 fix, 2026-07-03): the minimal weenie every REMOTE entity's
|
|
/// <see cref="MotionInterpreter"/> carries — standing in for retail's
|
|
/// per-object <c>ACCWeenieObject</c>, which every placed physics object has.
|
|
///
|
|
/// <para>
|
|
/// The load-bearing behavior is the RUN-RATE FALLBACK CHAIN:
|
|
/// <c>apply_run_to_command</c> (0x00527be0, raw 305062-305076) reads
|
|
/// <c>weenie ? (InqRunRate() ?: my_run_rate) : 1.0</c>. Remote weenies in
|
|
/// retail FAIL <c>InqRunRate</c> (no local skill data), landing on
|
|
/// <c>my_run_rate</c> — exactly the field the mt-6/7 unpack writes with the
|
|
/// wire's <c>MoveToRunRate</c> (M13). Our remote interps previously had NO
|
|
/// weenie at all, taking the degenerate <c>else 1.0</c> branch retail
|
|
/// reserves for detached objects — so an observer-side moveto dispatched
|
|
/// RunForward at speed 1.0 instead of the wire rate: the run cycle played
|
|
/// in slow motion and the chase velocity crawled (walk was unaffected —
|
|
/// walk speed isn't rate-scaled).
|
|
/// </para>
|
|
///
|
|
/// <para>
|
|
/// <see cref="IWeenieObject.IsThePlayer"/> stays default false — the A3
|
|
/// dual dispatch routes remotes through apply_interpreted_movement, ending
|
|
/// the fragile "null weenie counts as the player" reading of that gate.
|
|
/// <see cref="IWeenieObject.IsCreature"/> stays default true; static
|
|
/// animated objects (doors) also carry this weenie — retail would say
|
|
/// non-creature there, but their RemoteMotion bodies force-assert Contact,
|
|
/// so the creature ground-gate is satisfied either way (noted, not a
|
|
/// behavior difference today).
|
|
/// </para>
|
|
/// </summary>
|
|
public sealed class RemoteWeenie : IWeenieObject
|
|
{
|
|
/// <summary>Remote objects have no local skill data — fail, so the
|
|
/// retail fallback chain lands on <see cref="MotionInterpreter.MyRunRate"/>
|
|
/// (the wire-fed rate).</summary>
|
|
public bool InqRunRate(out float rate)
|
|
{
|
|
rate = 0f;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>Remotes never locally compute jump arcs (server-broadcast
|
|
/// VectorUpdate velocities drive them).</summary>
|
|
public bool InqJumpVelocity(float extent, out float vz)
|
|
{
|
|
vz = 0f;
|
|
return false;
|
|
}
|
|
|
|
/// <summary>Remotes never locally initiate jumps.</summary>
|
|
public bool CanJump(float extent) => true;
|
|
}
|