diff --git a/Source/Game/AI/SmartScripts/SmartAI.cs b/Source/Game/AI/SmartScripts/SmartAI.cs index 4f8288e05..14cb86836 100644 --- a/Source/Game/AI/SmartScripts/SmartAI.cs +++ b/Source/Game/AI/SmartScripts/SmartAI.cs @@ -732,9 +732,16 @@ namespace Game.AI else me.SetWalk(!_run); - Unit charmer = me.GetCharmer(); - if (charmer) - AttackStart(charmer); + if (!me.LastCharmerGUID.IsEmpty()) + { + if (!me.HasReactState(ReactStates.Passive)) + { + Unit lastCharmer = Global.ObjAccessor.GetUnit(me, me.LastCharmerGUID); + if (lastCharmer != null) + me.EngageWithTarget(lastCharmer); + } + me.LastCharmerGUID.Clear(); + } } GetScript().ProcessEventsFor(SmartEvents.Charmed, null, 0, 0, charmed); diff --git a/Source/Game/Entities/Unit/CharmInfo.cs b/Source/Game/Entities/Unit/CharmInfo.cs index 83a91c940..415b369c1 100644 --- a/Source/Game/Entities/Unit/CharmInfo.cs +++ b/Source/Game/Entities/Unit/CharmInfo.cs @@ -41,10 +41,11 @@ namespace Game.Entities for (var i = 0; i < SharedConst.ActionBarIndexMax; ++i) PetActionBar[i] = new UnitActionBarEntry(); - if (_unit.IsTypeId(TypeId.Unit)) + Creature creature = _unit.ToCreature(); + if (creature != null) { - _oldReactState = _unit.ToCreature().GetReactState(); - _unit.ToCreature().SetReactState(ReactStates.Passive); + _oldReactState = creature.GetReactState(); + creature.SetReactState(ReactStates.Passive); } } diff --git a/Source/Game/Entities/Unit/Unit.Pets.cs b/Source/Game/Entities/Unit/Unit.Pets.cs index edc794977..98ebf87f0 100644 --- a/Source/Game/Entities/Unit/Unit.Pets.cs +++ b/Source/Game/Entities/Unit/Unit.Pets.cs @@ -329,13 +329,6 @@ namespace Game.Entities GetMotionMaster().Clear(MovementGeneratorPriority.Normal); StopMoving(); - - // AI will schedule its own change if appropriate - UnitAI ai = GetAI(); - if (ai != null) - ai.OnCharmed(false); - else - ScheduleAIChange(); } else { @@ -345,16 +338,6 @@ namespace Game.Entities if (player.IsAFK()) player.ToggleAFK(); - if (charmer.IsTypeId(TypeId.Unit)) // we are charmed by a creature - { - // change AI to charmed AI on next Update tick - UnitAI ai = GetAI(); - if (ai != null) - ai.OnCharmed(false); - else - player.ScheduleAIChange(); - } - player.SetClientControl(this, false); } } @@ -416,6 +399,16 @@ namespace Game.Entities } AddUnitState(UnitState.Charmed); + + if (!IsPlayer() || !charmer.IsPlayer()) + { + // AI will schedule its own change if appropriate + UnitAI ai = GetAI(); + if (ai != null) + ai.OnCharmed(false); + else + ScheduleAIChange(); + } return true; } @@ -424,10 +417,12 @@ namespace Game.Entities if (!IsCharmed()) return; - if (!charmer) + if (charmer) + Cypher.Assert(charmer == GetCharmer()); + else charmer = GetCharmer(); - if (charmer != GetCharmer()) // one aura overrides another? - return; + + Cypher.Assert(charmer); CharmType type; if (HasUnitState(UnitState.Possessed)) @@ -455,10 +450,6 @@ namespace Game.Entities if (type != CharmType.Vehicle) LastCharmerGUID = charmer.GetGUID(); - // If charmer still exists - if (!charmer) - return; - Cypher.Assert(type != CharmType.Possess || charmer.IsTypeId(TypeId.Player)); Cypher.Assert(type != CharmType.Vehicle || (IsTypeId(TypeId.Unit) && IsVehicle())); @@ -500,6 +491,20 @@ namespace Game.Entities } } + Player player = ToPlayer(); + if (player != null) + player.SetClientControl(this, true); + + if (playerCharmer && this != charmer.GetFirstControlled()) + playerCharmer.SendRemoveControlBar(); + + // a guardian should always have charminfo + if (!IsGuardian()) + DeleteCharmInfo(); + + // reset confused movement for example + ApplyControlStatesIfNeeded(); + if (!IsPlayer() || charmer.IsCreature()) { UnitAI charmedAI = GetAI(); @@ -508,19 +513,6 @@ namespace Game.Entities else ScheduleAIChange(); } - - Player player = ToPlayer(); - if (player != null) - player.SetClientControl(this, true); - - // a guardian should always have charminfo - if (playerCharmer && this != charmer.GetFirstControlled()) - playerCharmer.SendRemoveControlBar(); - else if (IsTypeId(TypeId.Player) || (IsTypeId(TypeId.Unit) && !IsGuardian())) - DeleteCharmInfo(); - - // reset confused movement for example - ApplyControlStatesIfNeeded(); } public void GetAllMinionsByEntry(List Minions, uint entry) diff --git a/Source/Game/Movement/Generators/RandomMovement.cs b/Source/Game/Movement/Generators/RandomMovement.cs index e8bef3b78..28b50924c 100644 --- a/Source/Game/Movement/Generators/RandomMovement.cs +++ b/Source/Game/Movement/Generators/RandomMovement.cs @@ -109,7 +109,7 @@ namespace Game.Movement if (owner == null) return; - if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) + if (owner.HasUnitState(UnitState.NotMove | UnitState.LostControl) || owner.IsMovementPreventedByCasting()) { AddFlag(MovementGeneratorFlags.Interrupted); owner.StopMoving(); diff --git a/Source/Game/Movement/Generators/WaypointMovement.cs b/Source/Game/Movement/Generators/WaypointMovement.cs index e6a6b6e12..ee679ef76 100644 --- a/Source/Game/Movement/Generators/WaypointMovement.cs +++ b/Source/Game/Movement/Generators/WaypointMovement.cs @@ -140,7 +140,7 @@ namespace Game.Movement if (HasFlag(MovementGeneratorFlags.Finalized | MovementGeneratorFlags.Paused) || _path == null || _path.nodes.Empty()) return true; - if (owner.HasUnitState(UnitState.NotMove) || owner.IsMovementPreventedByCasting()) + if (owner.HasUnitState(UnitState.NotMove | UnitState.LostControl) || owner.IsMovementPreventedByCasting()) { AddFlag(MovementGeneratorFlags.Interrupted); owner.StopMoving();