diff --git a/src/AcDream.App/Rendering/GameWindow.cs b/src/AcDream.App/Rendering/GameWindow.cs index 9fc7279..ecd3bda 100644 --- a/src/AcDream.App/Rendering/GameWindow.cs +++ b/src/AcDream.App/Rendering/GameWindow.cs @@ -2832,14 +2832,29 @@ public sealed class GameWindow : IDisposable { var sequencer = new AcDream.Core.Physics.AnimationSequencer(setup, mtable, _animLoader); - const uint NonCombatStance = 0x80000001u; + // Style key is `0x80000000 | stance`. ACE's MotionStance.NonCombat + // is 0x3D (61 decimal), NOT 0x01. Verified live: ACE broadcasts + // UpdateMotion with stance=0x003D and the sequencer keys cycles + // by style=0x8000003D. An earlier B.4c seed used the wrong + // 0x80000001 value, which made HasCycle always return false -> + // SetCycle never fired -> sequencer empty -> Advance returned + // no frames -> per-frame tick collapsed all door parts to the + // entity origin (visible as "door halfway in the ground"). + const uint NonCombatStyle = 0x8000003Du; const uint MotionOn = 0x4000000Bu; // ACE MotionCommand.On (door open) const uint MotionOff = 0x4000000Cu; // ACE MotionCommand.Off (door closed) const uint EtherealPs = 0x4u; + // Prefer the spawn's wire-level stance if provided; else default + // to NonCombat. (Doors normally don't carry an initial MotionState + // on spawn — falling back to NonCombat matches ACE Door.cs:43.) + ushort spawnStance = spawn.MotionState?.Stance ?? 0; + uint initialStyle = spawnStance != 0 + ? (0x80000000u | (uint)spawnStance) + : NonCombatStyle; uint spawnState = spawn.PhysicsState ?? 0u; uint initialCycle = (spawnState & EtherealPs) != 0 ? MotionOn : MotionOff; - if (sequencer.HasCycle(NonCombatStance, initialCycle)) - sequencer.SetCycle(NonCombatStance, initialCycle); + if (sequencer.HasCycle(initialStyle, initialCycle)) + sequencer.SetCycle(initialStyle, initialCycle); var template = new (uint, IReadOnlyDictionary?)[meshRefs.Count]; for (int i = 0; i < meshRefs.Count; i++) @@ -2861,7 +2876,7 @@ public sealed class GameWindow : IDisposable if (AcDream.Core.Physics.PhysicsDiagnostics.ProbeBuildingEnabled) Console.WriteLine(System.FormattableString.Invariant( - $"[door-anim] registered guid=0x{spawn.Guid:X8} entityId=0x{entity.Id:X8} mtable=0x{mtableId:X8} initialCycle=0x{initialCycle:X8}")); + $"[door-anim] registered guid=0x{spawn.Guid:X8} entityId=0x{entity.Id:X8} mtable=0x{mtableId:X8} initialStyle=0x{initialStyle:X8} initialCycle=0x{initialCycle:X8}")); } } }