diff options
author | Treeston <treeston.mmoc@gmail.com> | 2018-08-23 14:33:28 +0200 |
---|---|---|
committer | Treeston <treeston.mmoc@gmail.com> | 2018-08-23 16:34:42 +0200 |
commit | 042f5515e4f3e52b0d2e23d9b9e147041849ce12 (patch) | |
tree | e9bd421089edfd6098a96300393d086875f9a054 /src | |
parent | 0e4a49b0a4c86eb4a2d0d128e24bc8aaabb47e31 (diff) |
Core/AI: Clean up charm AI handling, we now have two unique_ptr instead of a crapton of booleans
Diffstat (limited to 'src')
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); |