fix(animation): preserve wire motion on every spawn path

Replace the door-specific static-animation seed with one retail description-then-enter-world initializer shared by normal and reactive spawns. This preserves authoritative Dead and On/Off states, prevents replacement corpses from returning to Ready, and pins the lifecycle with Core and App tests.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-12 14:27:44 +02:00
parent 9b97102c67
commit 8be933fc94
9 changed files with 335 additions and 64 deletions

View file

@ -0,0 +1,58 @@
using AcDream.App.Rendering;
using AcDream.Core.Net.Messages;
using DatReaderWriter.DBObjs;
using DRWMotionCommand = DatReaderWriter.Enums.MotionCommand;
namespace AcDream.App.Tests.Rendering;
public sealed class SpawnMotionInitializerTests
{
[Fact]
public void CorpseUsesAuthoritativeDeadMotionFromWire()
{
var table = new MotionTable
{
DefaultStyle = (DRWMotionCommand)0x8000003Du,
};
var wire = new CreateObject.ServerMotionState(
Stance: 0x003D,
ForwardCommand: 0x0011);
SpawnMotionInitializer.Plan plan = SpawnMotionInitializer.ResolvePlan(table, wire);
Assert.Equal(0x8000003Du, plan.Style);
Assert.Equal(0x40000011u, plan.Motion);
}
[Theory]
[InlineData(0x000B, 0x4000000Bu)]
[InlineData(0x000C, 0x4000000Cu)]
public void DoorUsesAuthoritativeOnOrOffMotionFromWire(
ushort forwardCommand,
uint expectedMotion)
{
var table = new MotionTable();
var wire = new CreateObject.ServerMotionState(
Stance: 0x003D,
ForwardCommand: forwardCommand);
SpawnMotionInitializer.Plan plan = SpawnMotionInitializer.ResolvePlan(table, wire);
Assert.Equal(0x8000003Du, plan.Style);
Assert.Equal(expectedMotion, plan.Motion);
}
[Fact]
public void MissingWireStateUsesMotionTableDefaults()
{
var table = new MotionTable
{
DefaultStyle = (DRWMotionCommand)0x8000003Eu,
};
SpawnMotionInitializer.Plan plan = SpawnMotionInitializer.ResolvePlan(table, null);
Assert.Equal(0x8000003Eu, plan.Style);
Assert.Equal(0x41000003u, plan.Motion);
}
}