aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2018-08-23 14:33:28 +0200
committerTreeston <treeston.mmoc@gmail.com>2018-08-23 16:34:42 +0200
commit042f5515e4f3e52b0d2e23d9b9e147041849ce12 (patch)
treee9bd421089edfd6098a96300393d086875f9a054 /src
parent0e4a49b0a4c86eb4a2d0d128e24bc8aaabb47e31 (diff)
Core/AI: Clean up charm AI handling, we now have two unique_ptr instead of a crapton of booleans
Diffstat (limited to 'src')
-rw-r--r--src/server/game/AI/CoreAI/CombatAI.cpp7
-rw-r--r--src/server/game/AI/CoreAI/CombatAI.h2
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.cpp6
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.h4
-rw-r--r--src/server/game/AI/CoreAI/PetAI.cpp6
-rw-r--r--src/server/game/AI/CoreAI/PetAI.h2
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.cpp6
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h7
-rw-r--r--src/server/game/AI/CreatureAI.cpp10
-rw-r--r--src/server/game/AI/CreatureAI.h2
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.cpp13
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.h4
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp4
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp7
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.cpp11
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.cpp2
-rw-r--r--src/server/game/Combat/CombatManager.cpp20
-rw-r--r--src/server/game/Combat/ThreatManager.cpp8
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp87
-rw-r--r--src/server/game/Entities/Creature/Creature.h4
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.cpp6
-rw-r--r--src/server/game/Entities/Player/Player.cpp9
-rw-r--r--src/server/game/Entities/Player/Player.h2
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp232
-rw-r--r--src/server/game/Entities/Unit/Unit.h16
-rwxr-xr-xsrc/server/game/Entities/Vehicle/Vehicle.cpp6
-rw-r--r--src/server/game/Events/GameEventMgr.cpp2
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.cpp4
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h3
-rw-r--r--src/server/game/Handlers/PetHandler.cpp5
-rw-r--r--src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp5
-rw-r--r--src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp5
-rw-r--r--src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp4
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp22
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp4
-rw-r--r--src/server/game/Spells/Spell.cpp18
-rw-r--r--src/server/scripts/Commands/cs_debug.cpp4
-rw-r--r--src/server/scripts/Commands/cs_npc.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp2
-rw-r--r--src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp2
-rw-r--r--src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp2
-rw-r--r--src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp2
-rw-r--r--src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp4
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp11
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp2
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp4
-rw-r--r--src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp2
-rw-r--r--src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp21
-rw-r--r--src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp2
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp4
-rw-r--r--src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp2
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp2
-rw-r--r--src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp2
-rw-r--r--src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp7
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp8
-rw-r--r--src/server/scripts/Northrend/VioletHold/boss_moragg.cpp14
-rw-r--r--src/server/scripts/Northrend/VioletHold/violet_hold.cpp4
-rw-r--r--src/server/scripts/Northrend/zone_storm_peaks.cpp2
-rw-r--r--src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp17
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp10
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp2
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp4
66 files changed, 305 insertions, 400 deletions
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp
index 680b5ebb7c3..60ed90b8507 100644
--- a/src/server/game/AI/CoreAI/CombatAI.cpp
+++ b/src/server/game/AI/CoreAI/CombatAI.cpp
@@ -288,13 +288,14 @@ void VehicleAI::UpdateAI(uint32 diff)
}
}
-void VehicleAI::OnCharmed(bool apply)
+void VehicleAI::OnCharmed(bool /*isNew*/)
{
- if (!me->GetVehicleKit()->IsVehicleInUse() && !apply && m_HasConditions) // was used and has conditions
+ bool const charmed = me->IsCharmed();
+ if (!me->GetVehicleKit()->IsVehicleInUse() && !charmed && m_HasConditions) // was used and has conditions
{
m_DoDismiss = true; // needs reset
}
- else if (apply)
+ else if (charmed)
m_DoDismiss = false; // in use again
m_DismissTimer = VEHICLE_DISMISS_TIME; // reset timer
diff --git a/src/server/game/AI/CoreAI/CombatAI.h b/src/server/game/AI/CoreAI/CombatAI.h
index a27c8fc64ef..7c4525d1b0d 100644
--- a/src/server/game/AI/CoreAI/CombatAI.h
+++ b/src/server/game/AI/CoreAI/CombatAI.h
@@ -103,7 +103,7 @@ struct TC_GAME_API VehicleAI : public CreatureAI
void UpdateAI(uint32 diff) override;
void MoveInLineOfSight(Unit*) override { }
void AttackStart(Unit*) override { }
- void OnCharmed(bool apply) override;
+ void OnCharmed(bool isNew) override;
static int32 Permissible(Creature const* creature);
diff --git a/src/server/game/AI/CoreAI/PassiveAI.cpp b/src/server/game/AI/CoreAI/PassiveAI.cpp
index f0c8958a14c..52b04cc90a0 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.cpp
+++ b/src/server/game/AI/CoreAI/PassiveAI.cpp
@@ -69,12 +69,6 @@ void PossessedAI::KilledUnit(Unit* victim)
victim->RemoveFlag(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE);
}
-void PossessedAI::OnCharmed(bool /*apply*/)
-{
- me->NeedChangeAI = true;
- me->IsAIEnabled = false;
-}
-
void CritterAI::DamageTaken(Unit* /*done_by*/, uint32&)
{
if (!me->HasUnitState(UNIT_STATE_FLEEING))
diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h
index 93b2577e9f3..ce4efe52372 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.h
+++ b/src/server/game/AI/CoreAI/PassiveAI.h
@@ -46,8 +46,6 @@ class TC_GAME_API PossessedAI : public CreatureAI
void JustDied(Unit*) override;
void KilledUnit(Unit* victim) override;
- void OnCharmed(bool /*apply*/) override;
-
static int32 Permissible(Creature const* /*creature*/) { return PERMIT_BASE_NO; }
};
@@ -60,7 +58,7 @@ class TC_GAME_API NullCreatureAI : public CreatureAI
void AttackStart(Unit*) override { }
void UpdateAI(uint32) override { }
void EnterEvadeMode(EvadeReason /*why*/) override { }
- void OnCharmed(bool /*apply*/) override { }
+ void OnCharmed(bool /*isNew*/) override { }
static int32 Permissible(Creature const* creature);
};
diff --git a/src/server/game/AI/CoreAI/PetAI.cpp b/src/server/game/AI/CoreAI/PetAI.cpp
index a16ffc6721d..20a93451c93 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -610,12 +610,6 @@ void PetAI::ReceiveEmote(Player* player, uint32 emote)
}
}
-void PetAI::OnCharmed(bool /*apply*/)
-{
- me->NeedChangeAI = true;
- me->IsAIEnabled = false;
-}
-
void PetAI::ClearCharmInfoFlags()
{
// Quick access to set all flags to FALSE
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index d8b4002293a..d41a1080f6d 100644
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -52,8 +52,6 @@ class TC_GAME_API PetAI : public CreatureAI
void MoveInLineOfSight_Safe(Unit* /*who*/) { } // CreatureAI interferes with returning pets
void EnterEvadeMode(EvadeReason /*why*/) override { } // For fleeing, pets don't use this type of Evade mechanic
- void OnCharmed(bool /*apply*/) override;
-
private:
bool _needToStop(void);
void _stopAttack(void);
diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp
index 0d8700fb091..01c7dd6997f 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -47,6 +47,12 @@ void UnitAI::InitializeAI()
Reset();
}
+void UnitAI::OnCharmed(bool isNew)
+{
+ if (!isNew)
+ me->ScheduleAIChange();
+}
+
void UnitAI::AttackStartCaster(Unit* victim, float dist)
{
if (victim && me->Attack(victim, false))
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index 5b2071b9d8d..a15a15fe199 100644
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -143,8 +143,11 @@ class TC_GAME_API UnitAI
virtual void Reset() { }
- // Called when unit is charmed
- virtual void OnCharmed(bool apply) = 0;
+ // Called when unit's charm state changes with isNew = false
+ // Implementation should call me->ScheduleAIChange() if AI replacement is desired
+ // If this call is made, AI will be replaced on the next tick
+ // When replacement is made, OnCharmed is called with isNew = true
+ virtual void OnCharmed(bool isNew);
// Pass parameters between AI
virtual void DoAction(int32 /*param*/) { }
diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp
index 7b6615f36f1..d322a7d9597 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -33,12 +33,14 @@
#include "World.h"
//Disable CreatureAI when charmed
-void CreatureAI::OnCharmed(bool apply)
+void CreatureAI::OnCharmed(bool isNew)
{
- if (apply)
+ if (isNew && !me->IsCharmed() && me->LastCharmerGUID)
{
- me->NeedChangeAI = true;
- me->IsAIEnabled = false;
+ if (!me->HasReactState(REACT_PASSIVE))
+ if (Unit* lastCharmer = ObjectAccessor::GetUnit(*me, me->LastCharmerGUID))
+ me->EngageWithTarget(lastCharmer);
+ me->LastCharmerGUID.Clear();
}
}
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index f189462bd8b..c4b67765a63 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -139,7 +139,7 @@ class TC_GAME_API CreatureAI : public UnitAI
// Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*type*/, uint32 /*id*/) { }
- void OnCharmed(bool apply) override;
+ void OnCharmed(bool isNew) override;
// Called at reaching home after evade
virtual void JustReachedHome() { }
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp
index 98cfbd287f7..a17e465c131 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.cpp
+++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp
@@ -806,7 +806,11 @@ bool SimpleCharmedPlayerAI::CanAIAttack(Unit const* who) const
Unit* SimpleCharmedPlayerAI::SelectAttackTarget() const
{
if (Unit* charmer = me->GetCharmer())
- return charmer->IsAIEnabled ? charmer->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, ValidTargetSelectPredicate(this)) : charmer->GetVictim();
+ {
+ if (UnitAI* charmerAI = charmer->GetAI())
+ return charmerAI->SelectTarget(SELECT_TARGET_RANDOM, 0, ValidTargetSelectPredicate(this));
+ return charmer->GetVictim();
+ }
return nullptr;
}
@@ -1321,6 +1325,7 @@ PlayerAI::TargetedSpell SimpleCharmedPlayerAI::SelectAppropriateCastForSpec()
static const float CASTER_CHASE_DISTANCE = 28.0f;
void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff)
{
+ printf("SCPAI updateai %u\n", diff);
Creature* charmer = GetCharmer();
if (!charmer)
return;
@@ -1422,9 +1427,10 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff)
}
}
-void SimpleCharmedPlayerAI::OnCharmed(bool apply)
+void SimpleCharmedPlayerAI::OnCharmed(bool isNew)
{
- if (apply)
+ printf("SCPAI oncharm %u\n", isNew);
+ if (me->IsCharmed())
{
me->CastStop();
me->AttackStop();
@@ -1440,4 +1446,5 @@ void SimpleCharmedPlayerAI::OnCharmed(bool apply)
me->GetMotionMaster()->Clear();
me->StopMoving();
}
+ PlayerAI::OnCharmed(isNew);
}
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.h b/src/server/game/AI/PlayerAI/PlayerAI.h
index 348e89ba52c..ed77e46c1eb 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.h
+++ b/src/server/game/AI/PlayerAI/PlayerAI.h
@@ -29,8 +29,6 @@ class TC_GAME_API PlayerAI : public UnitAI
public:
explicit PlayerAI(Player* player);
- void OnCharmed(bool /*apply*/) override { } // charm AI application for players is handled by Unit::SetCharmedBy / Unit::RemoveCharmedBy
-
Creature* GetCharmer() const;
// helper functions to determine player info
@@ -101,7 +99,7 @@ class TC_GAME_API SimpleCharmedPlayerAI : public PlayerAI
public:
SimpleCharmedPlayerAI(Player* player) : PlayerAI(player), _castCheckTimer(2500), _chaseCloser(false), _forceFacing(true), _isFollowing(false) { }
void UpdateAI(uint32 diff) override;
- void OnCharmed(bool apply) override;
+ void OnCharmed(bool isNew) override;
protected:
bool CanAIAttack(Unit const* who) const override;
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index f58cd12829f..d57dc6c4c24 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -54,7 +54,7 @@ void SummonList::DoZoneInCombat(uint32 entry)
{
Creature* summon = ObjectAccessor::GetCreature(*me, *i);
++i;
- if (summon && summon->IsAIEnabled
+ if (summon && summon->IsAIEnabled()
&& (!entry || summon->GetEntry() == entry))
{
summon->AI()->DoZoneInCombat(nullptr);
@@ -118,7 +118,7 @@ void SummonList::DoActionImpl(int32 action, StorageType const& summons)
for (auto const& guid : summons)
{
Creature* summon = ObjectAccessor::GetCreature(*me, guid);
- if (summon && summon->IsAIEnabled)
+ if (summon && summon->IsAIEnabled())
summon->AI()->DoAction(action);
}
}
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
index c82ad99911a..56675f48218 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -154,13 +154,6 @@ void EscortAI::MovementInform(uint32 type, uint32 id)
}
}
-///@todo investigate whether if its necessary to handle anything on charm
-/*
-void EscortAI::OnCharmed(bool apply)
-{
-}
-*/
-
void EscortAI::UpdateAI(uint32 diff)
{
// Waypoint Updating
diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp
index 56bad41e3a4..058652563c3 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -661,17 +661,18 @@ void SmartAI::PassengerBoarded(Unit* who, int8 seatId, bool apply)
GetScript()->ProcessEventsFor(apply ? SMART_EVENT_PASSENGER_BOARDED : SMART_EVENT_PASSENGER_REMOVED, who, uint32(seatId), 0, apply);
}
-void SmartAI::OnCharmed(bool apply)
+void SmartAI::OnCharmed(bool /*isNew*/)
{
- if (apply) // do this before we change charmed state, as charmed state might prevent these things from processing
+ bool const charmed = me->IsCharmed();
+ if (charmed) // do this before we change charmed state, as charmed state might prevent these things from processing
{
if (HasEscortState(SMART_ESCORT_ESCORTING | SMART_ESCORT_PAUSED | SMART_ESCORT_RETURNING))
EndPath(true);
}
- mIsCharmed = apply;
+ mIsCharmed = charmed;
- if (!apply && !me->IsInEvadeMode())
+ if (!charmed && !me->IsInEvadeMode())
{
if (_repeatWaypointPath)
StartPath(mRun, GetScript()->GetPathId(), true);
@@ -682,7 +683,7 @@ void SmartAI::OnCharmed(bool apply)
AttackStart(charmer);
}
- GetScript()->ProcessEventsFor(SMART_EVENT_CHARMED, nullptr, 0, 0, apply);
+ GetScript()->ProcessEventsFor(SMART_EVENT_CHARMED, nullptr, 0, 0, charmed);
}
void SmartAI::DoAction(int32 param)
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index 2164509ac52..b96682564fe 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -140,7 +140,7 @@ class TC_GAME_API SmartAI : public CreatureAI
void InitializeAI() override;
// Called when creature gets charmed by another unit
- void OnCharmed(bool apply) override;
+ void OnCharmed(bool isNew) override;
// Used in scripts to share variables
void DoAction(int32 param = 0) override;
diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp
index cc5aeb2dcd5..7d5bbac162c 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -1037,7 +1037,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u
}
case SMART_ACTION_SET_IN_COMBAT_WITH_ZONE:
{
- if (me && me->IsAIEnabled)
+ if (me && me->IsAIEnabled())
{
me->AI()->DoZoneInCombat();
TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction: SMART_ACTION_SET_IN_COMBAT_WITH_ZONE: Creature %u", me->GetGUID().GetCounter());
diff --git a/src/server/game/Combat/CombatManager.cpp b/src/server/game/Combat/CombatManager.cpp
index 2e90d37bcb7..0024195bbed 100644
--- a/src/server/game/Combat/CombatManager.cpp
+++ b/src/server/game/Combat/CombatManager.cpp
@@ -71,10 +71,12 @@ void CombatReference::EndCombat()
bool const needSecondAI = second->GetCombatManager().UpdateOwnerCombatState();
// ...and if that happened, also notify the AI of it...
- if (needFirstAI && first->IsAIEnabled)
- first->GetAI()->JustExitedCombat();
- if (needSecondAI && second->IsAIEnabled)
- second->GetAI()->JustExitedCombat();
+ if (needFirstAI)
+ if (UnitAI* firstAI = first->GetAI())
+ firstAI->JustExitedCombat();
+ if (needSecondAI)
+ if (UnitAI* secondAI = second->GetAI())
+ secondAI->JustExitedCombat();
// ...and finally clean up the reference object
delete this;
@@ -114,8 +116,8 @@ void PvPCombatReference::SuppressFor(Unit* who)
{
Suppress(who);
if (who->GetCombatManager().UpdateOwnerCombatState())
- if (who->IsAIEnabled)
- who->GetAI()->JustExitedCombat();
+ if (UnitAI* ai = who->GetAI())
+ ai->JustExitedCombat();
}
CombatManager::~CombatManager()
@@ -271,8 +273,8 @@ void CombatManager::SuppressPvPCombat()
for (auto const& pair : _pvpRefs)
pair.second->Suppress(_owner);
if (UpdateOwnerCombatState())
- if (_owner->IsAIEnabled)
- _owner->GetAI()->JustExitedCombat();
+ if (UnitAI* ownerAI = _owner->GetAI())
+ ownerAI->JustExitedCombat();
}
void CombatManager::EndAllPvECombat()
@@ -292,7 +294,7 @@ void CombatManager::EndAllPvPCombat()
/*static*/ void CombatManager::NotifyAICombat(Unit* me, Unit* other)
{
- if (!me->IsAIEnabled)
+ if (!me->IsAIEnabled())
return;
me->GetAI()->JustEnteredCombat(other);
diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp
index 0a28183b3fd..50e195088c1 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -96,7 +96,7 @@ ThreatReference::OnlineState ThreatReference::SelectOnlineState()
return ONLINE_STATE_OFFLINE;
if (!FlagsAllowFighting(_owner, _victim) || !FlagsAllowFighting(_victim, _owner))
return ONLINE_STATE_OFFLINE;
- if (_owner->IsAIEnabled && !_owner->GetAI()->CanAIAttack(_victim))
+ if (_owner->IsAIEnabled() && !_owner->GetAI()->CanAIAttack(_victim))
return ONLINE_STATE_OFFLINE;
// next, check suppression (immunity to chosen melee attack school)
if (_victim->IsImmunedToDamage(_owner->GetMeleeDamageSchoolMask()))
@@ -280,7 +280,7 @@ void ThreatManager::UpdateOnlineStates(bool meThreateningOthers, bool othersThre
static void SaveCreatureHomePositionIfNeed(Creature* c)
{
MovementGeneratorType const movetype = c->GetMotionMaster()->GetCurrentMovementGeneratorType();
- if (movetype == WAYPOINT_MOTION_TYPE || movetype == POINT_MOTION_TYPE || (c->IsAIEnabled && c->AI()->IsEscorted()))
+ if (movetype == WAYPOINT_MOTION_TYPE || movetype == POINT_MOTION_TYPE || (c->IsAIEnabled() && c->AI()->IsEscorted()))
c->SetHomePosition(c->GetPosition());
}
@@ -374,8 +374,8 @@ void ThreatManager::AddThreat(Unit* target, float amount, SpellInfo const* spell
Creature* cOwner = _owner->ToCreature();
ASSERT(cOwner); // if we got here the owner can have a threat list, and must be a creature!
SaveCreatureHomePositionIfNeed(cOwner);
- if (cOwner->IsAIEnabled)
- cOwner->AI()->JustEngagedWith(target);
+ if (CreatureAI* ownerAI = cOwner->AI())
+ ownerAI->JustEngagedWith(target);
}
}
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index 0951a75ead1..6df264d909f 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -272,15 +272,6 @@ Creature::Creature(bool isWorldObject): Unit(isWorldObject), MapObject(), m_grou
m_isTempWorldObject = false;
}
-Creature::~Creature()
-{
- delete i_AI;
- i_AI = nullptr;
-
- //if (m_uint32Values)
- // TC_LOG_ERROR("entities.unit", "Deconstruct Creature Entry = %u", GetEntry());
-}
-
void Creature::AddToWorld()
{
///- Register the creature for guid lookup
@@ -388,8 +379,8 @@ void Creature::RemoveCorpse(bool setSpawnTime, bool destroyForNearbyPlayers)
RemoveAllAuras();
loot.clear();
uint32 respawnDelay = m_respawnDelay;
- if (IsAIEnabled)
- AI()->CorpseRemoved(respawnDelay);
+ if (CreatureAI* ai = AI())
+ ai->CorpseRemoved(respawnDelay);
if (destroyForNearbyPlayers)
DestroyForNearbyPlayers();
@@ -637,7 +628,7 @@ bool Creature::UpdateEntry(uint32 entry, CreatureData const* data /*= nullptr*/,
void Creature::Update(uint32 diff)
{
- if (IsAIEnabled && m_triggerJustAppeared && m_deathState != DEAD)
+ if (IsAIEnabled() && m_triggerJustAppeared && m_deathState != DEAD)
{
if (m_respawnCompatibilityMode && m_vehicleKit)
m_vehicleKit->Reset();
@@ -755,21 +746,8 @@ void Creature::Update(uint32 diff)
m_shouldReacquireTarget = false;
}
- // if creature is charmed, switch to charmed AI (and back)
- if (NeedChangeAI)
- {
- UpdateCharmAI();
- NeedChangeAI = false;
- IsAIEnabled = true;
- if (!IsInEvadeMode() && LastCharmerGUID)
- if (Unit* charmer = ObjectAccessor::GetUnit(*this, LastCharmerGUID))
- EngageWithTarget(charmer);
-
- LastCharmerGUID.Clear();
- }
-
// periodic check to see if the creature has passed an evade boundary
- if (IsAIEnabled && !IsInEvadeMode() && IsEngaged())
+ if (IsAIEnabled() && !IsInEvadeMode() && IsEngaged())
{
if (diff >= m_boundaryCheckTime)
{
@@ -808,14 +786,11 @@ void Creature::Update(uint32 diff)
}
}
- if (!IsInEvadeMode() && IsAIEnabled)
- {
- // do not allow the AI to be changed during update
- m_AI_locked = true;
- i_AI->UpdateAI(diff);
- m_AI_locked = false;
- }
+ // do not allow the AI to be changed during update
+ m_AI_locked = true;
+ Unit::AIUpdateTick(diff);
+ m_AI_locked = false;
// creature can be dead after UpdateAI call
// CORPSE/DEAD state will processed at next tick (in other case death timer will be updated unexpectedly)
@@ -851,8 +826,8 @@ void Creature::Update(uint32 diff)
{
m_cannotReachTimer += diff;
if (m_cannotReachTimer >= CREATURE_NOPATH_EVADE_TIME)
- if (IsAIEnabled)
- AI()->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_PATH);
+ if (CreatureAI* ai = AI())
+ ai->EnterEvadeMode(CreatureAI::EVADE_REASON_NO_PATH);
}
break;
}
@@ -988,13 +963,7 @@ bool Creature::AIM_Destroy()
return false;
}
- ASSERT(!i_disabledAI,
- "The disabled AI wasn't cleared!");
-
- delete i_AI;
- i_AI = nullptr;
-
- IsAIEnabled = false;
+ SetAI(nullptr);
return true;
}
@@ -1007,29 +976,24 @@ bool Creature::AIM_Create(CreatureAI* ai /*= nullptr*/)
return false;
}
- AIM_Destroy();
+ if (!ai)
+ ai = FactorySelector::SelectAI(this);
+
+ SetAI(ai);
Motion_Initialize();
- i_AI = ai ? ai : FactorySelector::SelectAI(this);
return true;
}
-void Creature::AI_InitializeAndEnable()
-{
- IsAIEnabled = true;
- i_AI->InitializeAI();
- // Initialize vehicle
- if (GetVehicleKit())
- GetVehicleKit()->Reset();
-}
-
bool Creature::AIM_Initialize(CreatureAI* ai)
{
if (!AIM_Create(ai))
return false;
- AI_InitializeAndEnable();
+ AI()->InitializeAI();
+ if (GetVehicleKit())
+ GetVehicleKit()->Reset();
return true;
}
@@ -1831,7 +1795,7 @@ bool Creature::IsInvisibleDueToDespawn() const
bool Creature::CanAlwaysSee(WorldObject const* obj) const
{
- if (IsAIEnabled && AI()->CanSeeAlways(obj))
+ if (IsAIEnabled() && AI()->CanSeeAlways(obj))
return true;
return false;
@@ -2079,8 +2043,8 @@ void Creature::Respawn(bool force)
// Re-initialize reactstate that could be altered by movementgenerators
InitializeReactState();
- if (IsAIEnabled) // reset the AI to be sure no dirty or uninitialized values will be used till next tick
- AI()->Reset();
+ if (UnitAI* ai = AI()) // reset the AI to be sure no dirty or uninitialized values will be used till next tick
+ ai->Reset();
m_triggerJustAppeared = true;
@@ -2445,7 +2409,7 @@ bool Creature::CanCreatureAttack(Unit const* victim, bool /*force*/) const
if (!victim->isInAccessiblePlaceFor(this))
return false;
- if (IsAIEnabled && !AI()->CanAIAttack(victim))
+ if (IsAIEnabled() && !AI()->CanAIAttack(victim))
return false;
// we cannot attack in evade mode
@@ -3275,8 +3239,7 @@ void Creature::AtExitCombat()
bool Creature::IsEscortNPC(bool onlyIfActive)
{
- if (!IsAIEnabled)
- return false;
-
- return AI()->IsEscortNPC(onlyIfActive);
+ if (CreatureAI* ai = AI())
+ return ai->IsEscortNPC(onlyIfActive);
+ return false;
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 23e567f7332..f6424e2ec11 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -62,7 +62,6 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
{
public:
explicit Creature(bool isWorldObject = false);
- virtual ~Creature();
void AddToWorld() override;
void RemoveFromWorld() override;
@@ -134,11 +133,10 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool AIM_Destroy();
bool AIM_Create(CreatureAI* ai = nullptr);
- void AI_InitializeAndEnable();
bool AIM_Initialize(CreatureAI* ai = nullptr);
void Motion_Initialize();
- CreatureAI* AI() const { return reinterpret_cast<CreatureAI*>(i_AI); }
+ CreatureAI* AI() const { return reinterpret_cast<CreatureAI*>(GetAI()); }
bool SetWalk(bool enable) override;
bool SetDisableGravity(bool disable, bool packetOnly = false) override;
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index 6bb6d864006..0f92d0e29aa 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.cpp
+++ b/src/server/game/Entities/Creature/TemporarySummon.cpp
@@ -206,9 +206,9 @@ void TempSummon::InitSummon()
Unit* owner = GetSummoner();
if (owner)
{
- if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled)
+ if (owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled())
owner->ToCreature()->AI()->JustSummoned(this);
- if (IsAIEnabled)
+ if (IsAIEnabled())
AI()->IsSummonedBy(owner);
}
}
@@ -242,7 +242,7 @@ void TempSummon::UnSummon(uint32 msTime)
}
Unit* owner = GetSummoner();
- if (owner && owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled)
+ if (owner && owner->GetTypeId() == TYPEID_UNIT && owner->ToCreature()->IsAIEnabled())
owner->ToCreature()->AI()->SummonedCreatureDespawn(this);
AddObjectToRemoveList();
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 8902b8575ea..14492cb203b 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -1058,14 +1058,7 @@ void Player::Update(uint32 p_time)
UpdateAfkReport(now);
- if (IsAIEnabled && GetAI())
- GetAI()->UpdateAI(p_time);
- else if (NeedChangeAI)
- {
- UpdateCharmAI();
- NeedChangeAI = false;
- IsAIEnabled = (GetAI() != nullptr);
- }
+ AIUpdateTick(p_time);
// Update items that have just a limited lifetime
if (now > m_Last_tick)
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 0bb4b515ac0..c6b8511c7ee 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -886,7 +886,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
explicit Player(WorldSession* session);
~Player();
- PlayerAI* AI() const { return reinterpret_cast<PlayerAI*>(i_AI); }
+ PlayerAI* AI() const { return reinterpret_cast<PlayerAI*>(GetAI()); }
void CleanupsBeforeDelete(bool finalCleanup = true) override;
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 09f5ef01a5e..dc948fa498d 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -289,12 +289,11 @@ bool DispelableAura::RollDispel() const
Unit::Unit(bool isWorldObject) :
WorldObject(isWorldObject), m_playerMovingMe(nullptr), m_lastSanctuaryTime(0),
- IsAIEnabled(false), NeedChangeAI(false), LastCharmerGUID(), m_ControlledByPlayer(false),
- movespline(new Movement::MoveSpline()), i_AI(nullptr), i_disabledAI(nullptr),
- m_AutoRepeatFirstCast(false), m_procDeep(0), m_removedAurasCount(0),
- i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_vehicle(nullptr),
- m_vehicleKit(nullptr), m_unitTypeMask(UNIT_MASK_NONE), m_Diminishing(), m_combatManager(this),
- m_threatManager(this), m_comboTarget(nullptr), m_comboPoints(0), m_spellHistory(new SpellHistory(this))
+ LastCharmerGUID(), m_ControlledByPlayer(false),
+ movespline(new Movement::MoveSpline()), m_AutoRepeatFirstCast(false), m_procDeep(0), m_removedAurasCount(0),
+ i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_vehicle(nullptr), m_vehicleKit(nullptr),
+ m_unitTypeMask(UNIT_MASK_NONE), m_Diminishing(), m_combatManager(this), m_threatManager(this),
+ m_comboTarget(nullptr), m_comboPoints(0), m_spellHistory(new SpellHistory(this))
{
m_objectType |= TYPEMASK_UNIT;
m_objectTypeId = TYPEID_UNIT;
@@ -453,6 +452,9 @@ void Unit::Update(uint32 p_time)
UpdateSplineMovement(p_time);
i_motionMaster->Update(p_time);
+
+ if (!i_AI && (GetTypeId() != TYPEID_PLAYER || IsCharmed()))
+ UpdateCharmAI();
}
bool Unit::haveOffhandWeapon() const
@@ -640,11 +642,11 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
{
uint32 rage_damage = damage + (cleanDamage ? cleanDamage->absorbed_damage : 0);
- if (victim->IsAIEnabled)
- victim->GetAI()->DamageTaken(attacker, damage);
+ if (UnitAI* victimAI = victim->GetAI())
+ victimAI->DamageTaken(attacker, damage);
- if (attacker && attacker->IsAIEnabled)
- attacker->GetAI()->DamageDealt(victim, damage, damagetype);
+ if (UnitAI* attackerAI = attacker ? attacker->GetAI() : nullptr)
+ attackerAI->DamageDealt(victim, damage, damagetype);
// Hook for OnDamage Event
sScriptMgr->OnDamage(attacker, victim, damage);
@@ -656,8 +658,8 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
{
for (Unit* controlled : victim->m_Controlled)
if (Creature* cControlled = controlled->ToCreature())
- if (cControlled->IsAIEnabled)
- cControlled->AI()->OwnerAttackedBy(attacker);
+ if (CreatureAI* controlledAI = cControlled->AI())
+ controlledAI->OwnerAttackedBy(attacker);
}
if (victim->ToPlayer()->GetCommandStatus(CHEAT_GOD))
@@ -5544,8 +5546,8 @@ bool Unit::Attack(Unit* victim, bool meleeAttack)
{
for (Unit* controlled : m_Controlled)
if (Creature* cControlled = controlled->ToCreature())
- if (cControlled->IsAIEnabled)
- cControlled->AI()->OwnerAttacked(victim);
+ if (CreatureAI* controlledAI = cControlled->AI())
+ controlledAI->OwnerAttacked(victim);
}
return true;
@@ -6093,14 +6095,11 @@ void Unit::SetCharm(Unit* charm, bool apply)
Unit* victim = healInfo.GetTarget();
uint32 addhealth = healInfo.GetHeal();
- if (healer)
- {
- if (victim->IsAIEnabled)
- victim->GetAI()->HealReceived(healer, addhealth);
+ if (UnitAI* victimAI = victim->GetAI())
+ victimAI->HealReceived(healer, addhealth);
- if (healer->IsAIEnabled)
- healer->GetAI()->HealDone(victim, addhealth);
- }
+ if (UnitAI* healerAI = healer ? healer->GetAI() : nullptr)
+ healerAI->HealDone(victim, addhealth);
if (addhealth)
gain = victim->ModifyHealth(int32(addhealth));
@@ -9408,12 +9407,49 @@ uint32 Unit::GetCreatePowers(Powers power) const
return 0;
}
+void Unit::AIUpdateTick(uint32 diff, bool /*force*/)
+{
+ if (!diff) // some places call with diff = 0, which does nothing (for now), see PR #22296
+ return;
+ if (UnitAI* ai = GetAI())
+ ai->UpdateAI(diff);
+}
+
+void Unit::SetAI(UnitAI* newAI)
+{
+ if (i_AI)
+ AIUpdateTick(0, true); // old AI gets a final tick if enabled
+ i_AI.reset(newAI);
+ AIUpdateTick(0, true); // new AI gets its initial tick
+}
+
+void Unit::ScheduleAIChange()
+{
+ printf("ScheduleAIChange %s\n", GetName().c_str());
+ bool const charmed = IsCharmed();
+ // if charm is applied, we can't have disabled AI already, and vice versa
+ if (charmed)
+ ASSERT(!i_disabledAI, "Attempt to schedule charm AI change on unit that already has disabled AI");
+ else if (GetTypeId() != TYPEID_PLAYER)
+ ASSERT(i_disabledAI, "Attempt to schedule charm ID change on unit that doesn't have disabled AI");
+
+ if (charmed)
+ i_disabledAI = std::move(i_AI);
+ else
+ i_AI.reset();
+}
+
+void Unit::RestoreDisabledAI()
+{
+ ASSERT((GetTypeId() == TYPEID_PLAYER) || i_disabledAI, "Attempt to restore disabled AI on creature without disabled AI");
+ i_AI = std::move(i_disabledAI);
+ AIUpdateTick(0, true);
+}
+
void Unit::AddToWorld()
{
if (!IsInWorld())
- {
WorldObject::AddToWorld();
- }
}
void Unit::RemoveFromWorld()
@@ -9424,8 +9460,8 @@ void Unit::RemoveFromWorld()
if (IsInWorld())
{
m_duringRemoveFromWorld = true;
- if (IsAIEnabled)
- GetAI()->LeavingWorld();
+ if (UnitAI* ai = GetAI())
+ ai->LeavingWorld();
if (IsVehicle())
RemoveVehicleKit();
@@ -9501,80 +9537,44 @@ void Unit::CleanupsBeforeDelete(bool finalCleanup)
void Unit::UpdateCharmAI()
{
- switch (GetTypeId())
+ if (IsCharmed())
{
- case TYPEID_UNIT:
- if (i_disabledAI) // disabled AI must be primary AI
- {
- if (!IsCharmed())
- {
- delete i_AI;
- i_AI = i_disabledAI;
- i_disabledAI = nullptr;
-
- if (GetTypeId() == TYPEID_UNIT)
- ToCreature()->AI()->OnCharmed(false);
- }
- }
- else
- {
- if (IsCharmed())
- {
- i_disabledAI = i_AI;
- if (isPossessed() || IsVehicle())
- i_AI = new PossessedAI(ToCreature());
- else
- i_AI = new PetAI(ToCreature());
- }
- }
- break;
- case TYPEID_PLAYER:
+ UnitAI* newAI = nullptr;
+ if (GetTypeId() == TYPEID_PLAYER)
{
- if (IsCharmed()) // if we are currently being charmed, then we should apply charm AI
+ if (Unit* charmer = GetCharmer())
{
- i_disabledAI = i_AI;
-
- UnitAI* newAI = nullptr;
// first, we check if the creature's own AI specifies an override playerai for its owned players
- if (Unit* charmer = GetCharmer())
- {
- if (Creature* creatureCharmer = charmer->ToCreature())
- {
- if (PlayerAI* charmAI = creatureCharmer->IsAIEnabled ? creatureCharmer->AI()->GetAIForCharmedPlayer(ToPlayer()) : nullptr)
- newAI = charmAI;
- }
- else
- {
- TC_LOG_ERROR("misc", "Attempt to assign charm AI to player %s who is charmed by non-creature %s.", GetGUID().ToString().c_str(), GetCharmerGUID().ToString().c_str());
- }
- }
- if (!newAI) // otherwise, we default to the generic one
- newAI = new SimpleCharmedPlayerAI(ToPlayer());
- i_AI = newAI;
- newAI->OnCharmed(true);
- }
- else
- {
- if (i_AI)
+ if (Creature* creatureCharmer = charmer->ToCreature())
{
- // we allow the charmed PlayerAI to clean up
- i_AI->OnCharmed(false);
- // then delete it
- delete i_AI;
+ if (CreatureAI* charmerAI = creatureCharmer->AI())
+ newAI = charmerAI->GetAIForCharmedPlayer(ToPlayer());
}
else
- {
- TC_LOG_ERROR("misc", "Attempt to remove charm AI from player %s who doesn't currently have charm AI.", GetGUID().ToString().c_str());
- }
- // and restore our previous PlayerAI (if we had one)
- i_AI = i_disabledAI;
- i_disabledAI = nullptr;
- // IsAIEnabled gets handled in the caller
+ TC_LOG_ERROR("misc", "Attempt to assign charm AI to player %s who is charmed by non-creature %s.", GetGUID().ToString().c_str(), GetCharmerGUID().ToString().c_str());
}
- break;
+ if (!newAI) // otherwise, we default to the generic one
+ newAI = new SimpleCharmedPlayerAI(ToPlayer());
}
- default:
- TC_LOG_ERROR("misc", "Attempt to update charm AI for unit %s, which is neither player nor creature.", GetGUID().ToString().c_str());
+ else
+ {
+ ASSERT(GetTypeId() == TYPEID_UNIT);
+ if (isPossessed() || IsVehicle())
+ newAI = new PossessedAI(ToCreature());
+ else
+ newAI = new PetAI(ToCreature());
+ }
+
+ ASSERT(newAI);
+ i_AI.reset(newAI);
+ newAI->OnCharmed(true);
+ AIUpdateTick(0, true);
+ }
+ else
+ {
+ RestoreDisabledAI();
+ if (i_AI)
+ i_AI->OnCharmed(true);
}
}
@@ -10946,7 +10946,7 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id)
plrVictim->SendDirectMessage(&data);
}
// Call KilledUnit for creatures
- if (attacker && attacker->GetTypeId() == TYPEID_UNIT && attacker->IsAIEnabled)
+ if (attacker && attacker->GetTypeId() == TYPEID_UNIT && attacker->IsAIEnabled())
attacker->ToCreature()->AI()->KilledUnit(victim);
// last damage from non duel opponent or opponent controlled creature
@@ -10973,16 +10973,16 @@ bool Unit::InitTamedPet(Pet* pet, uint8 level, uint32 spell_id)
}
// Call KilledUnit for creatures, this needs to be called after the lootable flag is set
- if (attacker && attacker->GetTypeId() == TYPEID_UNIT && attacker->IsAIEnabled)
+ if (attacker && attacker->GetTypeId() == TYPEID_UNIT && attacker->IsAIEnabled())
attacker->ToCreature()->AI()->KilledUnit(victim);
// Call creature just died function
- if (creature->IsAIEnabled)
- creature->AI()->JustDied(attacker);
+ if (CreatureAI* ai = creature->AI())
+ ai->JustDied(attacker);
if (TempSummon* summon = creature->ToTempSummon())
if (Unit* summoner = summon->GetSummoner())
- if (summoner->ToCreature() && summoner->IsAIEnabled)
+ if (summoner->ToCreature() && summoner->IsAIEnabled())
summoner->ToCreature()->AI()->SummonedCreatureDies(creature, attacker);
// Dungeon specific stuff, only applies to players killing creatures
@@ -11400,7 +11400,11 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
StopMoving();
- ToCreature()->AI()->OnCharmed(true);
+ // AI will schedule its own change if appropriate
+ if (UnitAI* ai = GetAI())
+ ai->OnCharmed(false);
+ else
+ ScheduleAIChange();
}
else if (Player* player = ToPlayer())
{
@@ -11410,12 +11414,10 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au
if (charmer->GetTypeId() == TYPEID_UNIT) // we are charmed by a creature
{
// change AI to charmed AI on next Update tick
- NeedChangeAI = true;
- if (IsAIEnabled)
- {
- IsAIEnabled = false;
- player->AI()->OnCharmed(true);
- }
+ if (UnitAI* ai = GetAI())
+ ai->OnCharmed(false);
+ else
+ player->ScheduleAIChange();
}
player->SetClientControl(this, false);
}
@@ -11517,16 +11519,9 @@ void Unit::RemoveCharmedBy(Unit* charmer)
///@todo Handle SLOT_IDLE motion resume
GetMotionMaster()->InitializeDefault();
- if (Creature* creature = ToCreature())
- {
- // Creature will restore its old AI on next update
- if (creature->AI())
- creature->AI()->OnCharmed(false);
-
- // Vehicle should not attack its passenger after he exists the seat
- if (type != CHARM_TYPE_VEHICLE)
- LastCharmerGUID = ASSERT_NOTNULL(charmer)->GetGUID();
- }
+ // Vehicle should not attack its passenger after he exists the seat
+ if (type != CHARM_TYPE_VEHICLE)
+ LastCharmerGUID = ASSERT_NOTNULL(charmer)->GetGUID();
// If charmer still exists
if (!charmer)
@@ -11573,16 +11568,11 @@ void Unit::RemoveCharmedBy(Unit* charmer)
}
}
- if (Player* player = ToPlayer())
- {
- if (charmer->GetTypeId() == TYPEID_UNIT) // charmed by a creature, this means we had PlayerAI
- {
- NeedChangeAI = true;
- IsAIEnabled = false;
- }
+ if (GetTypeId() != TYPEID_PLAYER || charmer->GetTypeId() == TYPEID_UNIT)
+ GetAI()->OnCharmed(false); // AI will potentially schedule a charm ai update
+ if (Player* player = ToPlayer())
player->SetClientControl(this, true);
- }
// a guardian should always have charminfo
if (playerCharmer && this != charmer->GetFirstControlled())
@@ -12466,7 +12456,7 @@ void Unit::HandleSpellClick(Unit* clicker, int8 seatId /*= -1*/)
}
Creature* creature = ToCreature();
- if (creature && creature->IsAIEnabled)
+ if (creature && creature->IsAIEnabled())
creature->AI()->OnSpellClick(clicker, spellClickHandled);
}
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index dfd1c1e020c..774ba7d5c46 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -28,6 +28,7 @@
#include "UnitDefines.h"
#include "Util.h"
#include <map>
+#include <memory>
#define VISUAL_WAYPOINT 1 // Creature Entry ID used for waypoints show, visible only for GMs
#define WORLD_TRIGGER 12999
@@ -763,8 +764,11 @@ class TC_GAME_API Unit : public WorldObject
virtual ~Unit();
- UnitAI* GetAI() { return i_AI; }
- void SetAI(UnitAI* newAI) { i_AI = newAI; }
+ bool IsAIEnabled() const { return (i_AI != nullptr); }
+ void AIUpdateTick(uint32 diff, bool force = false);
+ UnitAI* GetAI() const { return i_AI.get(); }
+ void SetAI(UnitAI* newAI);
+ void ScheduleAIChange();
void AddToWorld() override;
void RemoveFromWorld() override;
@@ -1180,7 +1184,6 @@ class TC_GAME_API Unit : public WorldObject
CharmInfo* GetCharmInfo() { return m_charmInfo; }
CharmInfo* InitCharmInfo();
void DeleteCharmInfo();
- void UpdateCharmAI();
// returns the unit that this player IS CONTROLLING
Unit* GetUnitBeingMoved() const;
// returns the player that this player IS CONTROLLING
@@ -1595,7 +1598,6 @@ class TC_GAME_API Unit : public WorldObject
uint32 GetModelForTotem(PlayerTotemType totemType);
friend class VehicleJoinEvent;
- bool IsAIEnabled, NeedChangeAI;
ObjectGuid LastCharmerGUID;
bool CreateVehicleKit(uint32 id, uint32 creatureEntry);
void RemoveVehicleKit();
@@ -1681,8 +1683,6 @@ class TC_GAME_API Unit : public WorldObject
void BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, Player* target) const override;
- UnitAI* i_AI, *i_disabledAI;
-
void _UpdateSpells(uint32 time);
void _DeleteRemovedAuras();
@@ -1785,6 +1785,10 @@ class TC_GAME_API Unit : public WorldObject
friend class ThreatManager;
ThreatManager m_threatManager;
+ void UpdateCharmAI();
+ void RestoreDisabledAI();
+ std::unique_ptr<UnitAI> i_AI, i_disabledAI;
+
std::unordered_set<AbstractFollower*> m_followingMe;
Unit* m_comboTarget;
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index 528b521f59d..b6a1e2f437c 100755
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -514,7 +514,7 @@ Vehicle* Vehicle::RemovePassenger(Unit* unit)
if (unit->IsFlying())
_me->CastSpell(unit, VEHICLE_SPELL_PARACHUTE, true);
- if (_me->GetTypeId() == TYPEID_UNIT && _me->ToCreature()->IsAIEnabled)
+ if (_me->GetTypeId() == TYPEID_UNIT && _me->ToCreature()->IsAIEnabled())
_me->ToCreature()->AI()->PassengerBoarded(unit, seat->first, false);
if (GetBase()->GetTypeId() == TYPEID_UNIT)
@@ -854,8 +854,8 @@ bool VehicleJoinEvent::Execute(uint64, uint32)
if (Creature* creature = Target->GetBase()->ToCreature())
{
- if (creature->IsAIEnabled)
- creature->AI()->PassengerBoarded(Passenger, Seat->first, true);
+ if (CreatureAI* ai = creature->AI())
+ ai->PassengerBoarded(Passenger, Seat->first, true);
sScriptMgr->OnAddPassenger(Target, Passenger, Seat->first);
diff --git a/src/server/game/Events/GameEventMgr.cpp b/src/server/game/Events/GameEventMgr.cpp
index e2930f42552..89c9d27efe7 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -1687,7 +1687,7 @@ public:
void Visit(std::unordered_map<ObjectGuid, Creature*>& creatureMap)
{
for (auto const& p : creatureMap)
- if (p.second->IsInWorld() && p.second->IsAIEnabled)
+ if (p.second->IsInWorld() && p.second->IsAIEnabled())
p.second->AI()->OnGameEvent(_activate, _eventId);
}
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.cpp b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
index 7fb56b3e686..b60f2ef0af4 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -133,10 +133,10 @@ inline void CreatureUnitRelocationWorker(Creature* c, Unit* u)
if (!c->HasUnitState(UNIT_STATE_SIGHTLESS))
{
- if (c->IsAIEnabled && c->CanSeeOrDetect(u, false, true))
+ if (c->IsAIEnabled() && c->CanSeeOrDetect(u, false, true))
c->AI()->MoveInLineOfSight_Safe(u);
else
- if (u->GetTypeId() == TYPEID_PLAYER && u->HasStealthAura() && c->IsAIEnabled && c->CanSeeOrDetect(u, false, true, true))
+ if (u->GetTypeId() == TYPEID_PLAYER && u->HasStealthAura() && c->IsAIEnabled() && c->CanSeeOrDetect(u, false, true, true))
c->AI()->TriggerAlert(u);
}
}
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index d4687d1b1ee..f55acdca8d7 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -1102,8 +1102,7 @@ namespace Trinity
if (!u->IsWithinLOSInMap(i_enemy))
return;
- if (u->GetAI() && u->IsAIEnabled)
- u->GetAI()->AttackStart(i_enemy);
+ u->EngageWithTarget(i_enemy);
}
private:
Unit* const i_funit;
diff --git a/src/server/game/Handlers/PetHandler.cpp b/src/server/game/Handlers/PetHandler.cpp
index d266fef5a42..3ef03ffc80b 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -209,7 +209,7 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
if (pet->GetVictim())
pet->AttackStop();
- if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature()->IsAIEnabled)
+ if (pet->GetTypeId() != TYPEID_PLAYER && pet->ToCreature()->IsAIEnabled())
{
charmInfo->SetIsCommandAttack(true);
charmInfo->SetIsAtStay(false);
@@ -368,9 +368,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
if (pet->GetVictim() != unit_target)
{
pet->GetMotionMaster()->Clear();
- if (pet->ToCreature()->IsAIEnabled)
+ if (CreatureAI* AI = pet->ToCreature()->AI())
{
- CreatureAI* AI = pet->ToCreature()->AI();
if (PetAI* petAI = dynamic_cast<PetAI*>(AI))
petAI->_AttackStart(unit_target); // force victim switch
else
diff --git a/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp
index 973921aafe1..2bf8c3f48f9 100644
--- a/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/ChaseMovementGenerator.cpp
@@ -52,9 +52,8 @@ static void DoMovementInform(Unit* owner, Unit* target)
if (owner->GetTypeId() != TYPEID_UNIT)
return;
- Creature* creatureOwner = owner->ToCreature();
- if (creatureOwner->IsAIEnabled && creatureOwner->AI())
- creatureOwner->AI()->MovementInform(CHASE_MOTION_TYPE, target->GetGUID().GetCounter());
+ if (CreatureAI* AI = owner->ToCreature()->AI())
+ AI->MovementInform(CHASE_MOTION_TYPE, target->GetGUID().GetCounter());
}
ChaseMovementGenerator::ChaseMovementGenerator(Unit* target, Optional<ChaseRange> range, Optional<ChaseAngle> angle) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle)
diff --git a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp
index e4b7fc78832..adcc35b1c86 100644
--- a/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/FollowMovementGenerator.cpp
@@ -31,9 +31,8 @@ static void DoMovementInform(Unit* owner, Unit* target)
if (owner->GetTypeId() != TYPEID_UNIT)
return;
- Creature* creatureOwner = owner->ToCreature();
- if (creatureOwner->IsAIEnabled && creatureOwner->AI())
- creatureOwner->AI()->MovementInform(FOLLOW_MOTION_TYPE, target->GetGUID().GetCounter());
+ if (CreatureAI* AI = owner->ToCreature()->AI())
+ AI->MovementInform(FOLLOW_MOTION_TYPE, target->GetGUID().GetCounter());
}
FollowMovementGenerator::FollowMovementGenerator(Unit* target, float range, ChaseAngle angle) : AbstractFollower(ASSERT_NOTNULL(target)), _range(range), _angle(angle)
diff --git a/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp
index a90a8b7af36..5df2ea43fef 100644
--- a/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/SplineChainMovementGenerator.cpp
@@ -185,8 +185,8 @@ void SplineChainMovementGenerator::Finalize(Unit* owner, bool active, bool movem
if (movementInform && HasFlag(MOVEMENTGENERATOR_FLAG_INFORM_ENABLED))
{
Creature* ownerCreature = owner->ToCreature();
- if (ownerCreature && ownerCreature->IsAIEnabled)
- ownerCreature->AI()->MovementInform(SPLINE_CHAIN_MOTION_TYPE, _id);
+ if (CreatureAI* AI = ownerCreature ? ownerCreature->AI() : nullptr)
+ AI->MovementInform(SPLINE_CHAIN_MOTION_TYPE, _id);
}
}
diff --git a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
index 7c0336e6523..aa81d6d0d92 100755
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -117,8 +117,8 @@ void WaypointMovementGenerator<Creature>::DoInitialize(Creature* owner)
_nextMoveTime.Reset(1000);
// inform AI
- if (owner->IsAIEnabled)
- owner->AI()->WaypointPathStarted(_path->id);
+ if (CreatureAI* AI = owner->AI())
+ AI->WaypointPathStarted(_path->id);
}
void WaypointMovementGenerator<Creature>::DoReset(Creature* owner)
@@ -256,10 +256,10 @@ void WaypointMovementGenerator<Creature>::OnArrived(Creature* owner)
}
// inform AI
- if (owner->IsAIEnabled)
+ if (CreatureAI* AI = owner->AI())
{
- owner->AI()->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode);
- owner->AI()->WaypointReached(waypoint.id, _path->id);
+ AI->MovementInform(WAYPOINT_MOTION_TYPE, _currentNode);
+ AI->WaypointReached(waypoint.id, _path->id);
}
owner->UpdateCurrentWaypointInfo(waypoint.id, _path->id);
@@ -286,8 +286,8 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun
ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id);
// inform AI
- if (owner->IsAIEnabled)
- owner->AI()->WaypointStarted(_path->nodes[_currentNode].id, _path->id);
+ if (CreatureAI* AI = owner->AI())
+ AI->WaypointStarted(_path->nodes[_currentNode].id, _path->id);
}
else
{
@@ -314,8 +314,8 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun
owner->UpdateCurrentWaypointInfo(0, 0);
// inform AI
- if (owner->IsAIEnabled)
- owner->AI()->WaypointPathEnded(waypoint.id, _path->id);
+ if (CreatureAI* AI = owner->AI())
+ AI->WaypointPathEnded(waypoint.id, _path->id);
return;
}
}
@@ -324,8 +324,8 @@ void WaypointMovementGenerator<Creature>::StartMove(Creature* owner, bool relaun
AddFlag(MOVEMENTGENERATOR_FLAG_INITIALIZED);
// inform AI
- if (owner->IsAIEnabled)
- owner->AI()->WaypointStarted(_path->nodes[_currentNode].id, _path->id);
+ if (CreatureAI* AI = owner->AI())
+ AI->WaypointStarted(_path->nodes[_currentNode].id, _path->id);
}
ASSERT(_currentNode < _path->nodes.size(), "WaypointMovementGenerator::StartMove: tried to reference a node id (%u) which is not included in path (%u)", _currentNode, _path->id);
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 16c6bc1a281..d63eca92429 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -432,7 +432,9 @@ class CreatureGameObjectScriptRegistrySwapHooks
if (!creature->IsAlive())
return;
- creature->AI_InitializeAndEnable();
+ creature->AI()->InitializeAI();
+ if (creature->GetVehicleKit())
+ creature->GetVehicleKit()->Reset();
creature->AI()->EnterEvadeMode();
// Cast a dummy visual spell asynchronously here to signal
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 58c2fa7755a..ec8b1202208 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -2541,18 +2541,16 @@ void Spell::TargetInfo::DoDamageAndTriggers(Spell* spell)
if (_spellHitTarget)
{
//AI functions
- if (_spellHitTarget->GetTypeId() == TYPEID_UNIT)
- {
- if (_spellHitTarget->ToCreature()->IsAIEnabled)
+ if (Creature* cHitTarget = _spellHitTarget->ToCreature())
+ if (CreatureAI* hitTargetAI = cHitTarget->AI())
{
if (spell->m_caster->GetTypeId() == TYPEID_GAMEOBJECT)
- _spellHitTarget->ToCreature()->AI()->SpellHit(spell->m_caster->ToGameObject(), spell->m_spellInfo);
+ hitTargetAI->SpellHit(spell->m_caster->ToGameObject(), spell->m_spellInfo);
else
- _spellHitTarget->ToCreature()->AI()->SpellHit(spell->m_caster->ToUnit(), spell->m_spellInfo);
+ hitTargetAI->SpellHit(spell->m_caster->ToUnit(), spell->m_spellInfo);
}
- }
- if (spell->m_caster->GetTypeId() == TYPEID_UNIT && spell->m_caster->ToCreature()->IsAIEnabled)
+ if (spell->m_caster->GetTypeId() == TYPEID_UNIT && spell->m_caster->ToCreature()->IsAIEnabled())
spell->m_caster->ToCreature()->AI()->SpellHitTarget(_spellHitTarget, spell->m_spellInfo);
else if (spell->m_caster->GetTypeId() == TYPEID_GAMEOBJECT && spell->m_caster->ToGameObject()->AI())
spell->m_caster->ToGameObject()->AI()->SpellHitTarget(_spellHitTarget, spell->m_spellInfo);
@@ -2601,7 +2599,7 @@ void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, uint8 effIndex)
go->AI()->SpellHit(spell->m_caster->ToUnit(), spell->m_spellInfo);
}
- if (spell->m_caster->GetTypeId() == TYPEID_UNIT && spell->m_caster->ToCreature()->IsAIEnabled)
+ if (spell->m_caster->GetTypeId() == TYPEID_UNIT && spell->m_caster->ToCreature()->IsAIEnabled())
spell->m_caster->ToCreature()->AI()->SpellHitTarget(go, spell->m_spellInfo);
else if (spell->m_caster->GetTypeId() == TYPEID_GAMEOBJECT && spell->m_caster->ToGameObject()->AI())
spell->m_caster->ToGameObject()->AI()->SpellHitTarget(go, spell->m_spellInfo);
@@ -3222,8 +3220,8 @@ void Spell::_cast(bool skipCheck)
if (Unit* target = m_targets.GetUnitTarget())
for (Unit* controlled : playerCaster->m_Controlled)
if (Creature* cControlled = controlled->ToCreature())
- if (cControlled->IsAIEnabled)
- cControlled->AI()->OwnerAttacked(target);
+ if (CreatureAI* controlledAI = cControlled->AI())
+ controlledAI->OwnerAttacked(target);
}
SetExecutedCurrently(true);
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 90785c53017..59ea2cde03c 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -1615,10 +1615,8 @@ public:
if (!player)
return false;
Creature* target = handler->getSelectedCreature();
- if (!target || !target->IsAIEnabled || !target->AI())
- {
+ if (!target || !target->IsAIEnabled())
return false;
- }
char* fill_str = args ? strtok((char*)args, " ") : nullptr;
char* duration_str = args ? strtok(nullptr, " ") : nullptr;
diff --git a/src/server/scripts/Commands/cs_npc.cpp b/src/server/scripts/Commands/cs_npc.cpp
index edfa6d15d89..db606da8c86 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -1502,7 +1502,7 @@ public:
return false;
}
- if (!creatureTarget->IsAIEnabled)
+ if (!creatureTarget->IsAIEnabled())
{
handler->PSendSysMessage(LANG_CREATURE_NOT_AI_ENABLED);
handler->SetSentErrorMessage(true);
diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
index 95e6a925ddd..33b490065fb 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -390,7 +390,7 @@ class npc_eye_of_acherus : public CreatureScript
_events.ScheduleEvent(EVENT_MOVE_START, 7s);
}
- void OnCharmed(bool /*apply*/) override { }
+ void OnCharmed(bool /*isNew*/) override { }
void UpdateAI(uint32 diff) override
{
diff --git a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
index c6939561f3b..82151ecbf1e 100644
--- a/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
+++ b/src/server/scripts/EasternKingdoms/zone_stormwind_city.cpp
@@ -336,7 +336,7 @@ public:
if (me->IsSummon())
{
Unit* summoner = me->ToTempSummon()->GetSummoner();
- if (summoner && summoner->GetTypeId() == TYPEID_UNIT && summoner->IsAIEnabled)
+ if (summoner && summoner->GetTypeId() == TYPEID_UNIT && summoner->IsAIEnabled())
{
npc_lord_gregor_lescovar::npc_lord_gregor_lescovarAI* ai =
CAST_AI(npc_lord_gregor_lescovar::npc_lord_gregor_lescovarAI, summoner->GetAI());
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
index 3066efeb80f..e11a398bc6a 100644
--- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
+++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
@@ -1291,7 +1291,7 @@ public:
{
if (TempSummon* summon = me->ToTempSummon())
if (Unit* summoner = summon->GetSummoner())
- if (summoner->IsAIEnabled)
+ if (summoner->IsAIEnabled())
summoner->GetAI()->DoAction(ACTION_FLESH_TENTACLE_KILLED);
}
};
diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
index 4c902435ba8..ebc0c04935d 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -1608,7 +1608,7 @@ class spell_halion_damage_aoe_summon : public SpellScriptLoader
Position pos = caster->GetPosition();
if (Creature* summon = caster->GetMap()->SummonCreature(entry, pos, properties, duration, caster, GetSpellInfo()->Id))
- if (summon->IsAIEnabled)
+ if (summon->IsAIEnabled())
summon->AI()->SetData(DATA_STACKS_DISPELLED, GetSpellValue()->EffectBasePoints[EFFECT_1]);
}
diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
index b8269474ab3..d0718b0745c 100644
--- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
+++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_northrend_beasts.cpp
@@ -1079,7 +1079,7 @@ class spell_gormok_ride_player : public AuraScript
return;
if (Unit *caster = GetCaster())
- if (caster->IsAIEnabled)
+ if (caster->IsAIEnabled())
caster->GetAI()->SetGUID(target->GetGUID(), DATA_NEW_TARGET);
}
@@ -1300,7 +1300,7 @@ class spell_icehowl_trample : public SpellScript
void CheckTargets(std::list<WorldObject*>& targets)
{
Creature* caster = GetCaster()->ToCreature();
- if (!caster || !caster->IsAIEnabled)
+ if (!caster || !caster->IsAIEnabled())
return;
if (targets.empty())
diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
index cc21eeec7b5..2f351308e9f 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
@@ -447,10 +447,7 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader
return;
Player* pTarget = GetTarget()->ToPlayer();
- oldAI = pTarget->AI();
- oldAIState = pTarget->IsAIEnabled;
GetTarget()->SetAI(new player_overlord_brandAI(pTarget, GetCasterGUID()));
- GetTarget()->IsAIEnabled = true;
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
@@ -458,10 +455,7 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader
if (GetTarget()->GetTypeId() != TYPEID_PLAYER)
return;
- GetTarget()->IsAIEnabled = oldAIState;
- PlayerAI* thisAI = GetTarget()->ToPlayer()->AI();
- GetTarget()->SetAI(oldAI);
- delete thisAI;
+ GetTarget()->SetAI(nullptr);
}
void Register() override
@@ -469,9 +463,6 @@ class spell_tyrannus_overlord_brand : public SpellScriptLoader
AfterEffectApply += AuraEffectApplyFn(spell_tyrannus_overlord_brand_AuraScript::OnApply, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
AfterEffectRemove += AuraEffectRemoveFn(spell_tyrannus_overlord_brand_AuraScript::OnRemove, EFFECT_0, SPELL_AURA_DUMMY, AURA_EFFECT_HANDLE_REAL);
}
-
- PlayerAI* oldAI = nullptr;
- bool oldAIState = false;
};
AuraScript* GetAuraScript() const override
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
index e80d238d7c9..b9fb998dd9f 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
@@ -1792,7 +1792,7 @@ class npc_gunship_cannon : public CreatureScript
{
}
- void OnCharmed(bool /*apply*/) override { }
+ void OnCharmed(bool /*isNew*/) override { }
void PassengerBoarded(Unit* /*passenger*/, int8 /*seat*/, bool apply) override
{
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
index 1d107a720fc..bb1e60e6d96 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -630,7 +630,7 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader
bool Load() override
{
- return GetCaster()->GetTypeId() == TYPEID_UNIT && GetCaster()->IsAIEnabled;
+ return GetCaster()->GetTypeId() == TYPEID_UNIT && GetCaster()->IsAIEnabled();
}
SpellCastResult CheckCast()
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
index 0878b5645f5..8d56c9cfb18 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -2367,8 +2367,8 @@ class spell_the_lich_king_quake : public SpellScriptLoader
void HandleSendEvent(SpellEffIndex /*effIndex*/)
{
- if (GetCaster()->IsAIEnabled)
- GetCaster()->GetAI()->DoAction(ACTION_START_ATTACK);
+ if (UnitAI* AI = GetCaster()->GetAI())
+ AI->DoAction(ACTION_START_ATTACK);
}
void Register() override
diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
index 95360a368ed..924a400da2a 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
@@ -1279,7 +1279,7 @@ class spell_dreamwalker_summon_suppresser : public SpellScriptLoader
void HandleSummon(Unit* caster)
{
- if (!caster || !caster->IsAIEnabled)
+ if (!caster || !caster->IsAIEnabled())
return;
std::list<Creature*> summoners;
diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp
index e6bd23bde49..2b6968d26ea 100644
--- a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp
+++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp
@@ -216,24 +216,11 @@ class npc_dk_understudy : public CreatureScript
DoMeleeAttackIfReady();
}
- void OnCharmed(bool apply) override
+ void OnCharmed(bool isNew) override
{
- ScriptedAI::OnCharmed(apply);
- if (apply)
- {
- if (!me->IsInCombat())
- JustEngagedWith(nullptr);
- me->StopMoving();
- me->SetReactState(REACT_PASSIVE);
- _charmer = me->GetCharmerGUID();
- }
- else
- {
- me->SetReactState(REACT_AGGRESSIVE);
- if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmer))
- AddThreat(charmer, 100000.0f);
- DoZoneInCombat();
- }
+ if (me->IsCharmed() && !me->IsEngaged())
+ JustEngagedWith(nullptr);
+ ScriptedAI::OnCharmed(isNew);
}
private:
InstanceScript* const _instance;
diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
index b718655ceb3..675ca6fcd9c 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -836,7 +836,7 @@ public:
{
Creature* casterDiskSummon = me->SummonCreature(NPC_HOVER_DISK_CASTER, RangeHoverDisksSpawnPositions[rangeDisks]);
- if (casterDiskSummon->IsAIEnabled)
+ if (casterDiskSummon->IsAIEnabled())
casterDiskSummon->AI()->DoAction(rangeDisks);
}
@@ -857,7 +857,7 @@ public:
{
Creature* casterDiskSummon = me->SummonCreature(NPC_HOVER_DISK_CASTER, RangeHoverDisksSpawnPositions[rangeDisks]);
- if (casterDiskSummon->IsAIEnabled)
+ if (casterDiskSummon->IsAIEnabled())
casterDiskSummon->AI()->DoAction(rangeDisks);
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
index 0da39233faa..3e95824e546 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_algalon_the_observer.cpp
@@ -1232,7 +1232,7 @@ class spell_algalon_big_bang : public SpellScriptLoader
private:
bool Load() override
{
- return GetCaster()->GetTypeId() == TYPEID_UNIT && GetCaster()->IsAIEnabled;
+ return GetCaster()->GetTypeId() == TYPEID_UNIT;
}
void CountTargets(std::list<WorldObject*>& targets)
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
index 3292edc24e2..413af0ef1f1 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
@@ -550,7 +550,7 @@ class spell_auriaya_agro_creator : public SpellScript
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
{
Creature* caster = GetCaster()->ToCreature();
- if (!caster || !caster->IsAIEnabled || caster->HasReactState(REACT_PASSIVE))
+ if (!caster || !caster->IsAIEnabled() || caster->HasReactState(REACT_PASSIVE))
return;
if (Unit* target = caster->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, CatsTargetSelector(caster, 5.0f, 10.0f)))
@@ -580,7 +580,7 @@ class spell_auriaya_random_agro_periodic : public AuraScript
void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
{
Creature* owner = GetUnitOwner()->ToCreature();
- if (!owner || !owner->IsAIEnabled || owner->HasReactState(REACT_PASSIVE))
+ if (!owner || !owner->IsAIEnabled() || owner->HasReactState(REACT_PASSIVE))
return;
bool farTarget = true;
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
index 86e6eca283f..042a5adce34 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
@@ -495,8 +495,8 @@ class achievement_ignis_shattered : public AchievementCriteriaScript
bool OnCheck(Player* /*source*/, Unit* target) override
{
- if (target && target->IsAIEnabled)
- return target->GetAI()->GetData(DATA_SHATTERED) != 0;
+ if (UnitAI* ai = target ? target->GetAI() : nullptr)
+ return ai->GetData(DATA_SHATTERED) != 0;
return false;
}
diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
index fd96955add0..6cf9fa22145 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
@@ -1711,7 +1711,7 @@ class achievement_iron_dwarf_medium_rare : public AchievementCriteriaScript
bool OnCheck(Player* /*player*/, Unit* target) override
{
- return target && target->IsAIEnabled && target->GetAI()->GetData(DATA_IRON_DWARF_MEDIUM_RARE);
+ return target && target->GetAI() && target->GetAI()->GetData(DATA_IRON_DWARF_MEDIUM_RARE);
}
};
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp
index 2a392030b0f..be1b482aa60 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp
@@ -373,7 +373,7 @@ class achievement_on_the_rocks : public AchievementCriteriaScript
bool OnCheck(Player* /*source*/, Unit* target) override
{
- return target && target->IsAIEnabled && target->GetAI()->GetData(DATA_ON_THE_ROCKS);
+ return target && target->GetAI() && target->GetAI()->GetData(DATA_ON_THE_ROCKS);
}
};
diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
index 07780da659b..96ea8405b0a 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_svala.cpp
@@ -606,7 +606,7 @@ class achievement_incredible_hulk : public AchievementCriteriaScript
bool OnCheck(Player* /*player*/, Unit* target) override
{
- return target && target->IsAIEnabled && target->GetAI()->GetData(DATA_INCREDIBLE_HULK);
+ return target && target->GetAI() && target->GetAI()->GetData(DATA_INCREDIBLE_HULK);
}
};
diff --git a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp
index d9800fab916..9752d775fba 100644
--- a/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp
+++ b/src/server/scripts/Northrend/VaultOfArchavon/boss_toravon.cpp
@@ -181,13 +181,12 @@ class spell_toravon_random_aggro : public SpellScript
void HandleScript(SpellEffIndex /*effIndex*/)
{
Creature* caster = GetCaster()->ToCreature();
- if (!caster->IsAIEnabled)
- return;
caster->GetThreatManager().ResetAllThreat();
- if (Unit* target = caster->AI()->SelectTarget(SELECT_TARGET_RANDOM, 1))
- caster->GetThreatManager().AddThreat(target, 1000000);
+ if (CreatureAI* ai = caster->AI())
+ if (Unit* target = ai->SelectTarget(SELECT_TARGET_RANDOM, 1))
+ caster->GetThreatManager().AddThreat(target, 1000000);
}
void Register() override
diff --git a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp
index cc92cf2bd85..40169d95b2a 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_ichoron.cpp
@@ -324,8 +324,8 @@ class spell_ichoron_drained : public SpellScriptLoader
GetTarget()->RemoveFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_FEIGN_DEATH);
if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_EXPIRE)
- if (GetTarget()->IsAIEnabled)
- GetTarget()->GetAI()->DoAction(ACTION_DRAINED);
+ if (UnitAI* ai = GetTarget()->GetAI())
+ ai->DoAction(ACTION_DRAINED);
}
void Register() override
@@ -398,8 +398,8 @@ class spell_ichoron_protective_bubble : public SpellScriptLoader
{
//if (GetTargetApplication()->GetRemoveMode() == AURA_REMOVE_BY_ENEMY_SPELL)
if (GetAura()->GetCharges() <= 1)
- if (GetTarget()->IsAIEnabled)
- GetTarget()->GetAI()->DoAction(ACTION_PROTECTIVE_BUBBLE_SHATTERED);
+ if (UnitAI* targetAI = GetTarget()->GetAI())
+ targetAI->DoAction(ACTION_PROTECTIVE_BUBBLE_SHATTERED);
}
void Register() override
diff --git a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp
index fbff39951d7..b9b73d0bcc5 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp
@@ -111,14 +111,12 @@ class spell_moragg_ray : public SpellScriptLoader
{
PreventDefaultAction();
- if (!GetTarget()->IsAIEnabled)
- return;
-
- if (Unit* target = GetTarget()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
- {
- uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
- GetTarget()->CastSpell(target, triggerSpell, aurEff);
- }
+ if (UnitAI* AI = GetTarget()->GetAI())
+ if (Unit* target = AI->SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
+ {
+ uint32 triggerSpell = GetSpellInfo()->Effects[aurEff->GetEffIndex()].TriggerSpell;
+ GetTarget()->CastSpell(target, triggerSpell, aurEff);
+ }
}
void Register() override
diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
index 3487fcdd92a..a59f999fadf 100644
--- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
+++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
@@ -1367,8 +1367,8 @@ class spell_violet_hold_portal_periodic : public SpellScriptLoader
void PeriodicTick(AuraEffect const* aurEff)
{
PreventDefaultAction();
- if (GetTarget()->IsAIEnabled)
- GetTarget()->GetAI()->SetData(DATA_PORTAL_PERIODIC_TICK, aurEff->GetTickNumber());
+ if (UnitAI* targetAI = GetTarget()->GetAI())
+ targetAI->SetData(DATA_PORTAL_PERIODIC_TICK, aurEff->GetTickNumber());
}
void Register() override
diff --git a/src/server/scripts/Northrend/zone_storm_peaks.cpp b/src/server/scripts/Northrend/zone_storm_peaks.cpp
index 302cdd7704a..9fc29686972 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -364,7 +364,7 @@ public:
}
void JustDied(Unit* /*killer*/) override { }
- void OnCharmed(bool /*apply*/) override { }
+ void OnCharmed(bool /*isNew*/) override { }
void UpdateAI(uint32 diff) override
{
diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp
index 850e3379213..81dcb72821b 100644
--- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp
+++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_blackheart_the_inciter.cpp
@@ -58,16 +58,15 @@ enum Events
class BlackheartCharmedPlayerAI : public SimpleCharmedPlayerAI
{
using SimpleCharmedPlayerAI::SimpleCharmedPlayerAI;
- void OnCharmed(bool apply) override
+ void OnCharmed(bool isNew) override
{
- SimpleCharmedPlayerAI::OnCharmed(apply);
- if (!me->GetMap()->IsDungeon())
- return;
- if (Creature* blackheart = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(DATA_BLACKHEART_THE_INCITER)))
- {
- blackheart->AI()->SetData(0, apply);
- blackheart->GetThreatManager().AddThreat(me, 0.0f);
- }
+ if (me->GetMap()->IsDungeon())
+ if (Creature* blackheart = ObjectAccessor::GetCreature(*me, me->GetInstanceScript()->GetGuidData(DATA_BLACKHEART_THE_INCITER)))
+ {
+ blackheart->AI()->SetData(0, me->IsCharmed());
+ blackheart->GetThreatManager().AddThreat(me, 0.0f);
+ }
+ SimpleCharmedPlayerAI::OnCharmed(isNew);
}
};
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index 9d79f6d2398..5dbad258d65 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -2914,20 +2914,14 @@ public:
if (ghoulGuid.IsEmpty())
return;
- oldAI = player->AI();
- oldAIState = player->IsAIEnabled;
player->SetAI(new player_ghoulAI(player, ghoulGuid));
- player->IsAIEnabled = true;
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
Player* player = GetTarget()->ToPlayer();
- player->IsAIEnabled = oldAIState;
- PlayerAI* thisAI = player->AI();
- player->SetAI(oldAI);
- delete thisAI;
+ player->SetAI(nullptr);
// Dismiss ghoul if necessary
if (Creature* ghoul = ObjectAccessor::GetCreature(*player, ghoulGuid))
@@ -2946,8 +2940,6 @@ public:
}
ObjectGuid ghoulGuid;
- PlayerAI* oldAI = nullptr;
- bool oldAIState = false;
};
AuraScript* GetAuraScript() const override
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index 2ff9d51dc8b..543a566df62 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -1647,7 +1647,7 @@ class spell_ethereal_pet_aura : public AuraScript
GetUnitOwner()->GetAllMinionsByEntry(minionList, NPC_ETHEREAL_SOUL_TRADER);
for (Creature* minion : minionList)
{
- if (minion->IsAIEnabled)
+ if (minion->IsAIEnabled())
{
minion->AI()->Talk(SAY_STEAL_ESSENCE);
minion->CastSpell(eventInfo.GetProcTarget(), SPELL_STEAL_ESSENCE_VISUAL);
diff --git a/src/server/scripts/Spells/spell_quest.cpp b/src/server/scripts/Spells/spell_quest.cpp
index 63d084e589b..09c5238bc51 100644
--- a/src/server/scripts/Spells/spell_quest.cpp
+++ b/src/server/scripts/Spells/spell_quest.cpp
@@ -54,8 +54,8 @@ class spell_generic_quest_update_entry_SpellScript : public SpellScript
if (!creatureTarget->IsPet() && creatureTarget->GetEntry() == _originalEntry)
{
creatureTarget->UpdateEntry(_newEntry);
- if (_shouldAttack && creatureTarget->IsAIEnabled)
- creatureTarget->AI()->AttackStart(GetCaster());
+ if (_shouldAttack)
+ creatureTarget->EngageWithTarget(GetCaster());
if (_despawnTime)
creatureTarget->DespawnOrUnsummon(_despawnTime);