diff --git a/Source/Framework/Constants/Movement/MovementConst.cs b/Source/Framework/Constants/Movement/MovementConst.cs index c261619fe..b30909a93 100644 --- a/Source/Framework/Constants/Movement/MovementConst.cs +++ b/Source/Framework/Constants/Movement/MovementConst.cs @@ -66,7 +66,10 @@ namespace Framework.Constants { None = 0x0, Update = 0x1, // Update in progress - StaticInitializationPending = 0x2 + StaticInitializationPending = 0x2, // Static movement (MOTION_SLOT_DEFAULT) hasn't been initialized + InitializationPending = 0x4, // MotionMaster is stalled until signaled + + Delayed = StaticInitializationPending | InitializationPending } public enum MotionMasterDelayedActionType diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index f2ceafb5f..647fb0a53 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -430,6 +430,7 @@ namespace Game.Entities public override void AddToWorld() { base.AddToWorld(); + i_motionMaster.AddToWorld(); RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.EnterWorld); } diff --git a/Source/Game/Movement/MotionMaster.cs b/Source/Game/Movement/MotionMaster.cs index b59bd7d0c..e23a2b283 100644 --- a/Source/Game/Movement/MotionMaster.cs +++ b/Source/Game/Movement/MotionMaster.cs @@ -106,7 +106,7 @@ namespace Game.Movement public void Initialize() { - if (HasFlag(MotionMasterFlags.Update)) + if (HasFlag(MotionMasterFlags.Delayed)) { _delayedActions.Enqueue(new DelayedAction(() => Initialize(), MotionMasterDelayedActionType.Initialize)); return; @@ -120,6 +120,16 @@ namespace Game.Movement Add(AI.AISelector.SelectMovementGenerator(_owner), MovementSlot.Default); } + public void AddToWorld() + { + if (!HasFlag(MotionMasterFlags.InitializationPending)) + return; + + ResolveDelayedActions(); + + RemoveFlag(MotionMasterFlags.InitializationPending); + } + public bool Empty() { return _defaultGenerator == null && _generators.Empty(); @@ -287,6 +297,9 @@ namespace Game.Movement if (!_owner) return; + if (HasFlag(MotionMasterFlags.InitializationPending)) + return; + Cypher.Assert(!Empty(), $"MotionMaster:Update: update called without Initializing! ({_owner.GetGUID()})"); AddFlag(MotionMasterFlags.Update); @@ -315,11 +328,7 @@ namespace Game.Movement RemoveFlag(MotionMasterFlags.Update); - while (_delayedActions.Count != 0) - { - _delayedActions.Peek().Resolve(); - _delayedActions.Dequeue(); - } + ResolveDelayedActions(); } void Add(MovementGenerator movement, MovementSlot slot = MovementSlot.Active) @@ -330,7 +339,7 @@ namespace Game.Movement if (IsInvalidMovementSlot(slot)) return; - if (HasFlag(MotionMasterFlags.Update)) + if (HasFlag(MotionMasterFlags.Delayed)) _delayedActions.Enqueue(new DelayedAction(() => Add(movement, slot), MotionMasterDelayedActionType.Add)); else DirectAdd(movement, slot); @@ -341,7 +350,7 @@ namespace Game.Movement if (movement == null || IsInvalidMovementSlot(slot)) return; - if (HasFlag(MotionMasterFlags.Update)) + if (HasFlag(MotionMasterFlags.Delayed)) { _delayedActions.Enqueue(new DelayedAction(() => Remove(movement, slot), MotionMasterDelayedActionType.Remove)); return; @@ -373,7 +382,7 @@ namespace Game.Movement if (IsInvalidMovementGeneratorType(type) || IsInvalidMovementSlot(slot)) return; - if (HasFlag(MotionMasterFlags.Update)) + if (HasFlag(MotionMasterFlags.Delayed)) { _delayedActions.Enqueue(new DelayedAction(() => Remove(type, slot), MotionMasterDelayedActionType.RemoveType)); return; @@ -403,7 +412,7 @@ namespace Game.Movement public void Clear() { - if (HasFlag(MotionMasterFlags.Update)) + if (HasFlag(MotionMasterFlags.Delayed)) { _delayedActions.Enqueue(new DelayedAction(() => Clear(), MotionMasterDelayedActionType.Clear)); return; @@ -418,7 +427,7 @@ namespace Game.Movement if (IsInvalidMovementSlot(slot)) return; - if (HasFlag(MotionMasterFlags.Update)) + if (HasFlag(MotionMasterFlags.Delayed)) { _delayedActions.Enqueue(new DelayedAction(() => Clear(slot), MotionMasterDelayedActionType.ClearSlot)); return; @@ -442,7 +451,7 @@ namespace Game.Movement public void Clear(MovementGeneratorMode mode) { - if (HasFlag(MotionMasterFlags.Update)) + if (HasFlag(MotionMasterFlags.Delayed)) { _delayedActions.Enqueue(new DelayedAction(() => Clear(mode), MotionMasterDelayedActionType.ClearMode)); return; @@ -457,7 +466,7 @@ namespace Game.Movement public void Clear(MovementGeneratorPriority priority) { - if (HasFlag(MotionMasterFlags.Update)) + if (HasFlag(MotionMasterFlags.Delayed)) { _delayedActions.Enqueue(new DelayedAction(() => Clear(priority), MotionMasterDelayedActionType.ClearPriority)); return; @@ -990,6 +999,15 @@ namespace Game.Movement Add(movement); } + void ResolveDelayedActions() + { + while (_delayedActions.Count != 0) + { + _delayedActions.Peek().Resolve(); + _delayedActions.Dequeue(); + } + } + void Remove(MovementGenerator movement, bool active, bool movementInform) { _generators.Remove(movement);