aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2018-08-23 14:33:28 +0200
committerShauren <shauren.trinity@gmail.com>2021-10-22 23:47:51 +0200
commite4e8c1c59c8b37216814526b4d2551f23934f465 (patch)
treea135fb3fc2adff0bded65f29d0e165b668a63c5c /src
parent6a91fe3fbe28e3bf36ab6107b9c6cbb842f65262 (diff)
Core/AI: Clean up charm AI handling, we now have two unique_ptr instead of a crapton of booleans
(cherry picked from commit 042f5515e4f3e52b0d2e23d9b9e147041849ce12)
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.cpp12
-rw-r--r--src/server/game/AI/CreatureAI.h2
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.cpp11
-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.cpp237
-rw-r--r--src/server/game/Entities/Unit/Unit.h15
-rw-r--r--src/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
-rw-r--r--src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp22
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp4
-rw-r--r--src/server/game/Spells/Spell.cpp20
-rw-r--r--src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp6
-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/ZulAman/instance_zulaman.cpp2
-rw-r--r--src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp10
-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.cpp2
-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_generic.cpp2
-rw-r--r--src/server/scripts/Spells/spell_quest.cpp4
67 files changed, 310 insertions, 395 deletions
diff --git a/src/server/game/AI/CoreAI/CombatAI.cpp b/src/server/game/AI/CoreAI/CombatAI.cpp
index f0696db80f3..b4720802236 100644
--- a/src/server/game/AI/CoreAI/CombatAI.cpp
+++ b/src/server/game/AI/CoreAI/CombatAI.cpp
@@ -299,13 +299,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 58a6414b00e..cfec8f91e41 100644
--- a/src/server/game/AI/CoreAI/CombatAI.h
+++ b/src/server/game/AI/CoreAI/CombatAI.h
@@ -102,7 +102,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 02f54b13cd3..701d1a3dc42 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.cpp
+++ b/src/server/game/AI/CoreAI/PassiveAI.cpp
@@ -68,12 +68,6 @@ void PossessedAI::KilledUnit(Unit* victim)
me->RemoveDynamicFlag(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 9dc33ec02b9..d8621ae40f1 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.h
+++ b/src/server/game/AI/CoreAI/PassiveAI.h
@@ -45,8 +45,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; }
};
@@ -59,7 +57,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 de6c5c2308c..1c01ddf55d3 100644
--- a/src/server/game/AI/CoreAI/PetAI.cpp
+++ b/src/server/game/AI/CoreAI/PetAI.cpp
@@ -612,12 +612,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 57cbc9ca404..091b06378ee 100644
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -51,8 +51,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 2665379e779..fe16a56497f 100644
--- a/src/server/game/AI/CoreAI/UnitAI.cpp
+++ b/src/server/game/AI/CoreAI/UnitAI.cpp
@@ -48,6 +48,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 bcfa93f33f3..5e5f657b08a 100644
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -144,8 +144,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 a966829b07f..84c549553dd 100644
--- a/src/server/game/AI/CreatureAI.cpp
+++ b/src/server/game/AI/CreatureAI.cpp
@@ -27,6 +27,7 @@
#include "Map.h"
#include "MapReference.h"
#include "MotionMaster.h"
+#include "ObjectAccessor.h"
#include "Player.h"
#include "SpellMgr.h"
#include "TemporarySummon.h"
@@ -34,13 +35,16 @@
#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.IsEmpty())
{
- 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();
}
+ UnitAI::OnCharmed(isNew);
}
std::unordered_map<std::pair<uint32, Difficulty>, AISpellInfoType> UnitAI::AISpellInfo;
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index f68d76a5780..f2ff2ef4fb5 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -131,7 +131,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 when a spell cast gets interrupted
virtual void OnSpellCastInterrupt(SpellInfo const* /*spell*/) { }
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp
index fb359ea6cb2..9dd296a7924 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.cpp
+++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp
@@ -691,7 +691,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;
}
@@ -1325,9 +1329,9 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff)
}
}
-void SimpleCharmedPlayerAI::OnCharmed(bool apply)
+void SimpleCharmedPlayerAI::OnCharmed(bool isNew)
{
- if (apply)
+ if (me->IsCharmed())
{
me->CastStop();
me->AttackStop();
@@ -1343,4 +1347,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 195f7cb03b2..1e129879bd6 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.h
+++ b/src/server/game/AI/PlayerAI/PlayerAI.h
@@ -28,8 +28,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
@@ -97,7 +95,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 88fd051f2aa..69681e171aa 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -47,7 +47,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);
@@ -111,7 +111,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 a3231bc79b3..adbfa359177 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp
@@ -151,13 +151,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 9ab05c55271..76b3778b060 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.cpp
+++ b/src/server/game/AI/SmartScripts/SmartAI.cpp
@@ -663,17 +663,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);
@@ -684,7 +685,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 6c40f429c13..801981a676a 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -141,7 +141,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 d183409eb62..b019d6816e5 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.cpp
+++ b/src/server/game/AI/SmartScripts/SmartScript.cpp
@@ -1064,7 +1064,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 %s", me->GetGUID().ToString().c_str());
diff --git a/src/server/game/Combat/CombatManager.cpp b/src/server/game/Combat/CombatManager.cpp
index 18e4e011351..68233d45b64 100644
--- a/src/server/game/Combat/CombatManager.cpp
+++ b/src/server/game/Combat/CombatManager.cpp
@@ -70,10 +70,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;
@@ -113,8 +115,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()
@@ -270,8 +272,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()
@@ -291,7 +293,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 c2ff5571012..8ac3828b8cb 100644
--- a/src/server/game/Combat/ThreatManager.cpp
+++ b/src/server/game/Combat/ThreatManager.cpp
@@ -94,7 +94,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()))
@@ -278,7 +278,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());
}
@@ -382,8 +382,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 b0b6ca9b270..303fefc1547 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -318,15 +318,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
@@ -430,8 +421,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();
@@ -691,7 +682,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();
@@ -810,21 +801,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.IsEmpty())
- 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)
{
@@ -863,14 +841,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)
@@ -906,8 +881,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;
}
@@ -1035,13 +1010,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;
}
@@ -1054,29 +1023,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;
}
@@ -1987,7 +1951,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;
@@ -2250,8 +2214,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;
@@ -2616,7 +2580,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
@@ -3432,8 +3396,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 9c53daa0efb..d840f0378f1 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -70,7 +70,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;
@@ -158,11 +157,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()); }
SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType /*attackType*/ = BASE_ATTACK) const override { return m_meleeDamageSchoolMask; }
void SetMeleeDamageSchool(SpellSchools school) { m_meleeDamageSchoolMask = SpellSchoolMask(1 << school); }
diff --git a/src/server/game/Entities/Creature/TemporarySummon.cpp b/src/server/game/Entities/Creature/TemporarySummon.cpp
index 2f2ff710143..1ccb481c8a7 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 c49cc3a4ddb..7b0861bf83b 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -974,14 +974,7 @@ void Player::Update(uint32 p_time)
if (!aura->IsPermanent())
aura->SetDuration(aura->GetSpellInfo()->GetMaxDuration());
- 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 131ea5b775c..988e350e8ba 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1089,7 +1089,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 f1c7b99c186..d4b032ef359 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -299,9 +299,8 @@ SpellNonMeleeDamage::SpellNonMeleeDamage(Unit* _attacker, Unit* _target, SpellIn
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),
+ LastCharmerGUID(), m_ControlledByPlayer(false),
+ movespline(new Movement::MoveSpline()), m_AutoRepeatFirstCast(false), m_procDeep(0), m_removedAurasCount(0),
m_interruptMask(SpellAuraInterruptFlags::None), m_interruptMask2(SpellAuraInterruptFlags2::None),
i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_vehicle(nullptr),
m_vehicleKit(nullptr), m_unitTypeMask(UNIT_MASK_NONE), m_Diminishing(), m_combatManager(this),
@@ -477,6 +476,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
@@ -676,11 +678,11 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
/*static*/ uint32 Unit::DealDamage(Unit* attacker, Unit* victim, uint32 damage, CleanDamage const* cleanDamage, DamageEffectType damagetype, SpellSchoolMask damageSchoolMask, SpellInfo const* spellProto, bool durabilityLoss)
{
- 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);
@@ -692,8 +694,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))
@@ -2885,7 +2887,7 @@ void Unit::InterruptSpell(CurrentSpellTypes spellType, bool withDelayed, bool wi
spell->SetReferencedFromCurrent(false);
}
- if (GetTypeId() == TYPEID_UNIT && IsAIEnabled)
+ if (GetTypeId() == TYPEID_UNIT && IsAIEnabled())
ToCreature()->AI()->OnSpellCastInterrupt(spell->GetSpellInfo());
}
}
@@ -4892,14 +4894,14 @@ void Unit::UpdateStatBuffModForClient(Stats stat)
void Unit::_RegisterDynObject(DynamicObject* dynObj)
{
m_dynObj.push_back(dynObj);
- if (GetTypeId() == TYPEID_UNIT && IsAIEnabled)
+ if (GetTypeId() == TYPEID_UNIT && IsAIEnabled())
ToCreature()->AI()->JustRegisteredDynObject(dynObj);
}
void Unit::_UnregisterDynObject(DynamicObject* dynObj)
{
m_dynObj.remove(dynObj);
- if (GetTypeId() == TYPEID_UNIT && IsAIEnabled)
+ if (GetTypeId() == TYPEID_UNIT && IsAIEnabled())
ToCreature()->AI()->JustUnregisteredDynObject(dynObj);
}
@@ -4975,7 +4977,7 @@ void Unit::AddGameObject(GameObject* gameObj)
GetSpellHistory()->StartCooldown(createBySpell, 0, nullptr, true);
}
- if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsAIEnabled)
+ if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsAIEnabled())
ToCreature()->AI()->JustSummonedGameobject(gameObj);
}
@@ -5009,7 +5011,7 @@ void Unit::RemoveGameObject(GameObject* gameObj, bool del)
m_gameObj.remove(gameObj);
- if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsAIEnabled)
+ if (GetTypeId() == TYPEID_UNIT && ToCreature()->IsAIEnabled())
ToCreature()->AI()->SummonedGameobjectDespawn(gameObj);
if (del)
@@ -5059,14 +5061,14 @@ void Unit::RemoveAllGameObjects()
void Unit::_RegisterAreaTrigger(AreaTrigger* areaTrigger)
{
m_areaTrigger.push_back(areaTrigger);
- if (GetTypeId() == TYPEID_UNIT && IsAIEnabled)
+ if (GetTypeId() == TYPEID_UNIT && IsAIEnabled())
ToCreature()->AI()->JustRegisteredAreaTrigger(areaTrigger);
}
void Unit::_UnregisterAreaTrigger(AreaTrigger* areaTrigger)
{
m_areaTrigger.erase(std::remove(m_areaTrigger.begin(), m_areaTrigger.end(), areaTrigger));
- if (GetTypeId() == TYPEID_UNIT && IsAIEnabled)
+ if (GetTypeId() == TYPEID_UNIT && IsAIEnabled())
ToCreature()->AI()->JustUnregisteredAreaTrigger(areaTrigger);
}
@@ -5501,8 +5503,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;
@@ -6062,14 +6064,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));
@@ -9072,6 +9071,44 @@ int32 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()
+{
+ 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()
{
WorldObject::AddToWorld();
@@ -9087,8 +9124,8 @@ void Unit::RemoveFromWorld()
if (IsInWorld())
{
m_duringRemoveFromWorld = true;
- if (IsAIEnabled)
- GetAI()->LeavingWorld();
+ if (UnitAI* ai = GetAI())
+ ai->LeavingWorld();
if (IsVehicle())
RemoveVehicleKit(true);
@@ -9161,80 +9198,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 = ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PossessedAI"))->Create(ToCreature());
- else
- i_AI = ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PetAI"))->Create(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 = ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PossessedAI"))->Create(ToCreature());
+ else
+ newAI = ASSERT_NOTNULL(sCreatureAIRegistry->GetRegistryItem("PetAI"))->Create(ToCreature());
+ }
+
+ ASSERT(newAI);
+ i_AI.reset(newAI);
+ newAI->OnCharmed(true);
+ AIUpdateTick(0, true);
+ }
+ else
+ {
+ RestoreDisabledAI();
+ if (i_AI)
+ i_AI->OnCharmed(true);
}
}
@@ -10494,7 +10495,7 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
plrVictim->SendDurabilityLoss(plrVictim, loss);
}
// 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
@@ -10521,16 +10522,16 @@ void Unit::SetMeleeAnimKitId(uint16 animKitId)
}
// 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
@@ -10926,7 +10927,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())
{
@@ -10936,12 +10941,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);
}
@@ -11043,16 +11046,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)
@@ -11099,16 +11095,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())
@@ -11824,7 +11815,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 82b94f3b096..df0e080915b 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -764,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;
@@ -1277,7 +1280,6 @@ class TC_GAME_API Unit : public WorldObject
void DeleteCharmInfo();
void SetPetNumberForClient(uint32 petNumber) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::PetNumber), petNumber); }
void SetPetNameTimestamp(uint32 timestamp) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::PetNameTimestamp), timestamp); }
- void UpdateCharmAI();
// returns the unit that this player IS CONTROLLING
Unit* GetUnitBeingMoved() const;
// returns the player that this player IS CONTROLLING
@@ -1751,7 +1753,6 @@ class TC_GAME_API Unit : public WorldObject
uint32 GetModelForForm(ShapeshiftForm form, uint32 spellId) const;
friend class VehicleJoinEvent;
- bool IsAIEnabled, NeedChangeAI;
ObjectGuid LastCharmerGUID;
bool CreateVehicleKit(uint32 id, uint32 creatureEntry, bool loading = false);
void RemoveVehicleKit(bool onRemoveFromWorld = false);
@@ -1851,8 +1852,6 @@ class TC_GAME_API Unit : public WorldObject
void DestroyForPlayer(Player* target) const override;
void ClearUpdateMask(bool remove) override;
- UnitAI* i_AI, *i_disabledAI;
-
void _UpdateSpells(uint32 time);
void _DeleteRemovedAuras();
@@ -1964,6 +1963,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;
bool m_cleanupDone; // lock made to not add stuff after cleanup before delete
diff --git a/src/server/game/Entities/Vehicle/Vehicle.cpp b/src/server/game/Entities/Vehicle/Vehicle.cpp
index 152751c91ad..ad8d4653ce2 100644
--- a/src/server/game/Entities/Vehicle/Vehicle.cpp
+++ b/src/server/game/Entities/Vehicle/Vehicle.cpp
@@ -506,7 +506,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)
@@ -851,8 +851,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 2cfa51dd402..8aaf83018b9 100644
--- a/src/server/game/Events/GameEventMgr.cpp
+++ b/src/server/game/Events/GameEventMgr.cpp
@@ -1661,7 +1661,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 b68d366dbfb..a223e55f0ac 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.cpp
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.cpp
@@ -132,10 +132,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 944649d68ba..2ec61224cd1 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -1160,8 +1160,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 67d9c4f00b0..a92119e7685 100644
--- a/src/server/game/Handlers/PetHandler.cpp
+++ b/src/server/game/Handlers/PetHandler.cpp
@@ -202,7 +202,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);
@@ -373,9 +373,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 91bb0e3540c..e52393a97ad 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 0691ffe0fef..6d2544f8f89 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 6f5c0506b96..543d40eb332 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 e8f9a532194..c6056806c8e 100644
--- a/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
+++ b/src/server/game/Movement/MovementGenerators/WaypointMovementGenerator.cpp
@@ -116,8 +116,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)
@@ -255,10 +255,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);
@@ -285,8 +285,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
{
@@ -313,8 +313,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;
}
}
@@ -323,8 +323,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 b5e587eb149..b1022b43967 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -479,7 +479,9 @@ class CreatureGameObjectAreaTriggerScriptRegistrySwapHooks
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 90d342e1b3d..22a1b24329c 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -2634,18 +2634,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);
@@ -2694,7 +2692,7 @@ void Spell::GOTargetInfo::DoTargetSpellHit(Spell* spell, SpellEffectInfo const&
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);
@@ -3316,8 +3314,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);
@@ -3563,7 +3561,7 @@ void Spell::_cast(bool skipCheck)
// Call CreatureAI hook OnSuccessfulSpellCast
if (Creature* caster = m_originalCaster->ToCreature())
- if (caster->IsAIEnabled)
+ if (caster->IsAIEnabled())
caster->AI()->OnSuccessfulSpellCast(GetSpellInfo());
}
diff --git a/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp b/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp
index 525879f6cc7..f4cdd4c4360 100644
--- a/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp
+++ b/src/server/scripts/Argus/AntorusTheBurningThrone/boss_garothi_worldbreaker.cpp
@@ -560,7 +560,7 @@ class spell_garothi_fel_bombardment_selector : public SpellScript
void HandleWarningEffect(SpellEffIndex /*effIndex*/)
{
Creature* caster = GetCaster() ? GetCaster()->ToCreature() : nullptr;
- if (!caster || !caster->IsAIEnabled)
+ if (!caster || !caster->IsAIEnabled())
return;
Unit* target = GetHitUnit();
@@ -693,7 +693,7 @@ class spell_garothi_decimation_selector : public SpellScript
{
caster->CastSpell(GetHitUnit(), SPELL_DECIMATION_WARNING, true);
if (Creature* decimator = caster->ToCreature())
- if (decimator->IsAIEnabled)
+ if (decimator->IsAIEnabled())
decimator->AI()->Talk(SAY_ANNOUNCE_DECIMATION, GetHitUnit());
}
}
@@ -843,7 +843,7 @@ class spell_garothi_cannon_chooser : public SpellScript
void HandleDummyEffect(SpellEffIndex /*effIndex*/)
{
Creature* caster = GetHitCreature();
- if (!caster || !caster->IsAIEnabled)
+ if (!caster || !caster->IsAIEnabled())
return;
InstanceScript* instance = caster->GetInstanceScript();
diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp
index 752fcc19386..f78442af163 100644
--- a/src/server/scripts/Commands/cs_debug.cpp
+++ b/src/server/scripts/Commands/cs_debug.cpp
@@ -1354,10 +1354,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 8d6ba06b49a..229f1ea9b64 100644
--- a/src/server/scripts/Commands/cs_npc.cpp
+++ b/src/server/scripts/Commands/cs_npc.cpp
@@ -1584,7 +1584,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 95543c71159..b9fc7583725 100644
--- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
+++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter1.cpp
@@ -396,7 +396,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/ZulAman/instance_zulaman.cpp b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp
index 8db37e7275a..3e473f74ad3 100644
--- a/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp
+++ b/src/server/scripts/EasternKingdoms/ZulAman/instance_zulaman.cpp
@@ -226,7 +226,7 @@ class instance_zulaman : public InstanceMapScript
case EVENT_START_ZULAMAN:
if (Creature* voljin = instance->GetCreature(VoljinGUID))
{
- if (voljin->IsAIEnabled)
+ if (voljin->IsAIEnabled())
voljin->AI()->DoAction(ACTION_START_ZULAMAN);
}
break;
diff --git a/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
index 2307954145d..ceda6ec369b 100644
--- a/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
+++ b/src/server/scripts/Kalimdor/Firelands/boss_baleroc.cpp
@@ -326,7 +326,7 @@ class spell_baleroc_blades_of_baleroc : public SpellScript
void ChooseBlade(SpellEffIndex /*effIndex*/)
{
Creature* caster = GetCaster()->ToCreature();
- if (!caster || !caster->IsAIEnabled)
+ if (!caster || !caster->IsAIEnabled())
return;
switch (urand(1, 2))
@@ -364,13 +364,13 @@ class spell_baleroc_inferno_blade : public AuraScript
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
- if (GetTarget()->IsAIEnabled)
+ if (GetTarget()->IsAIEnabled())
GetTarget()->GetAI()->DoAction(ACTION_EQUIP_INFERNO_BLADE);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
- if (GetTarget()->IsAIEnabled)
+ if (GetTarget()->IsAIEnabled())
GetTarget()->GetAI()->DoAction(ACTION_EQUIP_DEFAULT);
}
@@ -393,13 +393,13 @@ class spell_baleroc_decimation_blade : public AuraScript
void OnApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
- if (GetTarget()->IsAIEnabled)
+ if (GetTarget()->IsAIEnabled())
GetTarget()->GetAI()->DoAction(ACTION_EQUIP_DECIMATION_BLADE);
}
void OnRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
{
- if (GetTarget()->IsAIEnabled)
+ if (GetTarget()->IsAIEnabled())
GetTarget()->GetAI()->DoAction(ACTION_EQUIP_DEFAULT);
}
diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp
index 8862eeb7eb4..11415bff291 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 c15529ec5d4..1d24d0e25ac 100644
--- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
+++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp
@@ -1614,7 +1614,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 b2658110776..fef166d403e 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 73fe05ed0f3..0ab9547e3f2 100644
--- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_scourgelord_tyrannus.cpp
@@ -449,10 +449,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*/)
@@ -460,10 +457,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
@@ -471,9 +465,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 7609c5c6992..1efd753228c 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp
@@ -1786,7 +1786,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 0ec4ace8d67..b0daf19085c 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp
@@ -629,7 +629,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 3de744e67aa..f74c3d0395f 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp
@@ -2350,8 +2350,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 35787628e51..e056c325bf9 100644
--- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
+++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp
@@ -1282,7 +1282,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 028bd2d4974..1cad6aa47f8 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 25416696d1f..43d96cea444 100644
--- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
+++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp
@@ -834,7 +834,7 @@ public:
{
Creature* casterDiskSummon = me->SummonCreature(NPC_HOVER_DISK_CASTER, RangeHoverDisksSpawnPositions[rangeDisks]);
- if (casterDiskSummon->IsAIEnabled)
+ if (casterDiskSummon->IsAIEnabled())
casterDiskSummon->AI()->DoAction(rangeDisks);
}
@@ -855,7 +855,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 706bf99204a..2e4a561dc56 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 6f6a52b763a..cd76f07a932 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp
@@ -553,7 +553,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)))
@@ -583,7 +583,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 fe76f6c875d..20074dba079 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_ignis.cpp
@@ -496,8 +496,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 b78f7289f1e..b810c15411a 100644
--- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
+++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_razorscale.cpp
@@ -1709,7 +1709,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 6b4b3a1aa1f..73afc6f7e81 100644
--- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp
+++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp
@@ -372,7 +372,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 334436bb49f..638cc511472 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 126d24da50c..1e20cbb4562 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 c79f707e650..9b72f64d13b 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()->RemoveUnitFlag2(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 2a2737bd127..1f22d400708 100644
--- a/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp
+++ b/src/server/scripts/Northrend/VioletHold/boss_moragg.cpp
@@ -103,7 +103,7 @@ class spell_moragg_ray : public SpellScriptLoader
{
PreventDefaultAction();
- if (!GetTarget()->IsAIEnabled)
+ if (!GetTarget()->GetAI())
return;
if (Unit* target = GetTarget()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 45.0f, true))
diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
index 8febf564b50..7e705934f96 100644
--- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
+++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp
@@ -1368,8 +1368,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 958d068eb79..d64644bab46 100644
--- a/src/server/scripts/Northrend/zone_storm_peaks.cpp
+++ b/src/server/scripts/Northrend/zone_storm_peaks.cpp
@@ -365,7 +365,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 21bf50ee269..8bf5a4cc888 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
@@ -57,16 +57,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_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index c203bda137c..83436b4986e 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -1536,7 +1536,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 991b7d275ec..d429eafd36b 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);