diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index cca5ebce937..f2f00a9d7fc 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -285,7 +285,7 @@ void CreatureAI::EngagementOver() bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) { - if (!IsEngaged()) + if (me->IsInEvadeMode()) return false; if (!me->IsAlive()) @@ -305,7 +305,6 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) me->DoNotReacquireSpellFocusTarget(); me->GetSpellHistory()->ResetAllCooldowns(); me->SetTarget(ObjectGuid::Empty); - EngagementOver(); return true; diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index fdb2869a596..aa951c1c4af 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -121,7 +121,7 @@ class TC_GAME_API CreatureAI : public UnitAI virtual void JustEngagedWith(Unit* /*who*/) { } // Called when the creature is killed - virtual void JustDied(Unit* /*killer*/) { if (IsEngaged()) EngagementOver(); } + virtual void JustDied(Unit* /*killer*/) { } // Called when the creature kills a unit virtual void KilledUnit(Unit* /*victim*/) { } diff --git a/src/server/game/Combat/CombatManager.cpp b/src/server/game/Combat/CombatManager.cpp index efd0766e22e..8426a2fb203 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() @@ -140,6 +142,15 @@ void CombatManager::Update(uint32 tdiff) } } +bool CombatManager::HasPvECombatWithPlayers() const +{ + for (std::pair const& reference : _pveRefs) + if (reference.second->GetOther(_owner)->GetTypeId() == TYPEID_PLAYER) + return true; + + return false; +} + bool CombatManager::HasPvPCombat() const { for (auto const& pair : _pvpRefs) @@ -271,8 +282,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() @@ -330,14 +341,14 @@ bool CombatManager::UpdateOwnerCombatState() const { _owner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); _owner->AtEnterCombat(); - if (_owner->GetTypeId() == TYPEID_UNIT) + if (_owner->GetTypeId() != TYPEID_UNIT) _owner->AtEngage(GetAnyTarget()); } else { _owner->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); _owner->AtExitCombat(); - if (_owner->GetTypeId() == TYPEID_UNIT) + if (_owner->GetTypeId() != TYPEID_UNIT) _owner->AtDisengage(); } diff --git a/src/server/game/Combat/CombatManager.h b/src/server/game/Combat/CombatManager.h index 010a72665b1..56f2e085554 100644 --- a/src/server/game/Combat/CombatManager.h +++ b/src/server/game/Combat/CombatManager.h @@ -106,6 +106,7 @@ class TC_GAME_API CombatManager Unit* GetOwner() const { return _owner; } bool HasCombat() const { return HasPvECombat() || HasPvPCombat(); } bool HasPvECombat() const { return !_pveRefs.empty(); } + bool HasPvECombatWithPlayers() const; std::unordered_map const& GetPvECombatRefs() const { return _pveRefs; } bool HasPvPCombat() const; std::unordered_map const& GetPvPCombatRefs() const { return _pvpRefs; } diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index 17f1309d372..0aee0b94476 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -700,7 +700,6 @@ void Creature::Update(uint32 diff) break; GetThreatManager().Update(diff); - if (_spellFocusInfo.delay) { if (_spellFocusInfo.delay <= diff) @@ -753,7 +752,7 @@ void Creature::Update(uint32 diff) if (player->IsGameMaster()) continue; - if (player->IsAlive() && this->IsHostileTo(player)) + if (player->IsAlive() && IsHostileTo(player)) EngageWithTarget(player); } } @@ -762,9 +761,8 @@ void Creature::Update(uint32 diff) } } - if (!IsInEvadeMode() && IsAIEnabled) + if (IsAIEnabled) { - // do not allow the AI to be changed during update m_AI_locked = true; i_AI->UpdateAI(diff); m_AI_locked = false; diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index bd9a316ade4..5ca750b1901 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -7671,8 +7671,8 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier) return; // This will only cause combat - the target will engage once the projectile hits (in DoAllEffectOnTarget) - if (targetInfo.missCondition != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) && (m_spellInfo->HasInitialAggro() || unit->IsEngaged())) - m_caster->SetInCombatWith(unit); + if (m_originalCaster && targetInfo.missCondition != SPELL_MISS_EVADE && !m_originalCaster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)) && (m_spellInfo->HasInitialAggro() || unit->IsEngaged())) + m_originalCaster->SetInCombatWith(unit); for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i) {