feat(R4-V1): command-selection family + state widening (closes M2-mechanics, M11, M12, M15)
MovementParameters gains the verbatim selection family: GetCommand 0x0052aa00 (the walk-vs-run cascade INCLUDING the CanCharge 0x10 fast-path ACE dropped - retail's default can_charge=false + the fast-path present, the A13+A15 canceling-pair trap avoided; inclusive threshold edge per the raw), TowardsAndAway, GetDesiredHeading per the live Ghidra decompile (fwd-towards 0 / fwd-away 180 / back-towards 180 / back-away 0), FromWire/FromWireTurnTo (UnPackNet semantics, all 18 A4 masks round-tripped). New MoveToMath: HeadingDiff per the live Ghidra decompile of 0x00528fb0 (the 360-diff NOT-TurnRight mirror + F_EPSILON 0.000199999995f - the BN "arg unused" artifact corrected), HeadingGreater (the visible TurnRight idiom), PositionHeading/Get/SetHeading reusing the codebase's single yaw-heading convention (P5), CylinderDistance (PDB arg order; planar-minus-radii shape documented as the interpretation - the raw's x87 body is garbled; seam noted). MovementType gains Invalid + retail 6/7/8/9; MovementStruct widened (ObjectId/TopLevelId/Pos/Radius/Height/Params, additive); WeenieError += 0x0B/0x36/0x37/0x38/0x3D with retail-meaning doc comments. 148 new conformance tests. Full suite: 3,860 passed. Implemented by a dedicated agent against the V0-pinned spec; scope + suite independently verified. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
386b1ce550
commit
e0d2492cbb
14 changed files with 1973 additions and 4 deletions
|
|
@ -0,0 +1,84 @@
|
|||
using AcDream.Core.Physics;
|
||||
using AcDream.Core.Physics.Motion;
|
||||
using Xunit;
|
||||
|
||||
namespace AcDream.Core.Tests.Physics.Motion;
|
||||
|
||||
/// <summary>
|
||||
/// R4-V1 — <c>MovementParameters::towards_and_away</c> (<c>0x0052a9a0</c>,
|
||||
/// raw 307917-307942), verbatim per r4-moveto-decomp.md §5d. Three bands:
|
||||
/// beyond <c>distance_to_object</c> → WalkForward towards; inside the
|
||||
/// <c>min_distance</c> epsilon band → WalkBackwards away (no turn, unlike
|
||||
/// the pure-away branch in §5c which uses WalkForward+turn-around); strictly
|
||||
/// between → idle (cmd 0).
|
||||
/// </summary>
|
||||
public sealed class MovementParametersTowardsAndAwayTests
|
||||
{
|
||||
[Fact]
|
||||
public void DistGreaterThanDto_WalkForward_Towards()
|
||||
{
|
||||
var p = new MovementParameters { DistanceToObject = 0.6f, MinDistance = 0.2f };
|
||||
|
||||
p.TowardsAndAway(dist: 5f, out uint cmd, out bool movingAway);
|
||||
|
||||
Assert.Equal(MotionCommand.WalkForward, cmd);
|
||||
Assert.False(movingAway);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DistExactlyAtDto_NotGreater_FallsToMinBandCheck()
|
||||
{
|
||||
var p = new MovementParameters { DistanceToObject = 0.6f, MinDistance = 0.2f };
|
||||
|
||||
// dist == dto is NOT > dto, so falls through to the min-band test;
|
||||
// 0.6 - 0.2 = 0.4, not < epsilon → idle.
|
||||
p.TowardsAndAway(dist: 0.6f, out uint cmd, out _);
|
||||
|
||||
Assert.Equal(0u, cmd);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsideMinDistanceEpsilonBand_WalkBackwards_Away()
|
||||
{
|
||||
var p = new MovementParameters { DistanceToObject = 0.6f, MinDistance = 0.2f };
|
||||
|
||||
// dist - min_distance < 0.000199999995f
|
||||
p.TowardsAndAway(dist: 0.2f, out uint cmd, out bool movingAway);
|
||||
|
||||
Assert.Equal(MotionCommand.WalkBackward, cmd);
|
||||
Assert.True(movingAway);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InsideMinDistanceEpsilonBand_JustBelowEpsilon_StillWalkBackwards()
|
||||
{
|
||||
var p = new MovementParameters { DistanceToObject = 0.6f, MinDistance = 0.2f };
|
||||
|
||||
p.TowardsAndAway(dist: 0.2f + 0.0001f, out uint cmd, out bool movingAway);
|
||||
|
||||
Assert.Equal(MotionCommand.WalkBackward, cmd);
|
||||
Assert.True(movingAway);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StrictlyBetweenMinAndDto_Idle()
|
||||
{
|
||||
var p = new MovementParameters { DistanceToObject = 0.6f, MinDistance = 0.2f };
|
||||
|
||||
p.TowardsAndAway(dist: 0.4f, out uint cmd, out bool movingAway);
|
||||
|
||||
Assert.Equal(0u, cmd);
|
||||
Assert.False(movingAway);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JustOutsideMinBand_NotYetIdle_Idle()
|
||||
{
|
||||
var p = new MovementParameters { DistanceToObject = 0.6f, MinDistance = 0.2f };
|
||||
|
||||
// dist - min = 0.0003, just over epsilon (0.0002) → NOT in the min band → idle
|
||||
p.TowardsAndAway(dist: 0.2003f, out uint cmd, out _);
|
||||
|
||||
Assert.Equal(0u, cmd);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue