fix(anim): Phase L.1c spawn-time cycle fallback + diagnostics
User reports same "torso on the ground" symptom after 34d7f4d. Likely
cause: my fallback only covered the OnLiveMotionUpdated path, not the
spawn handler at the CreateObject boundary. If the spawn-time
SetCycle requests a (style, motion) pair the MotionTable lacks,
ClearCyclicTail wipes the cyclic tail at line 396 of
AnimationSequencer.cs and every body part snaps to its setup-default
offset until the first OnLiveMotionUpdated UM applies the path's
fallback there.
Apply the same fallback chain (requested → WalkForward → Ready →
no-op-don't-clear) at the spawn handler. Also add a one-line
diagnostic dump (under ACDREAM_DUMP_MOTION=1) on both code paths so
the next launch confirms whether the fallback is actually firing and
what (mtable, style, motion) tuples are missing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
34d7f4def2
commit
e71ed73aa9
1 changed files with 51 additions and 1 deletions
|
|
@ -2111,7 +2111,48 @@ public sealed class GameWindow : IDisposable
|
|||
{
|
||||
seqMotion = AcDream.Core.Physics.MotionCommand.Ready;
|
||||
}
|
||||
sequencer.SetCycle(seqStyle, seqMotion);
|
||||
|
||||
// Phase L.1c followup (2026-04-28): apply the same
|
||||
// missing-cycle fallback the OnLiveMotionUpdated path
|
||||
// uses. Without this, a monster spawned in combat
|
||||
// stance with the wire's seqMotion absent from its
|
||||
// MotionTable hits ClearCyclicTail() with no
|
||||
// replacement enqueue, every body part snaps to its
|
||||
// setup-default offset, and the visual collapses to
|
||||
// "torso on the ground" — visible to acdream
|
||||
// observers when another client is in combat with a
|
||||
// monster, until the first OnLiveMotionUpdated UM
|
||||
// applies the same fallback there.
|
||||
uint spawnCycle = seqMotion;
|
||||
if (!sequencer.HasCycle(seqStyle, spawnCycle))
|
||||
{
|
||||
uint origCycle = spawnCycle;
|
||||
// RunForward → WalkForward → Ready
|
||||
if ((spawnCycle & 0xFFu) == 0x07
|
||||
&& sequencer.HasCycle(seqStyle, 0x45000005u))
|
||||
{
|
||||
spawnCycle = 0x45000005u;
|
||||
}
|
||||
else if (sequencer.HasCycle(seqStyle, 0x41000003u))
|
||||
{
|
||||
spawnCycle = 0x41000003u;
|
||||
}
|
||||
else
|
||||
{
|
||||
spawnCycle = 0;
|
||||
}
|
||||
|
||||
if (Environment.GetEnvironmentVariable("ACDREAM_DUMP_MOTION") == "1")
|
||||
{
|
||||
Console.WriteLine(
|
||||
$"spawn cycle missing for guid=0x{spawn.Guid:X8} mtable=0x{mtableId:X8} " +
|
||||
$"style=0x{seqStyle:X8} requested=0x{origCycle:X8} " +
|
||||
$"→ fallback=0x{spawnCycle:X8}");
|
||||
}
|
||||
}
|
||||
|
||||
if (spawnCycle != 0)
|
||||
sequencer.SetCycle(seqStyle, spawnCycle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2603,6 +2644,7 @@ public sealed class GameWindow : IDisposable
|
|||
uint cycleToPlay = animCycle;
|
||||
if (!ae.Sequencer.HasCycle(fullStyle, cycleToPlay))
|
||||
{
|
||||
uint requested = cycleToPlay;
|
||||
// RunForward (0x44000007) → WalkForward (0x45000005)
|
||||
if ((cycleToPlay & 0xFFu) == 0x07
|
||||
&& ae.Sequencer.HasCycle(fullStyle, 0x45000005u))
|
||||
|
|
@ -2621,6 +2663,14 @@ public sealed class GameWindow : IDisposable
|
|||
{
|
||||
cycleToPlay = 0;
|
||||
}
|
||||
|
||||
if (Environment.GetEnvironmentVariable("ACDREAM_DUMP_MOTION") == "1")
|
||||
{
|
||||
Console.WriteLine(
|
||||
$"UM cycle missing for guid=0x{update.Guid:X8} " +
|
||||
$"style=0x{fullStyle:X8} requested=0x{requested:X8} " +
|
||||
$"→ fallback=0x{cycleToPlay:X8}");
|
||||
}
|
||||
}
|
||||
if (cycleToPlay != 0)
|
||||
ae.Sequencer.SetCycle(fullStyle, cycleToPlay, animSpeed);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue