using AcDream.Content.Vfx;
using AcDream.Core.Physics;
using AcDream.Core.Tests.Conformance;
using DatReaderWriter;
using DatReaderWriter.DBObjs;
using DatReaderWriter.Options;
using DatReaderWriter.Types;
namespace AcDream.Core.Tests.Physics;
///
/// Pins the retail Humanoid motion table data consumed by CSequence root motion.
/// The packet-driven remote mover must use these values, not a velocity guessed
/// from the interpreted command.
///
public sealed class HumanoidMotionTableRootMotionTests
{
private const uint HumanoidMotionTable = 0x09000001u;
private const uint HumanoidSetup = 0x02000001u;
private const uint NonCombatStyle = 0x8000003Du;
private const uint WalkForward = 0x40000005u;
private const uint RunForward = 0x40000007u;
private const uint Ready = 0x41000003u;
private const uint InterpretedWalkForward = 0x45000005u;
[Theory]
[InlineData(WalkForward)]
[InlineData(RunForward)]
public void RetailLocomotionCycle_ExposesItsLiteralMotionDataVelocity(uint motion)
{
string? datDir = ConformanceDats.ResolveDatDir();
if (datDir is null)
return;
using var dats = new DatCollection(datDir, DatAccessType.Read);
MotionTable table = Assert.IsType(dats.Get(HumanoidMotionTable));
int key = unchecked((int)((NonCombatStyle << 16) | (motion & 0x00FF_FFFFu)));
MotionData cycle = Assert.IsType(table.Cycles[key]);
Assert.Equal(System.Numerics.Vector3.Zero, cycle.Velocity);
}
[Fact]
public void RetailWalkSequence_ProducesAuthoredRootDisplacement()
{
string? datDir = ConformanceDats.ResolveDatDir();
if (datDir is null)
return;
using var dats = new DatCollection(datDir, DatAccessType.Read);
Setup setup = Assert.IsType(dats.Get(HumanoidSetup));
MotionTable table = Assert.IsType(dats.Get(HumanoidMotionTable));
var sequencer = new AnimationSequencer(
setup,
table,
new RetailAnimationLoader(dats));
sequencer.SetCycle(NonCombatStyle, Ready);
sequencer.SetCycle(NonCombatStyle, InterpretedWalkForward);
float distance = 0f;
for (int i = 0; i < 120; i++)
{
var root = new Frame
{
Origin = System.Numerics.Vector3.Zero,
Orientation = System.Numerics.Quaternion.Identity,
};
sequencer.Advance(1f / 60f, root);
distance += root.Origin.Length();
}
Assert.True(
distance > 1f,
$"Installed retail WalkForward should author root travel; got {distance:F3} m over 2 s.");
}
}