diff options
Diffstat (limited to 'src')
197 files changed, 985 insertions, 1135 deletions
diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h index a2b42011bd8..56e5e3c3aa2 100644 --- a/src/common/Utilities/Containers.h +++ b/src/common/Utilities/Containers.h @@ -87,6 +87,7 @@ namespace Trinity template<class C> inline auto SelectRandomContainerElement(C const& container) -> typename std::add_const<decltype(*std::begin(container))>::type& { + ASSERT(Size(container)); auto it = std::begin(container); std::advance(it, urand(0, uint32(Size(container)) - 1)); return *it; @@ -196,6 +197,7 @@ namespace Trinity { public: IteratorPair() : _iterators() { } + IteratorPair(iterator first, iterator second) : _iterators(first, second) { } IteratorPair(std::pair<iterator, iterator> iterators) : _iterators(iterators) { } iterator begin() const { return _iterators.first; } diff --git a/src/server/game/AI/CoreAI/GuardAI.cpp b/src/server/game/AI/CoreAI/GuardAI.cpp index f216059e492..7f65af41d63 100644 --- a/src/server/game/AI/CoreAI/GuardAI.cpp +++ b/src/server/game/AI/CoreAI/GuardAI.cpp @@ -45,14 +45,9 @@ void GuardAI::UpdateAI(uint32 /*diff*/) bool GuardAI::CanSeeAlways(WorldObject const* obj) { - if (!obj->isType(TYPEMASK_UNIT)) - return false; - - ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) - if ((*itr)->getUnitGuid() == obj->GetGUID()) + if (Unit const* unit = obj->ToUnit()) + if (unit->IsControlledByPlayer() && me->IsEngagedBy(unit)) return true; - return false; } @@ -62,14 +57,14 @@ void GuardAI::EnterEvadeMode(EvadeReason /*why*/) { me->GetMotionMaster()->MoveIdle(); me->CombatStop(true); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); return; } TC_LOG_DEBUG("entities.unit", "Guard entry: %u enters evade mode.", me->GetEntry()); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); // Remove ChaseMovementGenerator from MotionMaster stack list, and add HomeMovementGenerator instead diff --git a/src/server/game/AI/CoreAI/UnitAI.cpp b/src/server/game/AI/CoreAI/UnitAI.cpp index 9f13f7901bc..50a94caa1fa 100644 --- a/src/server/game/AI/CoreAI/UnitAI.cpp +++ b/src/server/game/AI/CoreAI/UnitAI.cpp @@ -103,14 +103,14 @@ bool UnitAI::DoSpellAttackIfReady(uint32 spell) return false; } -Unit* UnitAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, int32 aura) +Unit* UnitAI::SelectTarget(SelectAggroTarget targetType, uint32 position, float dist, bool playerOnly, bool withTank, int32 aura) { - return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, aura)); + return SelectTarget(targetType, position, DefaultTargetSelector(me, dist, playerOnly, withTank, aura)); } -void UnitAI::SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, float dist, bool playerOnly, int32 aura) +void UnitAI::SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, uint32 offset, float dist, bool playerOnly, bool withTank, int32 aura) { - SelectTargetList(targetList, DefaultTargetSelector(me, dist, playerOnly, aura), num, targetType); + SelectTargetList(targetList, num, targetType, offset, DefaultTargetSelector(me, dist, playerOnly, withTank, aura)); } float UnitAI::DoGetSpellMaxRange(uint32 spellId, bool positive) @@ -154,7 +154,7 @@ void UnitAI::DoCast(uint32 spellId) bool playerOnly = spellInfo->HasAttribute(SPELL_ATTR3_ONLY_TARGET_PLAYERS); float range = spellInfo->GetMaxRange(false); - DefaultTargetSelector targetSelector(me, range, playerOnly, -(int32)spellId); + DefaultTargetSelector targetSelector(me, range, playerOnly, true, -(int32)spellId); if (!(spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_VICTIM) && targetSelector(me->GetVictim())) target = me->GetVictim(); @@ -251,7 +251,12 @@ void UnitAI::FillAISpellInfo() ThreatManager& UnitAI::GetThreatManager() { - return me->getThreatManager(); + return me->GetThreatManager(); +} + +void UnitAI::SortByDistance(std::list<Unit*> list, bool ascending) +{ + list.sort(Trinity::ObjectDistanceOrderPred(me, ascending)); } bool DefaultTargetSelector::operator()(Unit const* target) const @@ -262,6 +267,9 @@ bool DefaultTargetSelector::operator()(Unit const* target) const if (!target) return false; + if (target == except) + return false; + if (m_playerOnly && (target->GetTypeId() != TYPEID_PLAYER)) return false; @@ -363,8 +371,8 @@ bool NonTankTargetSelector::operator()(Unit const* target) const if (_playerOnly && target->GetTypeId() != TYPEID_PLAYER) return false; - if (HostileReference* currentVictim = _source->getThreatManager().getCurrentVictim()) - return target->GetGUID() != currentVictim->getUnitGuid(); + if (Unit* currentVictim = _source->GetThreatManager().GetCurrentVictim()) + return target != currentVictim; return target != _source->GetVictim(); } @@ -405,8 +413,3 @@ bool FarthestTargetSelector::operator()(Unit const* target) const return true; } - -void SortByDistanceTo(Unit* reference, std::list<Unit*>& targets) -{ - targets.sort(Trinity::ObjectDistanceOrderPred(reference)); -} diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h index d164b9fe6d5..27542ebd3d1 100644 --- a/src/server/game/AI/CoreAI/UnitAI.h +++ b/src/server/game/AI/CoreAI/UnitAI.h @@ -46,11 +46,11 @@ enum SpellEffIndex : uint8; //Selection method used by SelectTarget enum SelectAggroTarget { - SELECT_TARGET_RANDOM = 0, //Just selects a random target - SELECT_TARGET_TOPAGGRO, //Selects targes from top aggro to bottom - SELECT_TARGET_BOTTOMAGGRO, //Selects targets from bottom aggro to top - SELECT_TARGET_NEAREST, - SELECT_TARGET_FARTHEST + SELECT_TARGET_RANDOM = 0, // just pick a random target + SELECT_TARGET_MAXTHREAT, // prefer targets higher in the threat list + SELECT_TARGET_MINTHREAT, // prefer targets lower in the threat list + SELECT_TARGET_MAXDISTANCE, // prefer targets further from us + SELECT_TARGET_MINDISTANCE // prefer targets closer to us }; // default predicate function to select target based on distance, player and/or aura criteria @@ -59,13 +59,15 @@ struct TC_GAME_API DefaultTargetSelector Unit const* me; float m_dist; bool m_playerOnly; + Unit const* except; int32 m_aura; // unit: the reference unit // dist: if 0: ignored, if > 0: maximum distance to the reference unit, if < 0: minimum distance to the reference unit // playerOnly: self explaining + // withMainTank: allow current tank to be selected // aura: if 0: ignored, if > 0: the target shall have the aura, if < 0, the target shall NOT have the aura - DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, int32 aura) : me(unit), m_dist(dist), m_playerOnly(playerOnly), m_aura(aura) { } + DefaultTargetSelector(Unit const* unit, float dist, bool playerOnly, bool withMainTank, int32 aura) : me(unit), m_dist(dist), m_playerOnly(playerOnly), except(withMainTank ? me->GetThreatManager().GetCurrentVictim() : nullptr), m_aura(aura) { } bool operator()(Unit const* target) const; }; @@ -124,8 +126,6 @@ struct TC_GAME_API FarthestTargetSelector bool _inLos; }; -TC_GAME_API void SortByDistanceTo(Unit* reference, std::list<Unit*>& targets); - class TC_GAME_API UnitAI { protected: @@ -152,94 +152,174 @@ class TC_GAME_API UnitAI virtual void SetGUID(ObjectGuid /*guid*/, int32 /*id*/ = 0) { } virtual ObjectGuid GetGUID(int32 /*id*/ = 0) const { return ObjectGuid::Empty; } - Unit* SelectTarget(SelectAggroTarget targetType, uint32 position = 0, float dist = 0.0f, bool playerOnly = false, int32 aura = 0); - // Select the targets satisfying the predicate. - // predicate shall extend std::unary_function<Unit*, bool> + // Select the best target (in <targetType> order) from the threat list that fulfill the following: + // - Not among the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM). + // - Within at most <dist> yards (if dist > 0.0f) + // - At least -<dist> yards away (if dist < 0.0f) + // - Is a player (if playerOnly = true) + // - Not the current tank (if withTank = false) + // - Has aura with ID <aura> (if aura > 0) + // - Does not have aura with ID -<aura> (if aura < 0) + Unit* SelectTarget(SelectAggroTarget targetType, uint32 offset = 0, float dist = 0.0f, bool playerOnly = false, bool withTank = true, int32 aura = 0); + // Select the best target (in <targetType> order) satisfying <predicate> from the threat list. + // If <offset> is nonzero, the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM) are skipped. template<class PREDICATE> - Unit* SelectTarget(SelectAggroTarget targetType, uint32 position, PREDICATE const& predicate) + Unit* SelectTarget(SelectAggroTarget targetType, uint32 offset, PREDICATE const& predicate) { - ThreatContainer::StorageType const& threatlist = GetThreatManager().getThreatList(); - if (position >= threatlist.size()) + ThreatManager& mgr = GetThreatManager(); + // shortcut: if we ignore the first <offset> elements, and there are at most <offset> elements, then we ignore ALL elements + if (mgr.GetThreatListSize() <= offset) return nullptr; std::list<Unit*> targetList; - Unit* currentVictim = nullptr; - if (auto currentVictimReference = GetThreatManager().getCurrentVictim()) + if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE) { - currentVictim = currentVictimReference->getTarget(); + for (ThreatReference* ref : mgr.GetUnsortedThreatList()) + { + if (ref->IsOffline()) + continue; - // Current victim always goes first - if (currentVictim && predicate(currentVictim)) + targetList.push_back(ref->GetVictim()); + } + } + else + { + Unit* currentVictim = mgr.GetCurrentVictim(); + if (currentVictim) targetList.push_back(currentVictim); + + for (ThreatReference* ref : mgr.GetSortedThreatList()) + { + if (ref->IsOffline()) + continue; + + Unit* thisTarget = ref->GetVictim(); + if (thisTarget != currentVictim) + targetList.push_back(thisTarget); + } } - for (HostileReference* hostileRef : threatlist) + // filter by predicate + targetList.remove_if([&predicate](Unit* target) { return !predicate(target); }); + + // shortcut: the list certainly isn't gonna get any larger after this point + if (targetList.size() <= offset) + return nullptr; + + // right now, list is unsorted for DISTANCE types - re-sort by MAXDISTANCE + if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE) + SortByDistance(targetList, targetType == SELECT_TARGET_MINDISTANCE); + + // then reverse the sorting for MIN sortings + if (targetType == SELECT_TARGET_MINTHREAT) + targetList.reverse(); + + // now pop the first <offset> elements + while (offset) { - if (currentVictim != nullptr && hostileRef->getTarget() != currentVictim && predicate(hostileRef->getTarget())) - targetList.push_back(hostileRef->getTarget()); - else if (currentVictim == nullptr && predicate(hostileRef->getTarget())) - targetList.push_back(hostileRef->getTarget()); + targetList.pop_front(); + --offset; } - if (position >= targetList.size()) + // maybe nothing fulfills the predicate + if (targetList.empty()) return nullptr; - if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) - SortByDistanceTo(me, targetList); - switch (targetType) { - case SELECT_TARGET_NEAREST: - case SELECT_TARGET_TOPAGGRO: - { - auto itr = targetList.begin(); - std::advance(itr, position); - return *itr; - } - case SELECT_TARGET_FARTHEST: - case SELECT_TARGET_BOTTOMAGGRO: - { - auto ritr = targetList.rbegin(); - std::advance(ritr, position); - return *ritr; - } + case SELECT_TARGET_MAXTHREAT: + case SELECT_TARGET_MINTHREAT: + case SELECT_TARGET_MAXDISTANCE: + case SELECT_TARGET_MINDISTANCE: + return targetList.front(); case SELECT_TARGET_RANDOM: return Trinity::Containers::SelectRandomContainerElement(targetList); default: - break; + return nullptr; } - - return nullptr; } - void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, float dist = 0.0f, bool playerOnly = false, int32 aura = 0); - - // Select the targets satifying the predicate. - // predicate shall extend std::unary_function<Unit*, bool> + // Select the best (up to) <num> targets (in <targetType> order) from the threat list that fulfill the following: + // - Not among the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM). + // - Within at most <dist> yards (if dist > 0.0f) + // - At least -<dist> yards away (if dist < 0.0f) + // - Is a player (if playerOnly = true) + // - Not the current tank (if withTank = false) + // - Has aura with ID <aura> (if aura > 0) + // - Does not have aura with ID -<aura> (if aura < 0) + // The resulting targets are stored in <targetList> (which is cleared first). + void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, uint32 offset = 0, float dist = 0.0f, bool playerOnly = false, bool withTank = true, int32 aura = 0); + + // Select the best (up to) <num> targets (in <targetType> order) satisfying <predicate> from the threat list and stores them in <targetList> (which is cleared first). + // If <offset> is nonzero, the first <offset> entries in <targetType> order (or MAXTHREAT order, if <targetType> is RANDOM) are skipped. template <class PREDICATE> - void SelectTargetList(std::list<Unit*>& targetList, PREDICATE const& predicate, uint32 maxTargets, SelectAggroTarget targetType) + void SelectTargetList(std::list<Unit*>& targetList, uint32 num, SelectAggroTarget targetType, uint32 offset, PREDICATE const& predicate) { - ThreatContainer::StorageType const& threatlist = GetThreatManager().getThreatList(); - if (threatlist.empty()) + targetList.clear(); + ThreatManager& mgr = GetThreatManager(); + // shortcut: we're gonna ignore the first <offset> elements, and there's at most <offset> elements, so we ignore them all - nothing to do here + if (mgr.GetThreatListSize() <= offset) return; - for (HostileReference* hostileRef : threatlist) - if (predicate(hostileRef->getTarget())) - targetList.push_back(hostileRef->getTarget()); + if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE) + { + for (ThreatReference* ref : mgr.GetUnsortedThreatList()) + { + if (ref->IsOffline()) + continue; + + targetList.push_back(ref->GetVictim()); + } + } + else + { + Unit* currentVictim = mgr.GetCurrentVictim(); + if (currentVictim) + targetList.push_back(currentVictim); + + for (ThreatReference* ref : mgr.GetSortedThreatList()) + { + if (ref->IsOffline()) + continue; + + Unit* thisTarget = ref->GetVictim(); + if (thisTarget != currentVictim) + targetList.push_back(thisTarget); + } + } + + // filter by predicate + targetList.remove_if([&predicate](Unit* target) { return !predicate(target); }); - if (targetList.size() < maxTargets) + // shortcut: the list isn't gonna get any larger + if (targetList.size() <= offset) + { + targetList.clear(); return; + } - if (targetType == SELECT_TARGET_NEAREST || targetType == SELECT_TARGET_FARTHEST) - SortByDistanceTo(me, targetList); + // right now, list is unsorted for DISTANCE types - re-sort by MAXDISTANCE + if (targetType == SELECT_TARGET_MAXDISTANCE || targetType == SELECT_TARGET_MINDISTANCE) + SortByDistance(targetList, targetType == SELECT_TARGET_MINDISTANCE); - if (targetType == SELECT_TARGET_FARTHEST || targetType == SELECT_TARGET_BOTTOMAGGRO) + // now the list is MAX sorted, reverse for MIN types + if (targetType == SELECT_TARGET_MINTHREAT) targetList.reverse(); + // ignore the first <offset> elements + while (offset) + { + targetList.pop_front(); + --offset; + } + + if (targetList.size() <= num) + return; + if (targetType == SELECT_TARGET_RANDOM) - Trinity::Containers::RandomResize(targetList, maxTargets); + Trinity::Containers::RandomResize(targetList, num); else - targetList.resize(maxTargets); + targetList.resize(num); } // Called at any Damage to any victim (before damage apply) @@ -303,6 +383,7 @@ class TC_GAME_API UnitAI UnitAI& operator=(UnitAI const& right) = delete; ThreatManager& GetThreatManager(); + void SortByDistance(std::list<Unit*> list, bool ascending = true); }; #endif diff --git a/src/server/game/AI/CreatureAI.cpp b/src/server/game/AI/CreatureAI.cpp index 7ecee7cc14c..cd073d3fe39 100644 --- a/src/server/game/AI/CreatureAI.cpp +++ b/src/server/game/AI/CreatureAI.cpp @@ -82,8 +82,8 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange if (Unit* summoner = creature->ToTempSummon()->GetSummoner()) { Unit* target = summoner->getAttackerForHelper(); - if (!target && summoner->CanHaveThreatList() && !summoner->getThreatManager().isThreatListEmpty()) - target = summoner->getThreatManager().getHostilTarget(); + if (!target && summoner->CanHaveThreatList() && !summoner->GetThreatManager().IsThreatListEmpty()) + target = summoner->GetThreatManager().GetAnyTarget(); if (target && (creature->IsFriendlyTo(summoner) || creature->IsHostileTo(target))) creature->AI()->AttackStart(target); } @@ -114,16 +114,8 @@ void CreatureAI::DoZoneInCombat(Creature* creature /*= nullptr*/, float maxRange { creature->SetInCombatWith(player); player->SetInCombatWith(creature); - creature->AddThreat(player, 0.0f); + creature->GetThreatManager().AddThreat(player, 0.0f, nullptr, true, true); } - - /* Causes certain things to never leave the threat list (Priest Lightwell, etc): - for (Unit::ControlList::const_iterator itr = player->m_Controlled.begin(); itr != player->m_Controlled.end(); ++itr) - { - creature->SetInCombatWith(*itr); - (*itr)->SetInCombatWith(creature); - creature->AddThreat(*itr, 0.0f); - }*/ } } } @@ -141,11 +133,11 @@ void CreatureAI::MoveInLineOfSight_Safe(Unit* who) void CreatureAI::MoveInLineOfSight(Unit* who) { - if (me->GetVictim()) + if (me->IsEngaged()) return; if (me->HasReactState(REACT_AGGRESSIVE) && me->CanStartAttack(who, false)) - AttackStart(who); + me->EngageWithTarget(who); } void CreatureAI::_OnOwnerCombatInteraction(Unit* target) @@ -154,12 +146,7 @@ void CreatureAI::_OnOwnerCombatInteraction(Unit* target) return; if (!me->HasReactState(REACT_PASSIVE) && me->CanStartAttack(target, true)) - { - if (me->IsInCombat()) - me->AddThreat(target, 0.0f); - else - AttackStart(target); - } + me->EngageWithTarget(target); } // Distract creature, if player gets too close while stealthed/prowling @@ -169,8 +156,8 @@ void CreatureAI::TriggerAlert(Unit const* who) const if (!who || who->GetTypeId() != TYPEID_PLAYER) return; - // If this unit isn't an NPC, is already distracted, is in combat, is confused, stunned or fleeing, do nothing - if (me->GetTypeId() != TYPEID_UNIT || me->IsInCombat() || me->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING | UNIT_STATE_DISTRACTED)) + // If this unit isn't an NPC, is already distracted, is fighting, is confused, stunned or fleeing, do nothing + if (me->GetTypeId() != TYPEID_UNIT || me->IsEngaged() || me->HasUnitState(UNIT_STATE_CONFUSED | UNIT_STATE_STUNNED | UNIT_STATE_FLEEING | UNIT_STATE_DISTRACTED)) return; // Only alert for hostiles! @@ -227,7 +214,7 @@ void CreatureAI::SetGazeOn(Unit* target) bool CreatureAI::UpdateVictimWithGaze() { - if (!me->IsInCombat()) + if (!me->IsEngaged()) return false; if (me->HasReactState(REACT_PASSIVE)) @@ -247,7 +234,7 @@ bool CreatureAI::UpdateVictimWithGaze() bool CreatureAI::UpdateVictim() { - if (!me->IsInCombat()) + if (!me->IsEngaged()) return false; if (!me->HasReactState(REACT_PASSIVE)) @@ -258,7 +245,7 @@ bool CreatureAI::UpdateVictim() return me->GetVictim() != nullptr; } - else if (me->getThreatManager().isThreatListEmpty()) + else if (me->GetThreatManager().IsThreatListEmpty()) { EnterEvadeMode(EVADE_REASON_NO_HOSTILES); return false; @@ -275,7 +262,7 @@ bool CreatureAI::_EnterEvadeMode(EvadeReason /*why*/) me->RemoveAurasOnEvade(); // sometimes bosses stuck in combat? - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->LoadCreaturesAddon(); me->SetLootRecipient(nullptr); diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h index a787082bf9d..bd7a6efab22 100644 --- a/src/server/game/AI/CreatureAI.h +++ b/src/server/game/AI/CreatureAI.h @@ -110,7 +110,7 @@ class TC_GAME_API CreatureAI : public UnitAI // Called for reaction at stopping attack at no attackers or targets virtual void EnterEvadeMode(EvadeReason why = EVADE_REASON_OTHER); - // Called for reaction at enter to combat if not in combat yet (enemy can be nullptr) + // Called for reaction when initially engaged virtual void EnterCombat(Unit* /*victim*/) { } // Called when the creature is killed diff --git a/src/server/game/AI/PlayerAI/PlayerAI.cpp b/src/server/game/AI/PlayerAI/PlayerAI.cpp index 34b98cd3fe7..92f1c6f06dc 100644 --- a/src/server/game/AI/PlayerAI/PlayerAI.cpp +++ b/src/server/game/AI/PlayerAI/PlayerAI.cpp @@ -1313,7 +1313,7 @@ void SimpleCharmedPlayerAI::UpdateAI(const uint32 diff) } } - if (charmer->IsInCombat()) + if (charmer->IsEngaged()) { Unit* target = me->GetVictim(); if (!target || !charmer->IsValidAttackTarget(target) || target->HasBreakableByDamageCrowdControlAura()) diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp index d32ac53cb9f..e9e252bcf35 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp @@ -200,6 +200,49 @@ void ScriptedAI::DoPlaySoundToSet(WorldObject* source, uint32 soundId) source->PlayDirectSound(soundId); } +void ScriptedAI::AddThreat(Unit* victim, float amount, Unit* who) +{ + if (!victim) + return; + if (!who) + who = me; + who->GetThreatManager().AddThreat(victim, amount, nullptr, true, true); +} + +void ScriptedAI::ModifyThreatByPercent(Unit* victim, int32 pct, Unit* who) +{ + if (!victim) + return; + if (!who) + who = me; + who->GetThreatManager().ModifyThreatByPercent(victim, pct); +} + +void ScriptedAI::ResetThreat(Unit* victim, Unit* who) +{ + if (!victim) + return; + if (!who) + who = me; + who->GetThreatManager().ResetThreat(victim); +} + +void ScriptedAI::ResetThreatList(Unit* who) +{ + if (!who) + who = me; + who->GetThreatManager().ResetAllThreat(); +} + +float ScriptedAI::GetThreat(Unit const* victim, Unit const* who) +{ + if (!victim) + return 0.0f; + if (!who) + who = me; + return who->GetThreatManager().GetThreat(victim); +} + Creature* ScriptedAI::DoSpawnCreature(uint32 entry, float offsetX, float offsetY, float offsetZ, float angle, uint32 type, uint32 despawntime) { return me->SummonCreature(entry, me->GetPositionX() + offsetX, me->GetPositionY() + offsetY, me->GetPositionZ() + offsetZ, angle, TempSummonType(type), despawntime); @@ -292,38 +335,6 @@ SpellInfo const* ScriptedAI::SelectSpell(Unit* target, uint32 school, uint32 mec return apSpell[urand(0, spellCount - 1)]; } -void ScriptedAI::DoResetThreat() -{ - if (!me->CanHaveThreatList() || me->getThreatManager().isThreatListEmpty()) - { - TC_LOG_ERROR("scripts", "DoResetThreat called for creature that either cannot have threat list or has empty threat list (me entry = %d)", me->GetEntry()); - return; - } - - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); - - for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (unit && DoGetThreat(unit)) - DoModifyThreatPercent(unit, -100); - } -} - -float ScriptedAI::DoGetThreat(Unit* unit) -{ - if (!unit) - return 0.0f; - return me->getThreatManager().getThreat(unit); -} - -void ScriptedAI::DoModifyThreatPercent(Unit* unit, int32 pct) -{ - if (!unit) - return; - me->getThreatManager().modifyThreatPercent(unit, pct); -} - void ScriptedAI::DoTeleportTo(float x, float y, float z, uint32 time) { me->Relocate(x, y, z); @@ -509,7 +520,7 @@ void BossAI::TeleportCheaters() float x, y, z; me->GetPosition(x, y, z); - ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType threatList = me->GetThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) if (Unit* target = (*itr)->getTarget()) if (target->GetTypeId() == TYPEID_PLAYER && !CheckBoundary(target)) @@ -519,7 +530,7 @@ void BossAI::TeleportCheaters() void BossAI::JustSummoned(Creature* summon) { summons.Summon(summon); - if (me->IsInCombat()) + if (me->IsEngaged()) DoZoneInCombat(summon); } diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h index 3b24203a146..6fc85b6a81a 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h +++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h @@ -210,11 +210,16 @@ struct TC_GAME_API ScriptedAI : public CreatureAI //Plays a sound to all nearby players void DoPlaySoundToSet(WorldObject* source, uint32 soundId); - //Drops all threat to 0%. Does not remove players from the threat list - void DoResetThreat(); - - float DoGetThreat(Unit* unit); - void DoModifyThreatPercent(Unit* unit, int32 pct); + // Add specified amount of threat directly to victim (ignores redirection effects) - also puts victim in combat and engages them if necessary + void AddThreat(Unit* victim, float amount, Unit* who = nullptr); + // Adds/removes the specified percentage from the specified victim's threat (to who, or me if not specified) + void ModifyThreatByPercent(Unit* victim, int32 pct, Unit* who = nullptr); + // Resets the victim's threat level to who (or me if not specified) to zero + void ResetThreat(Unit* victim, Unit* who = nullptr); + // Resets the specified unit's threat list (me if not specified) - does not delete entries, just sets their threat to zero + void ResetThreatList(Unit* who = nullptr); + // Returns the threat level of victim towards who (or me if not specified) + float GetThreat(Unit const* victim, Unit const* who = nullptr); void DoTeleportTo(float x, float y, float z, uint32 time = 0); void DoTeleportTo(float const pos[4]); diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp index 6f5b7f1aa71..30a59109e44 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.cpp @@ -103,8 +103,7 @@ bool npc_escortAI::AssistPlayerInCombatAgainst(Unit* who) } else { - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); + me->EngageWithTarget(who); return true; } } @@ -126,24 +125,7 @@ void npc_escortAI::MoveInLineOfSight(Unit* who) { float fAttackRadius = me->GetAttackDistance(who); if (me->IsWithinDistInMap(who, fAttackRadius) && me->IsWithinLOSInMap(who)) - { - if (!me->GetVictim()) - { - // Clear distracted state on combat - if (me->HasUnitState(UNIT_STATE_DISTRACTED)) - { - me->ClearUnitState(UNIT_STATE_DISTRACTED); - me->GetMotionMaster()->Clear(); - } - - AttackStart(who); - } - else if (me->GetMap()->IsDungeon()) - { - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - } - } + me->EngageWithTarget(who); } } } @@ -193,7 +175,7 @@ void npc_escortAI::ReturnToLastPoint() void npc_escortAI::EnterEvadeMode(EvadeReason /*why*/) { me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->SetLootRecipient(nullptr); diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp index d18876fc439..b0b332afecd 100644 --- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp +++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.cpp @@ -52,9 +52,7 @@ void FollowerAI::AttackStart(Unit* who) if (me->Attack(who, true)) { - me->AddThreat(who, 0.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); + me->EngageWithTarget(who); // in case it doesn't have threat+combat yet if (me->HasUnitState(UNIT_STATE_FOLLOW)) me->ClearUnitState(UNIT_STATE_FOLLOW); @@ -87,18 +85,8 @@ bool FollowerAI::AssistPlayerInCombatAgainst(Unit* who) //too far away and no free sight? if (me->IsWithinDistInMap(who, MAX_PLAYER_DISTANCE) && me->IsWithinLOSInMap(who)) { - //already fighting someone? - if (!me->GetVictim()) - { - AttackStart(who); - return true; - } - else - { - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - return true; - } + me->EngageWithTarget(who); + return true; } return false; @@ -131,10 +119,7 @@ void FollowerAI::MoveInLineOfSight(Unit* who) AttackStart(who); } else if (me->GetMap()->IsDungeon()) - { - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - } + me->EngageWithTarget(who); } } } @@ -176,7 +161,7 @@ void FollowerAI::JustRespawned() void FollowerAI::EnterEvadeMode(EvadeReason /*why*/) { me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->SetLootRecipient(nullptr); diff --git a/src/server/game/AI/SmartScripts/SmartAI.cpp b/src/server/game/AI/SmartScripts/SmartAI.cpp index 682f92f1ee6..5aa2550a704 100644 --- a/src/server/game/AI/SmartScripts/SmartAI.cpp +++ b/src/server/game/AI/SmartScripts/SmartAI.cpp @@ -559,18 +559,8 @@ bool SmartAI::AssistPlayerInCombatAgainst(Unit* who) //too far away and no free sight? if (me->IsWithinDistInMap(who, SMART_MAX_AID_DIST) && me->IsWithinLOSInMap(who)) { - //already fighting someone? - if (!me->GetVictim()) - { - AttackStart(who); - return true; - } - else - { - who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); - return true; - } + me->EngageWithTarget(who); + return true; } return false; diff --git a/src/server/game/AI/SmartScripts/SmartScript.cpp b/src/server/game/AI/SmartScripts/SmartScript.cpp index fe86978b0db..3072ef31425 100644 --- a/src/server/game/AI/SmartScripts/SmartScript.cpp +++ b/src/server/game/AI/SmartScripts/SmartScript.cpp @@ -459,15 +459,11 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u if (!me) break; - ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); - for (auto i = threatList.begin(); i != threatList.end(); ++i) + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) { - if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - { - me->getThreatManager().modifyThreatPercent(target, e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); - TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature guidLow %u modify threat for unit %u, value %i", - me->GetGUID().GetCounter(), target->GetGUID().GetCounter(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); - } + ref->ModifyThreatByPercent(std::max<int32>(-100,int32(e.action.threatPCT.threatINC) - int32(e.action.threatPCT.threatDEC))); + TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_ALL_PCT: Creature guidLow %u modify threat for unit %u, value %i", + me->GetGUID().GetCounter(), ref->GetVictim()->GetGUID().GetCounter(), int32(e.action.threatPCT.threatINC)-int32(e.action.threatPCT.threatDEC)); } break; } @@ -480,9 +476,9 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { if (IsUnit(target)) { - me->getThreatManager().modifyThreatPercent(target->ToUnit(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); + me->GetThreatManager().ModifyThreatByPercent(target->ToUnit(), std::max<int32>(-100, int32(e.action.threatPCT.threatINC) - int32(e.action.threatPCT.threatDEC))); TC_LOG_DEBUG("scripts.ai", "SmartScript::ProcessAction:: SMART_ACTION_THREAT_SINGLE_PCT: Creature guidLow %u modify threat for unit %u, value %i", - me->GetGUID().GetCounter(), target->GetGUID().GetCounter(), e.action.threatPCT.threatINC ? (int32)e.action.threatPCT.threatINC : -(int32)e.action.threatPCT.threatDEC); + me->GetGUID().GetCounter(), target->GetGUID().GetCounter(), int32(e.action.threatPCT.threatINC) - int32(e.action.threatPCT.threatDEC)); } } break; @@ -2091,7 +2087,7 @@ void SmartScript::ProcessAction(SmartScriptHolder& e, Unit* unit, uint32 var0, u { for (WorldObject* const target : targets) if (IsUnit(target)) - me->AddThreat(target->ToUnit(), float(e.action.threatPCT.threatINC) - float(e.action.threatPCT.threatDEC)); + me->GetThreatManager().AddThreat(target->ToUnit(), float(e.action.threatPCT.threatINC) - float(e.action.threatPCT.threatDEC), nullptr, true, true); break; } case SMART_ACTION_LOAD_EQUIPMENT: @@ -2292,10 +2288,10 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, { if (e.target.hostilRandom.powerType) { - if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))) + if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MAXTHREAT, 1, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))) targets.push_back(u); } - else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_TOPAGGRO, 1, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)) + else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MAXTHREAT, 1, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)) targets.push_back(u); } break; @@ -2304,10 +2300,10 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, { if (e.target.hostilRandom.powerType) { - if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))) + if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MINTHREAT, 0, PowerUsersSelector(me, Powers(e.target.hostilRandom.powerType - 1), float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0))) targets.push_back(u); } - else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_BOTTOMAGGRO, 0, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)) + else if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MINTHREAT, 0, float(e.target.hostilRandom.maxDist), e.target.hostilRandom.playerOnly != 0)) targets.push_back(u); } break; @@ -2338,7 +2334,7 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, case SMART_TARGET_FARTHEST: if (me) { - if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_FARTHEST, 0, FarthestTargetSelector(me, float(e.target.farthest.maxDist), e.target.farthest.playerOnly != 0, e.target.farthest.isInLos != 0))) + if (Unit* u = me->AI()->SelectTarget(SELECT_TARGET_MAXDISTANCE, 0, FarthestTargetSelector(me, float(e.target.farthest.maxDist), e.target.farthest.playerOnly != 0, e.target.farthest.isInLos != 0))) targets.push_back(u); } break; @@ -2555,14 +2551,10 @@ void SmartScript::GetTargets(ObjectVector& targets, SmartScriptHolder const& e, } case SMART_TARGET_THREAT_LIST: { - if (me) - { - ThreatContainer::StorageType const& threatList = me->getThreatManager().getThreatList(); - for (HostileReference const* ref : threatList) - if (Unit* temp = ObjectAccessor::GetUnit(*me, ref->getUnitGuid())) - if (e.target.hostilRandom.maxDist == 0 || me->IsWithinCombatRange(temp, float(e.target.hostilRandom.maxDist))) - targets.push_back(temp); - } + if (me && me->CanHaveThreatList()) + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) + if (!e.target.hostilRandom.maxDist || me->IsWithinCombatRange(ref->GetVictim(), float(e.target.hostilRandom.maxDist))) + targets.push_back(ref->GetVictim()); break; } case SMART_TARGET_CLOSEST_ENEMY: @@ -2646,18 +2638,18 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); break; case SMART_EVENT_UPDATE_OOC: - if (me && me->IsInCombat()) + if (me && me->IsEngaged()) return; ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); break; case SMART_EVENT_UPDATE_IC: - if (!me || !me->IsInCombat()) + if (!me || !me->IsEngaged()) return; ProcessTimedAction(e, e.event.minMaxRepeat.repeatMin, e.event.minMaxRepeat.repeatMax); break; case SMART_EVENT_HEALT_PCT: { - if (!me || !me->IsInCombat() || !me->GetMaxHealth()) + if (!me || !me->IsEngaged() || !me->GetMaxHealth()) return; uint32 perc = (uint32)me->GetHealthPct(); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) @@ -2667,7 +2659,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_TARGET_HEALTH_PCT: { - if (!me || !me->IsInCombat() || !me->GetVictim() || !me->EnsureVictim()->GetMaxHealth()) + if (!me || !me->IsEngaged() || !me->GetVictim() || !me->EnsureVictim()->GetMaxHealth()) return; uint32 perc = (uint32)me->EnsureVictim()->GetHealthPct(); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) @@ -2677,7 +2669,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_MANA_PCT: { - if (!me || !me->IsInCombat() || !me->GetMaxPower(POWER_MANA)) + if (!me || !me->IsEngaged() || !me->GetMaxPower(POWER_MANA)) return; uint32 perc = uint32(100.0f * me->GetPower(POWER_MANA) / me->GetMaxPower(POWER_MANA)); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) @@ -2687,7 +2679,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_TARGET_MANA_PCT: { - if (!me || !me->IsInCombat() || !me->GetVictim() || !me->EnsureVictim()->GetMaxPower(POWER_MANA)) + if (!me || !me->IsEngaged() || !me->GetVictim() || !me->EnsureVictim()->GetMaxPower(POWER_MANA)) return; uint32 perc = uint32(100.0f * me->EnsureVictim()->GetPower(POWER_MANA) / me->EnsureVictim()->GetMaxPower(POWER_MANA)); if (perc > e.event.minMaxRepeat.max || perc < e.event.minMaxRepeat.min) @@ -2697,7 +2689,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_RANGE: { - if (!me || !me->IsInCombat() || !me->GetVictim()) + if (!me || !me->IsEngaged() || !me->GetVictim()) return; if (me->IsInRange(me->GetVictim(), (float)e.event.minMaxRepeat.min, (float)e.event.minMaxRepeat.max)) @@ -2708,7 +2700,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_VICTIM_CASTING: { - if (!me || !me->IsInCombat()) + if (!me || !me->IsEngaged()) return; Unit* victim = me->GetVictim(); @@ -2726,7 +2718,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_FRIENDLY_HEALTH: { - if (!me || !me->IsInCombat()) + if (!me || !me->IsEngaged()) return; Unit* target = DoSelectLowestHpFriendly((float)e.event.friendlyHealth.radius, e.event.friendlyHealth.hpDeficit); @@ -2742,7 +2734,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_FRIENDLY_IS_CC: { - if (!me || !me->IsInCombat()) + if (!me || !me->IsEngaged()) return; std::vector<Creature*> creatures; @@ -2865,7 +2857,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_OOC_LOS: { - if (!me || me->IsInCombat()) + if (!me || me->IsEngaged()) return; //can trigger if closer than fMaxAllowedRange float range = (float)e.event.los.maxDist; @@ -2885,7 +2877,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_IC_LOS: { - if (!me || !me->IsInCombat()) + if (!me || !me->IsEngaged()) return; //can trigger if closer than fMaxAllowedRange float range = (float)e.event.los.maxDist; @@ -3075,7 +3067,7 @@ void SmartScript::ProcessEvent(SmartScriptHolder& e, Unit* unit, uint32 var0, ui } case SMART_EVENT_FRIENDLY_HEALTH_PCT: { - if (!me || !me->IsInCombat()) + if (!me || !me->IsEngaged()) return; ObjectVector targets; @@ -3220,10 +3212,10 @@ void SmartScript::UpdateTimer(SmartScriptHolder& e, uint32 const diff) if (e.event.event_phase_mask && !IsInPhase(e.event.event_phase_mask)) return; - if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->IsInCombat())) + if (e.GetEventType() == SMART_EVENT_UPDATE_IC && (!me || !me->IsEngaged())) return; - if (e.GetEventType() == SMART_EVENT_UPDATE_OOC && (me && me->IsInCombat())) //can be used with me=nullptr (go script) + if (e.GetEventType() == SMART_EVENT_UPDATE_OOC && (me && me->IsEngaged())) //can be used with me=nullptr (go script) return; if (e.timer < diff) @@ -3531,7 +3523,7 @@ void SmartScript::OnMoveInLineOfSight(Unit* who) if (!me) return; - ProcessEventsFor(me->IsInCombat() ? SMART_EVENT_IC_LOS : SMART_EVENT_OOC_LOS, who); + ProcessEventsFor(me->IsEngaged() ? SMART_EVENT_IC_LOS : SMART_EVENT_OOC_LOS, who); } // SmartScript end diff --git a/src/server/game/Combat/ThreatManager.cpp b/src/server/game/Combat/ThreatManager.cpp index 005e8fad2a8..5a1207b82ca 100644 --- a/src/server/game/Combat/ThreatManager.cpp +++ b/src/server/game/Combat/ThreatManager.cpp @@ -130,6 +130,9 @@ void HostileReference::fireStatusChanged(ThreatRefStatusChangeEvent& threatRefSt GetSource()->processThreatEvent(&threatRefStatusChangeEvent); } +// -- compatibility layer for combat rewrite (PR #19930) +Unit* HostileReference::GetOwner() const { return GetSource()->GetOwner(); } + //============================================================ void HostileReference::addThreat(float modThreat) @@ -263,7 +266,7 @@ void ThreatContainer::clearReferences() //============================================================ // Return the HostileReference of NULL, if not found -HostileReference* ThreatContainer::getReferenceByTarget(Unit* victim) const +HostileReference* ThreatContainer::getReferenceByTarget(Unit const* victim) const { if (!victim) return nullptr; @@ -292,7 +295,7 @@ HostileReference* ThreatContainer::addThreat(Unit* victim, float threat) //============================================================ -void ThreatContainer::modifyThreatPercent(Unit* victim, int32 percent) +void ThreatContainer::ModifyThreatByPercent(Unit* victim, int32 percent) { if (HostileReference* ref = getReferenceByTarget(victim)) ref->addThreatPercent(percent); @@ -391,6 +394,30 @@ HostileReference* ThreatContainer::selectNextVictim(Creature* attacker, HostileR ThreatManager::ThreatManager(Unit* owner) : iCurrentVictim(nullptr), iOwner(owner), iUpdateTimer(THREAT_UPDATE_INTERVAL) { } +// -- compatibility layer for combat rewrite (PR #19930) +void ThreatManager::ForwardThreatForAssistingMe(Unit* victim, float amount, SpellInfo const* spell, bool ignoreModifiers, bool ignoreRedirection) +{ + (void)ignoreModifiers; (void)ignoreRedirection; + GetOwner()->getHostileRefManager().threatAssist(victim, amount, spell); +} + +void ThreatManager::AddThreat(Unit* victim, float amount, SpellInfo const* spell, bool ignoreModifiers, bool ignoreRedirection) +{ + (void)ignoreModifiers; (void)ignoreRedirection; + if (!iOwner->CanHaveThreatList() || iOwner->HasUnitState(UNIT_STATE_EVADE)) + return; + iOwner->SetInCombatWith(victim); + victim->SetInCombatWith(iOwner); + addThreat(victim, amount, spell ? spell->GetSchoolMask() : victim->GetMeleeDamageSchoolMask(), spell); +} + +void ThreatManager::ClearAllThreat() +{ + if (iOwner->CanHaveThreatList(true) && !isThreatListEmpty()) + iOwner->SendClearThreatListOpcode(); + clearReferences(); +} + //============================================================ void ThreatManager::clearReferences() @@ -453,9 +480,9 @@ void ThreatManager::_addThreat(Unit* victim, float threat) //============================================================ -void ThreatManager::modifyThreatPercent(Unit* victim, int32 percent) +void ThreatManager::ModifyThreatByPercent(Unit* victim, int32 percent) { - iThreatContainer.modifyThreatPercent(victim, percent); + iThreatContainer.ModifyThreatByPercent(victim, percent); } //============================================================ diff --git a/src/server/game/Combat/ThreatManager.h b/src/server/game/Combat/ThreatManager.h index c500663214e..fcc0f82a220 100644 --- a/src/server/game/Combat/ThreatManager.h +++ b/src/server/game/Combat/ThreatManager.h @@ -24,6 +24,7 @@ #include "LinkedReference/Reference.h" #include "UnitEvents.h" #include "ObjectGuid.h" +#include "Containers.h" #include <list> @@ -51,6 +52,19 @@ class TC_GAME_API HostileReference : public Reference<Unit, ThreatManager> public: HostileReference(Unit* refUnit, ThreatManager* threatManager, float threat); + // -- compatibility layer for combat rewrite (PR #19930) + Unit* GetOwner() const; + Unit* GetVictim() const { return getTarget(); } + void AddThreat(float amt) { addThreat(amt); } + void SetThreat(float amt) { setThreat(amt); } + void ModifyThreatByPercent(int32 pct) { addThreatPercent(pct); } + void ScaleThreat(float factor) { setThreat(iThreat*factor); } + bool IsOnline() const { return iOnline; } + bool IsAvailable() const { return iOnline; } + bool IsOffline() const { return !iOnline; } + float GetThreat() const { return getThreat(); } + void ClearThreat() { removeReference(); } + //================================================= void addThreat(float modThreat); @@ -157,7 +171,7 @@ class TC_GAME_API ThreatContainer HostileReference* addThreat(Unit* victim, float threat); - void modifyThreatPercent(Unit* victim, int32 percent); + void ModifyThreatByPercent(Unit* victim, int32 percent); HostileReference* selectNextVictim(Creature* attacker, HostileReference* currentVictim) const; @@ -175,7 +189,7 @@ class TC_GAME_API ThreatContainer return iThreatList.empty() ? nullptr : iThreatList.front(); } - HostileReference* getReferenceByTarget(Unit* victim) const; + HostileReference* getReferenceByTarget(Unit const* victim) const; StorageType const & getThreatList() const { return iThreatList; } @@ -201,9 +215,31 @@ class TC_GAME_API ThreatContainer //================================================= +typedef HostileReference ThreatReference; class TC_GAME_API ThreatManager { public: + // -- compatibility layer for combat rewrite (PR #19930) + Trinity::Containers::IteratorPair<std::list<ThreatReference*>::const_iterator> GetSortedThreatList() const { auto& list = iThreatContainer.getThreatList(); return { list.cbegin(), list.cend() }; } + Trinity::Containers::IteratorPair<std::list<ThreatReference*>::const_iterator> GetUnsortedThreatList() const { return GetSortedThreatList(); } + Unit* SelectVictim() { return getHostilTarget(); } + Unit* GetCurrentVictim() const { if (ThreatReference* ref = getCurrentVictim()) return ref->GetVictim(); else return nullptr; } + bool IsThreatListEmpty(bool includeOffline = false) const { return includeOffline ? areThreatListsEmpty() : isThreatListEmpty(); } + bool IsThreatenedBy(Unit const* who, bool includeOffline = false) const { return (FindReference(who, includeOffline) != nullptr); } + size_t GetThreatListSize() const { return iThreatContainer.iThreatList.size(); } + void ForwardThreatForAssistingMe(Unit* victim, float amount, SpellInfo const* spell, bool ignoreModifiers = false, bool ignoreRedirection = false); + Unit* GetAnyTarget() const { auto const& list = getThreatList(); if (!list.empty()) return list.front()->getTarget(); return nullptr; } + void ResetThreat(Unit const* who) { if (auto* ref = FindReference(who, true)) ref->setThreat(0.0f); } + void ResetAllThreat() { resetAllAggro(); } + float GetThreat(Unit const* who, bool includeOffline = false) const { if (auto* ref = FindReference(who, includeOffline)) return ref->GetThreat(); return 0.0f; } + void ClearThreat(Unit const* who) { if (auto* ref = FindReference(who, true)) ref->removeReference(); } + void ClearAllThreat(); + void AddThreat(Unit* victim, float amount, SpellInfo const* spell = nullptr, bool ignoreModifiers = false, bool ignoreRedirection = false); + private: + HostileReference* FindReference(Unit const* who, bool includeOffline) const { if (auto* ref = iThreatContainer.getReferenceByTarget(who)) return ref; if (includeOffline) if (auto* ref = iThreatOfflineContainer.getReferenceByTarget(who)) return ref; return nullptr; } + + public: + friend class HostileReference; explicit ThreatManager(Unit* owner); @@ -216,7 +252,7 @@ class TC_GAME_API ThreatManager void doAddThreat(Unit* victim, float threat); - void modifyThreatPercent(Unit* victim, int32 percent); + void ModifyThreatByPercent(Unit* victim, int32 percent); float getThreat(Unit* victim, bool alsoSearchOfflineList = false); diff --git a/src/server/game/Combat/UnitEvents.h b/src/server/game/Combat/UnitEvents.h index 35b7e7ecb5f..5e7a00f049d 100644 --- a/src/server/game/Combat/UnitEvents.h +++ b/src/server/game/Combat/UnitEvents.h @@ -116,7 +116,7 @@ class TC_GAME_API ThreatRefStatusChangeEvent : public UnitBaseEvent void setThreatManager(ThreatManager* pThreatManager) { iThreatManager = pThreatManager; } - ThreatManager* getThreatManager() const { return iThreatManager; } + ThreatManager* GetThreatManager() const { return iThreatManager; } }; #endif diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp index ef17eaa07bd..3b274c3b67f 100644 --- a/src/server/game/Entities/Creature/Creature.cpp +++ b/src/server/game/Entities/Creature/Creature.cpp @@ -215,9 +215,7 @@ bool AssistDelayEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) if (assistant && assistant->CanAssistTo(&m_owner, victim)) { assistant->SetNoCallAssistance(true); - assistant->CombatStart(victim); - if (assistant->IsAIEnabled) - assistant->AI()->AttackStart(victim); + assistant->EngageWithTarget(victim); } } } @@ -682,7 +680,7 @@ void Creature::Update(uint32 diff) } // periodic check to see if the creature has passed an evade boundary - if (IsAIEnabled && !IsInEvadeMode() && IsInCombat()) + if (IsAIEnabled && !IsInEvadeMode() && IsEngaged()) { if (diff >= m_boundaryCheckTime) { @@ -693,7 +691,7 @@ void Creature::Update(uint32 diff) } // if periodic combat pulse is enabled and we are both in combat and in a dungeon, do this now - if (m_combatPulseDelay > 0 && IsInCombat() && GetMap()->IsDungeon()) + if (m_combatPulseDelay > 0 && IsEngaged() && GetMap()->IsDungeon()) { if (diff > m_combatPulseTime) m_combatPulseTime = 0; @@ -712,12 +710,7 @@ void Creature::Update(uint32 diff) continue; if (player->IsAlive() && IsHostileTo(player)) - { - if (CanHaveThreatList()) - AddThreat(player, 0.0f); - SetInCombatWith(player); - player->SetInCombatWith(this); - } + EngageWithTarget(player); } } @@ -1662,7 +1655,7 @@ bool Creature::CanStartAttack(Unit const* who, bool force) const if (!_IsTargetAcceptable(who)) return false; - if (who->IsInCombat() && IsWithinDist(who, ATTACK_DISTANCE)) + if (who->IsEngaged() && IsWithinDist(who, ATTACK_DISTANCE)) if (Unit* victim = who->getAttackerForHelper()) if (IsWithinDistInMap(victim, sWorld->getFloatConfig(CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS))) force = true; @@ -1803,8 +1796,6 @@ void Creature::setDeathState(DeathState s) SetUInt32Value(UNIT_FIELD_FLAGS, unit_flags); SetUInt32Value(UNIT_DYNAMIC_FLAGS, dynamicflags); - RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); - SetMeleeDamageSchool(SpellSchools(cinfo->dmgschool)); if (creatureData && GetPhaseMask() != creatureData->phaseMask) @@ -2193,7 +2184,7 @@ bool Creature::CanAssistTo(Unit const* u, Unit const* enemy, bool checkfaction / return false; // skip fighting creature - if (IsInCombat()) + if (IsEngaged()) return false; // only free creature @@ -2243,7 +2234,7 @@ bool Creature::_IsTargetAcceptable(Unit const* target) const Unit const* targetVictim = target->getAttackerForHelper(); // if I'm already fighting target, or I'm hostile towards the target, the target is acceptable - if (IsInCombatWith(target) || IsHostileTo(target)) + if (IsEngagedBy(target) || IsHostileTo(target)) return true; // if the target's victim is friendly, and the target is neutral, the target is acceptable @@ -2441,11 +2432,7 @@ void Creature::SetInCombatWithZone() continue; if (player->IsAlive()) - { - SetInCombatWith(player); - player->SetInCombatWith(this); - AddThreat(player, 0.0f); - } + EngageWithTarget(player); } } } diff --git a/src/server/game/Entities/Creature/CreatureGroups.cpp b/src/server/game/Entities/Creature/CreatureGroups.cpp index f534db8759c..b7de0c874fa 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.cpp +++ b/src/server/game/Entities/Creature/CreatureGroups.cpp @@ -173,7 +173,7 @@ void CreatureGroup::RemoveMember(Creature* member) member->SetFormation(nullptr); } -void CreatureGroup::MemberAttackStart(Creature* member, Unit* target) +void CreatureGroup::MemberEngagingTarget(Creature* member, Unit* target) { uint8 groupAI = sFormationMgr->CreatureGroupMap[member->GetSpawnId()]->groupAI; if (!groupAI) @@ -181,11 +181,7 @@ void CreatureGroup::MemberAttackStart(Creature* member, Unit* target) for (CreatureGroupMemberType::iterator itr = m_members.begin(); itr != m_members.end(); ++itr) { - if (m_leader) // avoid crash if leader was killed and reset. - TC_LOG_DEBUG("entities.unit", "GROUP ATTACK: group instance id %u calls member instid %u", m_leader->GetInstanceId(), member->GetInstanceId()); - Creature* other = itr->first; - // Skip self if (other == member) continue; @@ -193,11 +189,8 @@ void CreatureGroup::MemberAttackStart(Creature* member, Unit* target) if (!other->IsAlive()) continue; - if (other->GetVictim()) - continue; - if (((other != m_leader && groupAI & FLAG_AGGRO_ON_AGGRO) || (other == m_leader && groupAI & FLAG_TO_AGGRO_ON_AGGRO)) && other->IsValidAttackTarget(target)) - other->AI()->AttackStart(target); + other->EngageWithTarget(target); } } diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h index f0ce2677dc8..3f8e466fca5 100644 --- a/src/server/game/Entities/Creature/CreatureGroups.h +++ b/src/server/game/Entities/Creature/CreatureGroups.h @@ -89,7 +89,7 @@ class TC_GAME_API CreatureGroup void FormationReset(bool dismiss); void LeaderMoveTo(Position const& destination, uint32 id = 0, uint32 moveType = 0, bool orientation = false); - void MemberAttackStart(Creature* member, Unit* target); + void MemberEngagingTarget(Creature* member, Unit* target); }; #define sFormationMgr FormationMgr::instance() diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp index ba48a64d719..508a89a86c8 100644 --- a/src/server/game/Entities/Object/Object.cpp +++ b/src/server/game/Entities/Object/Object.cpp @@ -1000,7 +1000,7 @@ void MovementInfo::OutDebug() WorldObject::WorldObject(bool isWorldObject) : WorldLocation(), LastUsedScriptID(0), m_name(""), m_isActive(false), m_isWorldObject(isWorldObject), m_zoneScript(nullptr), m_transport(nullptr), m_zoneId(0), m_areaId(0), m_staticFloorZ(VMAP_INVALID_HEIGHT), m_currMap(nullptr), m_InstanceId(0), -m_phaseMask(PHASEMASK_NORMAL), m_notifyflags(0), m_executed_notifies(0) +m_phaseMask(PHASEMASK_NORMAL), m_notifyflags(0) { m_serverSideVisibility.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE | GHOST_VISIBILITY_GHOST); m_serverSideVisibilityDetect.SetValue(SERVERSIDE_VISIBILITY_GHOST, GHOST_VISIBILITY_ALIVE); diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h index f5ff5100b78..ca1b547f68b 100644 --- a/src/server/game/Entities/Object/Object.h +++ b/src/server/game/Entities/Object/Object.h @@ -410,9 +410,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation void AddToNotify(uint16 f) { m_notifyflags |= f;} bool isNeedNotify(uint16 f) const { return (m_notifyflags & f) != 0; } uint16 GetNotifyFlags() const { return m_notifyflags; } - bool NotifyExecuted(uint16 f) const { return (m_executed_notifies & f) != 0; } - void SetNotified(uint16 f) { m_executed_notifies |= f;} - void ResetAllNotifies() { m_notifyflags = 0; m_executed_notifies = 0; } + void ResetAllNotifies() { m_notifyflags = 0; } bool isActiveObject() const { return m_isActive; } void setActive(bool isActiveObject); @@ -476,7 +474,6 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation uint32 m_phaseMask; // in area phase state uint16 m_notifyflags; - uint16 m_executed_notifies; virtual bool _IsWithinDist(WorldObject const* obj, float dist2compare, bool is3D, bool incOwnRadius = true, bool incTargetRadius = true) const; bool CanNeverSee(WorldObject const* obj) const; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index b4d93f01d09..33ce50c1053 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -20285,14 +20285,38 @@ void Player::UpdateAfkReport(time_t currTime) } } +void Player::SetContestedPvP(Player* attackedPlayer) +{ + if (attackedPlayer && (attackedPlayer == this || (duel && duel->opponent == attackedPlayer))) + return; + + SetContestedPvPTimer(30000); + if (!HasUnitState(UNIT_STATE_ATTACK_PLAYER)) + { + AddUnitState(UNIT_STATE_ATTACK_PLAYER); + SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP); + // call MoveInLineOfSight for nearby contested guards + Trinity::AIRelocationNotifier notifier(*this); + Cell::VisitWorldObjects(this, notifier, GetVisibilityRange()); + } + for (Unit* unit : m_Controlled) + { + if (!unit->HasUnitState(UNIT_STATE_ATTACK_PLAYER)) + { + unit->AddUnitState(UNIT_STATE_ATTACK_PLAYER); + Trinity::AIRelocationNotifier notifier(*unit); + Cell::VisitWorldObjects(this, notifier, GetVisibilityRange()); + } + } +} + void Player::UpdateContestedPvP(uint32 diff) { - if (!m_contestedPvPTimer||IsInCombat()) + if (!m_contestedPvPTimer || IsInCombat()) return; + if (m_contestedPvPTimer <= diff) - { ResetContestedPvP(); - } else m_contestedPvPTimer -= diff; } diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h index 210909db73f..4a2a82000b4 100644 --- a/src/server/game/Entities/Player/Player.h +++ b/src/server/game/Entities/Player/Player.h @@ -1502,6 +1502,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player> void UpdateAfkReport(time_t currTime); void UpdatePvPFlag(time_t currTime); + void SetContestedPvP(Player* attackedPlayer = nullptr); void UpdateContestedPvP(uint32 currTime); void SetContestedPvPTimer(uint32 newTime) {m_contestedPvPTimer = newTime;} void ResetContestedPvP(); diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index bb43c34182a..daa9d5bdefa 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -445,7 +445,7 @@ void Unit::Update(uint32 p_time) // Having this would prevent spells from being proced, so let's crash ASSERT(!m_procDeep); - if (CanHaveThreatList() && getThreatManager().isNeedUpdateToClient(p_time)) + if (CanHaveThreatList() && GetThreatManager().isNeedUpdateToClient(p_time)) SendThreatListUpdate(); // update combat timer only for players and pets (only pets with PetAI) @@ -880,7 +880,7 @@ uint32 Unit::DealDamage(Unit* victim, uint32 damage, CleanDamage const* cleanDam if (damagetype != DOT && damage > 0 && !victim->GetOwnerGUID().IsPlayer() && (!spellProto || !spellProto->HasAura(SPELL_AURA_DAMAGE_SHIELD))) victim->ToCreature()->SetLastDamagedTime(GameTime::GetGameTime() + MAX_AGGRO_RESET_TIME); - victim->AddThreat(this, float(damage), damageSchoolMask, spellProto); + victim->GetThreatManager().AddThreat(this, float(damage), spellProto); } else // victim is a player { @@ -5763,6 +5763,9 @@ void Unit::_removeAttacker(Unit* pAttacker) Unit* Unit::getAttackerForHelper() const // If someone wants to help, who to give them { + if (!IsEngaged()) + return nullptr; + if (Unit* victim = GetVictim()) if ((!IsPet() && !GetPlayerMovingMe()) || IsInCombatWith(victim) || victim->IsInCombatWith(this)) return victim; @@ -5866,14 +5869,14 @@ bool Unit::Attack(Unit* victim, bool meleeAttack) if (creature && !IsPet()) { // should not let player enter combat by right clicking target - doesn't helps - AddThreat(victim, 0.0f); + GetThreatManager().AddThreat(victim, 0.0f); SetInCombatWith(victim); if (victim->GetTypeId() == TYPEID_PLAYER) victim->SetInCombatWith(this); if (Unit* owner = victim->GetOwner()) { - AddThreat(owner, 0.0f); + GetThreatManager().AddThreat(owner, 0.0f); SetInCombatWith(owner); if (owner->GetTypeId() == TYPEID_PLAYER) owner->SetInCombatWith(this); @@ -6768,12 +6771,16 @@ void Unit::SendEnergizeSpellLog(Unit* victim, uint32 spellId, int32 damage, Powe void Unit::EnergizeBySpell(Unit* victim, uint32 spellId, int32 damage, Powers powerType) { - SendEnergizeSpellLog(victim, spellId, damage, powerType); + if (SpellInfo const* info = sSpellMgr->GetSpellInfo(spellId)) + EnergizeBySpell(victim, info, damage, powerType); +} + +void Unit::EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damage, Powers powerType) +{ + SendEnergizeSpellLog(victim, spellInfo->Id, damage, powerType); // needs to be called after sending spell log victim->ModifyPower(powerType, damage); - - SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId); - victim->getHostileRefManager().threatAssist(this, float(damage) * 0.5f, spellInfo); + victim->GetThreatManager().ForwardThreatForAssistingMe(this, float(damage)/2, spellInfo, true); } uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uint32 pdamage, DamageEffectType damagetype, uint32 stack) const @@ -8690,11 +8697,11 @@ void Unit::CombatStart(Unit* target, bool initialAggro) SetInCombatWith(target); target->SetInCombatWith(this); } - Unit* who = target->GetCharmerOrOwnerOrSelf(); - if (who->GetTypeId() == TYPEID_PLAYER) - SetContestedPvP(who->ToPlayer()); Player* me = GetCharmerOrOwnerPlayerOrPlayerItself(); + Unit* who = target->GetCharmerOrOwnerOrSelf(); + if (me && who->GetTypeId() == TYPEID_PLAYER) + me->SetContestedPvP(who->ToPlayer()); if (me && who->IsPvP() && (who->GetTypeId() != TYPEID_PLAYER || !me->duel || me->duel->opponent != who)) @@ -8732,7 +8739,7 @@ void Unit::SetInCombatState(bool PvP, Unit* enemy) creature->AI()->EnterCombat(enemy); if (creature->GetFormation()) - creature->GetFormation()->MemberAttackStart(creature, enemy); + creature->GetFormation()->MemberEngagingTarget(creature, enemy); } if (IsPet()) @@ -9419,7 +9426,7 @@ void Unit::setDeathState(DeathState s) if (s != ALIVE && s != JUST_RESPAWNED) { CombatStop(); - DeleteThreatList(); + GetThreatManager().ClearAllThreat(); getHostileRefManager().deleteReferences(); ClearComboPointHolders(); // any combo points pointed to unit lost at it death @@ -9489,7 +9496,7 @@ bool Unit::CanHaveThreatList(bool skipAliveCheck) const // return false; // summons can not have a threat list, unless they are controlled by a creature - if (HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && ((Pet*)this)->GetOwnerGUID().IsPlayer()) + if (HasUnitTypeMask(UNIT_MASK_MINION | UNIT_MASK_GUARDIAN | UNIT_MASK_CONTROLABLE_GUARDIAN) && GetOwnerGUID().IsPlayer()) return false; return true; @@ -9509,24 +9516,6 @@ float Unit::ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask) //====================================================================== -void Unit::AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask, SpellInfo const* threatSpell) -{ - // Only mobs can manage threat lists - if (CanHaveThreatList() && !HasUnitState(UNIT_STATE_EVADE)) - m_ThreatManager.addThreat(victim, fThreat, schoolMask, threatSpell); -} - -//====================================================================== - -void Unit::DeleteThreatList() -{ - if (CanHaveThreatList(true) && !m_ThreatManager.isThreatListEmpty()) - SendClearThreatListOpcode(); - m_ThreatManager.clearReferences(); -} - -//====================================================================== - void Unit::TauntApply(Unit* taunter) { ASSERT(GetTypeId() == TYPEID_UNIT); @@ -10678,7 +10667,7 @@ void Unit::CleanupBeforeRemoveFromMap(bool finalCleanup) CombatStop(); ClearComboPoints(); ClearComboPointHolders(); - DeleteThreatList(); + GetThreatManager().ClearAllThreat(); getHostileRefManager().deleteReferences(); } @@ -11338,8 +11327,7 @@ Player* Unit::GetSpellModOwner() const if (HasUnitTypeMask(UNIT_MASK_PET | UNIT_MASK_TOTEM | UNIT_MASK_GUARDIAN)) { if (Unit* owner = GetOwner()) - if (Player* player = owner->ToPlayer()) - return player; + return owner->ToPlayer(); } return nullptr; } @@ -11904,29 +11892,6 @@ bool Unit::IsUnderLastManaUseEffect() const return getMSTimeDiff(m_lastManaUse, GameTime::GetGameTimeMS()) < 5000; } -void Unit::SetContestedPvP(Player* attackedPlayer) -{ - Player* player = GetCharmerOrOwnerPlayerOrPlayerItself(); - - if (!player || (attackedPlayer && (attackedPlayer == player || (player->duel && player->duel->opponent == attackedPlayer)))) - return; - - player->SetContestedPvPTimer(30000); - if (!player->HasUnitState(UNIT_STATE_ATTACK_PLAYER)) - { - player->AddUnitState(UNIT_STATE_ATTACK_PLAYER); - player->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_CONTESTED_PVP); - // call MoveInLineOfSight for nearby contested guards - UpdateObjectVisibility(); - } - if (!HasUnitState(UNIT_STATE_ATTACK_PLAYER)) - { - AddUnitState(UNIT_STATE_ATTACK_PLAYER); - // call MoveInLineOfSight for nearby contested guards - UpdateObjectVisibility(); - } -} - Pet* Unit::CreateTamedPetFrom(Creature* creatureTarget, uint32 spell_id) { if (GetTypeId() != TYPEID_PLAYER) @@ -12184,7 +12149,7 @@ void Unit::Kill(Unit* victim, bool durabilityLoss) if (!creature->IsPet()) { - creature->DeleteThreatList(); + creature->GetThreatManager().ClearAllThreat(); // must be after setDeathState which resets dynamic flags if (!creature->loot.isLooted()) @@ -12576,7 +12541,7 @@ bool Unit::SetCharmedBy(Unit* charmer, CharmType type, AuraApplication const* au CastStop(); CombatStop(); /// @todo CombatStop(true) may cause crash (interrupt spells) - DeleteThreatList(); + GetThreatManager().ClearAllThreat(); Player* playerCharmer = charmer->ToPlayer(); @@ -12719,7 +12684,7 @@ void Unit::RemoveCharmedBy(Unit* charmer) CastStop(); CombatStop(); /// @todo CombatStop(true) may cause crash (interrupt spells) getHostileRefManager().deleteReferences(); - DeleteThreatList(); + GetThreatManager().ClearAllThreat(); if (_oldFactionId) { @@ -13177,8 +13142,8 @@ void Unit::SetPhaseMask(uint32 newPhaseMask, bool update) // modify threat lists for new phasemask if (GetTypeId() != TYPEID_PLAYER) { - std::list<HostileReference*> threatList = getThreatManager().getThreatList(); - std::list<HostileReference*> offlineThreatList = getThreatManager().getOfflineThreatList(); + std::list<HostileReference*> threatList = GetThreatManager().getThreatList(); + std::list<HostileReference*> offlineThreatList = GetThreatManager().getOfflineThreatList(); // merge expects sorted lists threatList.sort(); @@ -14027,15 +13992,15 @@ void Unit::UpdateHeight(float newZ) void Unit::SendThreatListUpdate() { - if (!getThreatManager().isThreatListEmpty()) + if (!GetThreatManager().isThreatListEmpty()) { - uint32 count = getThreatManager().getThreatList().size(); + uint32 count = GetThreatManager().getThreatList().size(); //TC_LOG_DEBUG("entities.unit", "WORLD: Send SMSG_THREAT_UPDATE Message"); WorldPacket data(SMSG_THREAT_UPDATE, 8 + count * 8); data << GetPackGUID(); data << uint32(count); - ThreatContainer::StorageType const& tlist = getThreatManager().getThreatList(); + ThreatContainer::StorageType const& tlist = GetThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr) { data << (*itr)->getUnitGuid().WriteAsPacked(); @@ -14047,16 +14012,16 @@ void Unit::SendThreatListUpdate() void Unit::SendChangeCurrentVictimOpcode(HostileReference* pHostileReference) { - if (!getThreatManager().isThreatListEmpty()) + if (!GetThreatManager().isThreatListEmpty()) { - uint32 count = getThreatManager().getThreatList().size(); + uint32 count = GetThreatManager().getThreatList().size(); TC_LOG_DEBUG("entities.unit", "WORLD: Send SMSG_HIGHEST_THREAT_UPDATE Message"); WorldPacket data(SMSG_HIGHEST_THREAT_UPDATE, 8 + 8 + count * 8); data << GetPackGUID(); data << pHostileReference->getUnitGuid().WriteAsPacked(); data << uint32(count); - ThreatContainer::StorageType const& tlist = getThreatManager().getThreatList(); + ThreatContainer::StorageType const& tlist = GetThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = tlist.begin(); itr != tlist.end(); ++itr) { data << (*itr)->getUnitGuid().WriteAsPacked(); diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 73ca8add151..1a32512a01b 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1000,6 +1000,7 @@ class TC_GAME_API Unit : public WorldObject bool IsWithinCombatRange(Unit const* obj, float dist2compare) const; bool IsWithinMeleeRange(Unit const* obj) const; float GetMeleeRange(Unit const* target) const; + virtual SpellSchoolMask GetMeleeDamageSchoolMask() const; void GetRandomContactPoint(Unit const* target, float& x, float& y, float& z, float distance2dMin, float distance2dMax) const; uint32 m_extraAttacks; bool m_canDualWield; @@ -1222,6 +1223,12 @@ class TC_GAME_API Unit : public WorldObject bool IsInFlight() const { return HasUnitState(UNIT_STATE_IN_FLIGHT); } + bool IsEngaged() const { return IsInCombat(); } + bool IsEngagedBy(Unit const* who) const { return IsInCombatWith(who); } + void EngageWithTarget(Unit* who) { SetInCombatWith(who); who->SetInCombatWith(this); GetThreatManager().AddThreat(who, 0.0f); } + bool IsThreatened() const { return CanHaveThreatList() && !GetThreatManager().IsThreatListEmpty(); } + bool IsThreatenedBy(Unit const* who) const { return who && CanHaveThreatList() && GetThreatManager().IsThreatenedBy(who); } + bool IsInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); } bool IsPetInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PET_IN_COMBAT); } bool IsInCombatWith(Unit const* who) const; @@ -1259,8 +1266,9 @@ class TC_GAME_API Unit : public WorldObject void SendHealSpellLog(HealInfo& healInfo, bool critical = false); int32 HealBySpell(HealInfo& healInfo, bool critical = false); - void SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, Powers powerType); - void EnergizeBySpell(Unit* victim, uint32 SpellID, int32 Damage, Powers powertype); + void SendEnergizeSpellLog(Unit* victim, uint32 spellId, int32 damage, Powers powerType); + void EnergizeBySpell(Unit* victim, uint32 spellId, int32 damage, Powers powerType); + void EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damage, Powers powerType); void CastSpell(SpellCastTargets const& targets, SpellInfo const* spellInfo, CustomSpellValues const* value, TriggerCastFlags triggerFlags = TRIGGERED_NONE, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); void CastSpell(Unit* victim, uint32 spellId, bool triggered, Item* castItem = nullptr, AuraEffect const* triggeredByAura = nullptr, ObjectGuid originalCaster = ObjectGuid::Empty); @@ -1661,12 +1669,11 @@ class TC_GAME_API Unit : public WorldObject // Threat related methods bool CanHaveThreatList(bool skipAliveCheck = false) const; - void AddThreat(Unit* victim, float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* threatSpell = nullptr); float ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL); - void DeleteThreatList(); void TauntApply(Unit* victim); void TauntFadeOut(Unit* taunter); - ThreatManager& getThreatManager() { return m_ThreatManager; } + ThreatManager& GetThreatManager() { return m_ThreatManager; } + ThreatManager const& GetThreatManager() const { return m_ThreatManager; } void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); } void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ } HostileRefManager& getHostileRefManager() { return m_HostileRefManager; } @@ -1974,8 +1981,6 @@ class TC_GAME_API Unit : public WorldObject CharmInfo* m_charmInfo; SharedVisionList m_sharedVision; - virtual SpellSchoolMask GetMeleeDamageSchoolMask() const; - MotionMaster* i_motionMaster; uint32 m_reactiveTimer[MAX_REACTIVE]; diff --git a/src/server/game/Grids/ObjectGridLoader.cpp b/src/server/game/Grids/ObjectGridLoader.cpp index 848df6f60dc..653c9d51d11 100644 --- a/src/server/game/Grids/ObjectGridLoader.cpp +++ b/src/server/game/Grids/ObjectGridLoader.cpp @@ -217,10 +217,10 @@ void ObjectGridStoper::Visit(CreatureMapType &m) for (CreatureMapType::iterator iter = m.begin(); iter != m.end(); ++iter) { iter->GetSource()->RemoveAllDynObjects(); - if (iter->GetSource()->IsInCombat() || !iter->GetSource()->getThreatManager().areThreatListsEmpty()) + if (iter->GetSource()->IsInCombat() || !iter->GetSource()->GetThreatManager().areThreatListsEmpty()) { iter->GetSource()->CombatStop(); - iter->GetSource()->DeleteThreatList(); + iter->GetSource()->GetThreatManager().ClearAllThreat(); iter->GetSource()->AI()->EnterEvadeMode(); } } diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index eedbd4f90b9..86713a4efd6 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -39,6 +39,7 @@ #include "Spell.h" #include "SpellHistory.h" #include "SpellMgr.h" +#include "ThreatManager.h" #include "Unit.h" #include "Util.h" #include "Vehicle.h" @@ -4371,7 +4372,7 @@ void AuraEffect::HandleAuraDummy(AuraApplication const* aurApp, uint8 mode, bool case 1515: // Tame beast // FIX_ME: this is 2.0.12 threat effect replaced in 2.1.x by dummy aura, must be checked for correctness if (caster && target->CanHaveThreatList()) - target->AddThreat(caster, 10.0f); + target->GetThreatManager().AddThreat(caster, 10.0f); break; case 13139: // net-o-matic // root to self part of (root_target->charge->root_self sequence @@ -5775,7 +5776,7 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c HealInfo healInfo(caster, caster, heal, GetSpellInfo(), GetSpellInfo()->GetSchoolMask()); caster->HealBySpell(healInfo); - caster->getHostileRefManager().threatAssist(caster, healInfo.GetEffectiveHeal() * 0.5f, GetSpellInfo()); + caster->GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal()*0.5f, GetSpellInfo()); caster->ProcSkillsAndAuras(caster, PROC_FLAG_DONE_PERIODIC, PROC_FLAG_TAKEN_PERIODIC, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_NONE, hitMask, nullptr, nullptr, &healInfo); } } @@ -5901,7 +5902,7 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const SpellPeriodicAuraLogInfo pInfo(this, heal, heal - healInfo.GetEffectiveHeal(), healInfo.GetAbsorb(), 0, 0.0f, crit); target->SendPeriodicAuraLog(&pInfo); - target->getHostileRefManager().threatAssist(caster, float(healInfo.GetEffectiveHeal()) * 0.5f, GetSpellInfo()); + target->GetThreatManager().ForwardThreatForAssistingMe(caster, float(healInfo.GetEffectiveHeal())*0.5f, GetSpellInfo()); bool haveCastItem = !GetBase()->GetCastItemGUID().IsEmpty(); @@ -5984,7 +5985,8 @@ void AuraEffect::HandlePeriodicManaLeechAuraTick(Unit* target, Unit* caster) con if (gainAmount) { gainedAmount = caster->ModifyPower(powerType, gainAmount); - target->AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellInfo()->GetSchoolMask(), GetSpellInfo()); + // energize is not modified by threat modifiers + target->GetThreatManager().AddThreat(caster, float(gainedAmount) * 0.5f, GetSpellInfo(), true); } // Drain Mana @@ -6035,7 +6037,7 @@ void AuraEffect::HandleObsModPowerAuraTick(Unit* target, Unit* caster) const int32 gain = target->ModifyPower(powerType, amount); if (caster) - target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellInfo()); + target->GetThreatManager().ForwardThreatForAssistingMe(caster, float(gain)*0.5f, GetSpellInfo(), true); } void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) const @@ -6070,7 +6072,7 @@ void AuraEffect::HandlePeriodicEnergizeAuraTick(Unit* target, Unit* caster) cons int32 gain = target->ModifyPower(powerType, amount); if (caster) - target->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, GetSpellInfo()); + target->GetThreatManager().ForwardThreatForAssistingMe(caster, float(gain)*0.5f, GetSpellInfo(), true); } void AuraEffect::HandlePeriodicPowerBurnAuraTick(Unit* target, Unit* caster) const diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 8309bf00fd3..d9990dfb033 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -2385,7 +2385,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) HealInfo healInfo(caster, unitTarget, addhealth, m_spellInfo, m_spellInfo->GetSchoolMask()); caster->HealBySpell(healInfo, crit); - unitTarget->getHostileRefManager().threatAssist(caster, float(healInfo.GetEffectiveHeal()) * 0.5f, m_spellInfo); + unitTarget->GetThreatManager().ForwardThreatForAssistingMe(caster, float(healInfo.GetEffectiveHeal())*0.5f, m_spellInfo); m_healing = healInfo.GetEffectiveHeal(); // Do triggers for unit @@ -2454,8 +2454,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (missInfo == SPELL_MISS_RESIST && m_spellInfo->HasAttribute(SPELL_ATTR0_CU_PICKPOCKET) && unitTarget->GetTypeId() == TYPEID_UNIT) { m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK); - if (unitTarget->ToCreature()->IsAIEnabled) - unitTarget->ToCreature()->AI()->AttackStart(m_caster); + unitTarget->ToCreature()->EngageWithTarget(m_caster); } } @@ -2558,14 +2557,16 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA // assisting case, healing and resurrection if (unit->HasUnitState(UNIT_STATE_ATTACK_PLAYER)) { - m_caster->SetContestedPvP(); - if (m_caster->GetTypeId() == TYPEID_PLAYER) - m_caster->ToPlayer()->UpdatePvP(true); + if (Player* playerOwner = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself()) + { + playerOwner->SetContestedPvP(); + playerOwner->UpdatePvP(true); + } } if (unit->IsInCombat() && m_spellInfo->HasInitialAggro()) { m_caster->SetInCombatState(unit->GetCombatTimer() > 0, unit); - unit->getHostileRefManager().threatAssist(m_caster, 0.0f); + unit->GetThreatManager().ForwardThreatForAssistingMe(m_caster, 0.0f, nullptr, true); } } } @@ -4786,14 +4787,14 @@ void Spell::HandleThreatSpells() // positive spells distribute threat among all units that are in combat with target, like healing if (m_spellInfo->IsPositive()) - target->getHostileRefManager().threatAssist(m_caster, threatToAdd, m_spellInfo); + target->GetThreatManager().ForwardThreatForAssistingMe(m_caster, threatToAdd, m_spellInfo); // for negative spells threat gets distributed among affected targets else { if (!target->CanHaveThreatList()) continue; - target->AddThreat(m_caster, threatToAdd, m_spellInfo->GetSchoolMask(), m_spellInfo); + target->GetThreatManager().AddThreat(m_caster, threatToAdd, m_spellInfo, true); } } TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->IsPositive() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size())); diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index 2201e39059b..72a39a6073b 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2476,7 +2476,7 @@ void Spell::EffectDistract(SpellEffIndex /*effIndex*/) return; // Check for possible target - if (!unitTarget || unitTarget->IsInCombat()) + if (!unitTarget || unitTarget->IsEngaged()) return; // target must be OK to do this @@ -3074,17 +3074,17 @@ void Spell::EffectTaunt(SpellEffIndex /*effIndex*/) if (m_spellInfo->Id == 62124 && (!unitTarget->IsPet() || !unitTarget->GetOwnerGUID().IsPlayer())) m_caster->CastSpell(unitTarget, 67485, true); - if (!unitTarget->getThreatManager().getOnlineContainer().empty()) + if (!unitTarget->GetThreatManager().getOnlineContainer().empty()) { // Also use this effect to set the taunter's threat to the taunted creature's highest value - float myThreat = unitTarget->getThreatManager().getThreat(m_caster); - float topThreat = unitTarget->getThreatManager().getOnlineContainer().getMostHated()->getThreat(); + float myThreat = unitTarget->GetThreatManager().getThreat(m_caster); + float topThreat = unitTarget->GetThreatManager().getOnlineContainer().getMostHated()->getThreat(); if (topThreat > myThreat) - unitTarget->getThreatManager().doAddThreat(m_caster, topThreat - myThreat); + unitTarget->GetThreatManager().doAddThreat(m_caster, topThreat - myThreat); //Set aggro victim to caster - if (HostileReference* forcedVictim = unitTarget->getThreatManager().getOnlineContainer().getReferenceByTarget(m_caster)) - unitTarget->getThreatManager().setCurrentVictim(forcedVictim); + if (HostileReference* forcedVictim = unitTarget->GetThreatManager().getOnlineContainer().getReferenceByTarget(m_caster)) + unitTarget->GetThreatManager().setCurrentVictim(forcedVictim); } if (unitTarget->ToCreature()->IsAIEnabled && !unitTarget->ToCreature()->HasReactState(REACT_PASSIVE)) @@ -3385,7 +3385,7 @@ void Spell::EffectThreat(SpellEffIndex /*effIndex*/) if (!unitTarget->CanHaveThreatList()) return; - unitTarget->AddThreat(m_caster, float(damage)); + unitTarget->GetThreatManager().AddThreat(m_caster, float(damage)); } void Spell::EffectHealMaxHealth(SpellEffIndex /*effIndex*/) @@ -4990,7 +4990,7 @@ void Spell::EffectModifyThreatPercent(SpellEffIndex /*effIndex*/) if (!unitTarget) return; - unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage); + unitTarget->GetThreatManager().ModifyThreatByPercent(m_caster, damage); } void Spell::EffectTransmitted(SpellEffIndex effIndex) diff --git a/src/server/scripts/Commands/cs_debug.cpp b/src/server/scripts/Commands/cs_debug.cpp index ea9024a30a3..69f7ecb3f9a 100644 --- a/src/server/scripts/Commands/cs_debug.cpp +++ b/src/server/scripts/Commands/cs_debug.cpp @@ -846,7 +846,7 @@ public: if (!target || target->IsTotem() || target->IsPet()) return false; - ThreatContainer::StorageType const& threatList = target->getThreatManager().getThreatList(); + ThreatContainer::StorageType const& threatList = target->GetThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator itr; uint32 count = 0; handler->PSendSysMessage("Threat list of %s (guid %u)", target->GetName().c_str(), target->GetGUID().GetCounter()); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp index 7d3d77f52b1..9b17017501b 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/boss_coren_direbrew.cpp @@ -321,7 +321,7 @@ public: }) .Schedule(Seconds(2), [this](TaskContext mugChuck) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, -SPELL_HAS_DARK_BREWMAIDENS_BREW)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, true, -SPELL_HAS_DARK_BREWMAIDENS_BREW)) DoCast(target, SPELL_CHUCK_MUG); mugChuck.Repeat(Seconds(4)); }); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp index 1ac6dfd542c..cf569cbeba5 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/instance_blackrock_depths.cpp @@ -376,7 +376,7 @@ public: {//do not call EnterEvadeMode(), it will create infinit loops boss->Respawn(); boss->RemoveAllAuras(); - boss->DeleteThreatList(); + boss->GetThreatManager().ClearAllThreat(); boss->CombatStop(true); boss->LoadCreaturesAddon(); boss->GetMotionMaster()->MoveTargetedHome(); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp index d8403641dfa..d60f821d314 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_broodlord_lashlayer.cpp @@ -89,8 +89,8 @@ public: break; case EVENT_KNOCKBACK: DoCastVictim(SPELL_KNOCKBACK); - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(me->GetVictim(), -50); + if (GetThreat(me->GetVictim())) + ModifyThreatByPercent(me->GetVictim(), -50); events.ScheduleEvent(EVENT_KNOCKBACK, urand(15000, 30000)); break; case EVENT_CHECK: diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp index 024fc54e6a0..835a6fd77f7 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_firemaw.cpp @@ -72,8 +72,8 @@ public: break; case EVENT_WINGBUFFET: DoCastVictim(SPELL_WINGBUFFET); - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(me->GetVictim(), -75); + if (GetThreat(me->GetVictim())) + ModifyThreatByPercent(me->GetVictim(), -75); events.ScheduleEvent(EVENT_WINGBUFFET, 30000); break; case EVENT_FLAMEBUFFET: diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp index 31d606975bb..a7cc955295c 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_flamegor.cpp @@ -77,8 +77,8 @@ public: break; case EVENT_WINGBUFFET: DoCastVictim(SPELL_WINGBUFFET); - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(me->GetVictim(), -75); + if (GetThreat(me->GetVictim())) + ModifyThreatByPercent(me->GetVictim(), -75); events.ScheduleEvent(EVENT_WINGBUFFET, 30000); break; case EVENT_FRENZY: diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp index f213a2be37c..b4b9e5da0e0 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_nefarian.cpp @@ -321,7 +321,7 @@ public: DoCast(target, SPELL_SHADOWBOLT); break; } - DoResetThreat(); + ResetThreatList(); events.ScheduleEvent(EVENT_SHADOW_BOLT, urand(3000, 10000)); break; case EVENT_FEAR: diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp index b7c4e32188d..14b73446602 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/BlackwingLair/boss_razorgore.cpp @@ -151,10 +151,6 @@ public: break; case EVENT_CONFLAGRATION: DoCastVictim(SPELL_CONFLAGRATION); - // @todo is this even necessary? pretty sure AI ignores targets with disorient by default - if (me->GetVictim() && me->EnsureVictim()->HasAura(SPELL_CONFLAGRATION)) - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100, true)) - me->TauntApply(target); events.ScheduleEvent(EVENT_CONFLAGRATION, 30000); break; } diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp index ef9378df968..f2e2a8e3e15 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_baron_geddon.cpp @@ -98,7 +98,7 @@ class boss_baron_geddon : public CreatureScript events.ScheduleEvent(EVENT_INFERNO, 45000); break; case EVENT_IGNITE_MANA: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IGNITE_MANA)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_IGNITE_MANA)) DoCast(target, SPELL_IGNITE_MANA); events.ScheduleEvent(EVENT_IGNITE_MANA, 30000); break; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp index 1fa9bfeec25..7ee31766add 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_magmadar.cpp @@ -97,7 +97,7 @@ class boss_magmadar : public CreatureScript events.ScheduleEvent(EVENT_PANIC, 35000); break; case EVENT_LAVA_BOMB: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_LAVA_BOMB)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_LAVA_BOMB)) DoCast(target, SPELL_LAVA_BOMB); events.ScheduleEvent(EVENT_LAVA_BOMB, 12000); break; diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp index 49bb5f11ecc..96af55e719c 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_ragnaros.cpp @@ -249,7 +249,7 @@ class boss_ragnaros : public CreatureScript //is not very well supported in the core //no it really isnt //so added normaly spawning and banish workaround and attack again after 90 secs. me->AttackStop(); - DoResetThreat(); + ResetThreatList(); me->SetReactState(REACT_PASSIVE); me->InterruptNonMeleeSpells(false); //Root self diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp index bf7e1d8a213..9bb68840955 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_shazzrah.cpp @@ -82,7 +82,7 @@ class boss_shazzrah : public CreatureScript DoCastVictim(SPELL_ARCANE_EXPLOSION); break; case EVENT_SHAZZRAH_CURSE: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHAZZRAH_CURSE)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_SHAZZRAH_CURSE)) DoCast(target, SPELL_SHAZZRAH_CURSE); events.ScheduleEvent(EVENT_SHAZZRAH_CURSE, urand(25000, 30000)); break; @@ -95,7 +95,7 @@ class boss_shazzrah : public CreatureScript events.ScheduleEvent(EVENT_COUNTERSPELL, urand(16000, 20000)); break; case EVENT_SHAZZRAH_GATE: - DoResetThreat(); + ResetThreatList(); DoCastAOE(SPELL_SHAZZRAH_GATE_DUMMY); events.ScheduleEvent(EVENT_ARCANE_EXPLOSION_TRIGGERED, 2000); events.RescheduleEvent(EVENT_ARCANE_EXPLOSION, urand(3000, 6000)); diff --git a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp index 778e4bd9069..6469ddea0fb 100644 --- a/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp +++ b/src/server/scripts/EasternKingdoms/BlackrockMountain/MoltenCore/boss_sulfuron_harbinger.cpp @@ -185,12 +185,12 @@ class npc_flamewaker_priest : public CreatureScript events.ScheduleEvent(EVENT_HEAL, urand(15000, 20000)); break; case EVENT_SHADOW_WORD_PAIN: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_SHADOWWORDPAIN)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_SHADOWWORDPAIN)) DoCast(target, SPELL_SHADOWWORDPAIN); events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, urand(18000, 26000)); break; case EVENT_IMMOLATE: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_IMMOLATE)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_IMMOLATE)) DoCast(target, SPELL_IMMOLATE); events.ScheduleEvent(EVENT_IMMOLATE, urand(15000, 25000)); break; diff --git a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp index f787da07308..83d0fdcc943 100644 --- a/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp +++ b/src/server/scripts/EasternKingdoms/Gnomeregan/gnomeregan.cpp @@ -214,11 +214,7 @@ public: continue; if (player->IsAlive()) - { - temp->SetInCombatWith(player); - player->SetInCombatWith(temp); - temp->AddThreat(player, 0.0f); - } + AddThreat(player, 0.0f, temp); } } } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_curator.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_curator.cpp index 8676bbe9520..44244eef0e7 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_curator.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_curator.cpp @@ -102,7 +102,7 @@ public: switch (eventId) { case EVENT_HATEFUL_BOLT: - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 1)) DoCast(target, SPELL_HATEFUL_BOLT); events.Repeat(Seconds(7), Seconds(15)); break; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp index fa7a27082d8..75b119e9936 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_midnight.cpp @@ -173,12 +173,11 @@ public: scheduler.Schedule(Seconds(10), Seconds(25), [this](TaskContext task) { Unit* target = nullptr; - ThreatContainer::StorageType const& t_list = me->getThreatManager().getThreatList(); std::vector<Unit*> target_list; - for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr) + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) { - target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); + target = ref->GetVictim(); if (target && !target->IsWithinDist(me, 8.00f, false) && target->IsWithinDist(me, 25.0f, false)) target_list.push_back(target); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp index 8b0f5a7a150..9ab217b6765 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_moroes.cpp @@ -300,14 +300,8 @@ public: if (Blind_Timer <= diff) { - std::list<Unit*> targets; - SelectTargetList(targets, 5, SELECT_TARGET_RANDOM, me->GetCombatReach()*5, true); - for (std::list<Unit*>::const_iterator i = targets.begin(); i != targets.end(); ++i) - if (!me->IsWithinMeleeRange(*i)) - { - DoCast(*i, SPELL_BLIND); - break; - } + if (Unit* target = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 0.0f, true, false)) + DoCast(target, SPELL_BLIND); Blind_Timer = 40000; } else Blind_Timer -= diff; } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp index 36777a5670c..be22ce083ec 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_netherspite.cpp @@ -227,7 +227,7 @@ public: } // aggro target if Red Beam if (j == RED_PORTAL && me->GetVictim() != target && target->GetTypeId() == TYPEID_PLAYER) - me->getThreatManager().addThreat(target, 100000.0f+DoGetThreat(me->GetVictim())); + AddThreat(target, 100000.0f); } } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp index 95510202610..ffabc345b4f 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_nightbane.cpp @@ -321,7 +321,7 @@ public: me->GetMotionMaster()->MoveAlongSplineChain(POINT_INTRO_END, SPLINE_CHAIN_INTRO_END, false); break; case EVENT_RAIN_OF_BONES: - DoResetThreat(); + ResetThreatList(); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { me->SetFacingToObject(target); diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp index e2843844076..837fdad72b3 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_prince_malchezaar.cpp @@ -316,19 +316,18 @@ public: if (!info) return; - ThreatContainer::StorageType const& t_list = me->getThreatManager().getThreatList(); + Unit* tank = me->GetThreatManager().GetCurrentVictim(); std::vector<Unit*> targets; - if (t_list.empty()) - return; + for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList()) + { + Unit* target = ref->GetVictim(); + if (target != tank && target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER) + targets.push_back(target); + } - //begin + 1, so we don't target the one with the highest threat - ThreatContainer::StorageType::const_iterator itr = t_list.begin(); - std::advance(itr, 1); - for (; itr != t_list.end(); ++itr) //store the threat list in a different container - if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) - if (target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER) - targets.push_back(target); + if (targets.empty()) + return; //cut down to size if we have more than 5 targets while (targets.size() > 5) @@ -455,9 +454,7 @@ public: if (target) { axe->AI()->AttackStart(target); - //axe->getThreatManager().tauntApply(target); //Taunt Apply and fade out does not work properly - // So we'll use a hack to add a lot of threat to our target - axe->AddThreat(target, 10000000.0f); + AddThreat(target, 10000000.0f, axe); } } } @@ -493,11 +490,9 @@ public: if (Unit* axe = ObjectAccessor::GetUnit(*me, axes[i])) { if (axe->GetVictim()) - DoModifyThreatPercent(axe->GetVictim(), -100); + ResetThreat(axe->GetVictim(), axe); if (target) - axe->AddThreat(target, 1000000.0f); - //axe->getThreatManager().tauntFadeOut(axe->GetVictim()); - //axe->getThreatManager().tauntApply(target); + AddThreat(target, 1000000.0f, axe); } } } diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp index 0f44933caeb..4309ae2d31f 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_shade_of_aran.cpp @@ -185,19 +185,11 @@ public: void FlameWreathEffect() { std::vector<Unit*> targets; - ThreatContainer::StorageType const& t_list = me->getThreatManager().getThreatList(); - - if (t_list.empty()) - return; - //store the threat list in a different container - for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) - { - Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - //only on alive players - if (target && target->IsAlive() && target->GetTypeId() == TYPEID_PLAYER) - targets.push_back(target); - } + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) + if (Player* target = ref->GetVictim()->ToPlayer()) + if (target->IsAlive()) + targets.push_back(target); //cut down to size if we have more than 3 targets while (targets.size() > 3) diff --git a/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp index 37c944500e5..85b9ddf84bf 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/boss_terestian_illhoof.cpp @@ -126,7 +126,7 @@ public: events.Repeat(Seconds(42)); break; case EVENT_SHADOWBOLT: - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0)) DoCast(target, SPELL_SHADOW_BOLT); events.Repeat(Seconds(4), Seconds(10)); break; diff --git a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp index 9a01970f68b..68dee5eadc8 100644 --- a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp +++ b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp @@ -924,11 +924,11 @@ public: { Talk(SAY_WOLF_HOOD); DoCast(target, SPELL_LITTLE_RED_RIDING_HOOD, true); - TempThreat = DoGetThreat(target); + TempThreat = GetThreat(target); if (TempThreat) - DoModifyThreatPercent(target, -100); + ModifyThreatByPercent(target, -100); HoodGUID = target->GetGUID(); - me->AddThreat(target, 1000000.0f); + AddThreat(target, 1000000.0f); ChaseTimer = 20000; IsChasing = true; } @@ -940,9 +940,9 @@ public: if (Unit* target = ObjectAccessor::GetUnit(*me, HoodGUID)) { HoodGUID.Clear(); - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -100); - me->AddThreat(target, TempThreat); + if (GetThreat(target)) + ModifyThreatByPercent(target, -100); + AddThreat(target, TempThreat); TempThreat = 0; } @@ -1257,7 +1257,7 @@ public: Julianne->GetMotionMaster()->Clear(); Julianne->setDeathState(JUST_DIED); Julianne->CombatStop(true); - Julianne->DeleteThreatList(); + Julianne->GetThreatManager().ClearAllThreat(); Julianne->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } return; @@ -1285,7 +1285,7 @@ public: Creature* Julianne = (ObjectAccessor::GetCreature((*me), JulianneGUID)); if (Julianne && Julianne->GetVictim()) { - me->AddThreat(Julianne->GetVictim(), 1.0f); + AddThreat(Julianne->GetVictim(), 1.0f); AttackStart(Julianne->GetVictim()); } } @@ -1527,7 +1527,7 @@ void boss_julianne::boss_julianneAI::DamageTaken(Unit* /*done_by*/, uint32 &dama Romulo->GetMotionMaster()->Clear(); Romulo->setDeathState(JUST_DIED); Romulo->CombatStop(true); - Romulo->DeleteThreatList(); + Romulo->GetThreatManager().ClearAllThreat(); Romulo->SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_LOOTABLE); } diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp index 600ab5d379b..5cf03b678f6 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_felblood_kaelthas.cpp @@ -199,15 +199,15 @@ public: if (!summonedUnit) return; - ThreatContainer::StorageType const& threatlist = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType const& threatlist = me->GetThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); if (unit && unit->IsAlive()) { - float threat = me->getThreatManager().getThreat(unit); - summonedUnit->AddThreat(unit, threat); + float threat = me->GetThreatManager().getThreat(unit); + AddThreat(unit, threat, summonedUnit); } } } @@ -217,7 +217,7 @@ public: float x = KaelLocations[0][0]; float y = KaelLocations[0][1]; me->UpdatePosition(x, y, LOCATION_Z, 0.0f); - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { @@ -230,7 +230,7 @@ public: void CastGravityLapseKnockUp() { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { @@ -243,7 +243,7 @@ public: void CastGravityLapseFly() // Use Fly Packet hack for now as players can't cast "fly" spells unless in map 530. Has to be done a while after they get knocked into the air... { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { @@ -259,7 +259,7 @@ public: void RemoveGravityLapse() { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList(); ThreatContainer::StorageType::const_iterator i = threatlist.begin(); for (i = threatlist.begin(); i != threatlist.end(); ++i) { @@ -399,7 +399,7 @@ public: if (Orb && target) { Orb->SetSpeedRate(MOVE_RUN, 0.5f); - Orb->AddThreat(target, 1000000.0f); + AddThreat(target, 1000000.0f, Orb); Orb->AI()->AttackStart(target); } } @@ -680,7 +680,7 @@ public: { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true)) { - me->AddThreat(target, 1.0f); + AddThreat(target, 1.0f); me->TauntApply(target); AttackStart(target); } diff --git a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp index 8cddec4b58f..da54f79f6c7 100644 --- a/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp +++ b/src/server/scripts/EasternKingdoms/MagistersTerrace/boss_priestess_delrissa.cpp @@ -169,16 +169,9 @@ public: Talk(SAY_AGGRO); for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { if (Unit* pAdd = ObjectAccessor::GetUnit(*me, m_auiLackeyGUID[i])) - { - if (!pAdd->GetVictim()) - { - who->SetInCombatWith(pAdd); - pAdd->AddThreat(who, 0.0f); - } - } - } + if (!pAdd->IsEngaged()) + AddThreat(who, 0.0f, pAdd); instance->SetBossState(DATA_DELRISSA, IN_PROGRESS); } @@ -402,25 +395,13 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI return; for (uint8 i = 0; i < MAX_ACTIVE_LACKEY; ++i) - { if (Unit* pAdd = ObjectAccessor::GetUnit(*me, m_auiLackeyGUIDs[i])) - { - if (!pAdd->GetVictim() && pAdd != me) - { - who->SetInCombatWith(pAdd); - pAdd->AddThreat(who, 0.0f); - } - } - } + if (!pAdd->IsEngaged() && pAdd != me) + AddThreat(who, 0.0f, pAdd); if (Creature* pDelrissa = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_DELRISSA))) - { - if (pDelrissa->IsAlive() && !pDelrissa->GetVictim()) - { - who->SetInCombatWith(pDelrissa); - pDelrissa->AddThreat(who, 0.0f); - } - } + if (pDelrissa->IsAlive() && !pDelrissa->IsEngaged()) + AddThreat(who, 0.0f, pDelrissa); } void JustDied(Unit* /*killer*/) override @@ -477,7 +458,7 @@ struct boss_priestess_lackey_commonAI : public ScriptedAI if (ResetThreatTimer <= diff) { - DoResetThreat(); + ResetThreatList(); ResetThreatTimer = urand(5000, 20000); } else ResetThreatTimer -= diff; } @@ -549,10 +530,10 @@ public: Unit* unit = SelectTarget(SELECT_TARGET_RANDOM, 0); - DoResetThreat(); + ResetThreatList(); if (unit) - me->AddThreat(unit, 1000.0f); + AddThreat(unit, 1000.0f); InVanish = true; Vanish_Timer = 30000; @@ -874,7 +855,7 @@ public: if (Blink_Timer <= diff) { bool InMeleeRange = false; - ThreatContainer::StorageType const& t_list = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType const& t_list = me->GetThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) { if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) @@ -968,7 +949,7 @@ public: if (Intercept_Stun_Timer <= diff) { bool InMeleeRange = false; - ThreatContainer::StorageType const& t_list = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType const& t_list = me->GetThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) { if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) diff --git a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp index bc950388ec7..5484bb78c2f 100644 --- a/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletEnclave/chapter5.cpp @@ -430,7 +430,7 @@ public: if (me->Attack(who, true)) { - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); me->SetInCombatWith(who); who->SetInCombatWith(me); DoStartMovement(who); @@ -1384,7 +1384,7 @@ public: if (me->HasAura(SPELL_THE_MIGHT_OF_MOGRAINE)) me->RemoveAurasDueToSpell(SPELL_THE_MIGHT_OF_MOGRAINE); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->InterruptNonMeleeSpells(false); me->SetWalk(false); @@ -1405,7 +1405,7 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiKorfaxGUID)) { temp->RemoveAllAuras(); - temp->DeleteThreatList(); + temp->GetThreatManager().ClearAllThreat(); temp->CombatStop(true); temp->AttackStop(); temp->SetFaction(me->GetFaction()); @@ -1416,7 +1416,7 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiMaxwellGUID)) { temp->RemoveAllAuras(); - temp->DeleteThreatList(); + temp->GetThreatManager().ClearAllThreat(); temp->CombatStop(true); temp->AttackStop(); temp->SetFaction(me->GetFaction()); @@ -1427,7 +1427,7 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiEligorGUID)) { temp->RemoveAllAuras(); - temp->DeleteThreatList(); + temp->GetThreatManager().ClearAllThreat(); temp->CombatStop(true); temp->AttackStop(); temp->SetFaction(me->GetFaction()); @@ -1439,7 +1439,7 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiKoltiraGUID)) { temp->RemoveAllAuras(); - temp->DeleteThreatList(); + temp->GetThreatManager().ClearAllThreat(); temp->CombatStop(true); temp->AttackStop(); temp->SetFaction(me->GetFaction()); @@ -1454,7 +1454,7 @@ public: if (Creature* temp = ObjectAccessor::GetCreature(*me, uiThassarianGUID)) { temp->RemoveAllAuras(); - temp->DeleteThreatList(); + temp->GetThreatManager().ClearAllThreat(); temp->CombatStop(true); temp->AttackStop(); temp->SetFaction(me->GetFaction()); @@ -1484,15 +1484,11 @@ public: { if (Creature* temp = ObjectAccessor::GetCreature(*me, ui_GUID)) if (temp->IsAlive()) - if (Unit* pTarger = SelectTarget(SELECT_TARGET_RANDOM, 0)) - if (pTarger->IsAlive()) + if (Unit* pTarget = SelectTarget(SELECT_TARGET_RANDOM, 0)) + if (pTarget->IsAlive()) { - // temp->DeleteThreatList(); - temp->AddThreat(pTarger, 0.0f); - temp->AI()->AttackStart(pTarger); - temp->SetInCombatWith(pTarger); - pTarger->SetInCombatWith(temp); - // temp->GetMotionMaster()->MoveChase(pTarger, 20.0f); + AddThreat(pTarget, 0.0f, temp); + temp->AI()->AttackStart(pTarget); } } @@ -1550,7 +1546,7 @@ public: { temp = me->SummonCreature(NPC_DEFENDER_OF_THE_LIGHT, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); temp->SetFaction(FACTION_SCARLET_CRUSADE); - me->AddThreat(temp, 0.0f); + AddThreat(temp, 0.0f); uiDefenderGUID[i] = temp->GetGUID(); } } @@ -1561,7 +1557,7 @@ public: { temp = me->SummonCreature(NPC_RIMBLAT_EARTHSHATTER, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); temp->SetFaction(FACTION_SCARLET_CRUSADE); - me->AddThreat(temp, 0.0f); + AddThreat(temp, 0.0f); uiEarthshatterGUID[i] = temp->GetGUID(); } } @@ -1570,7 +1566,7 @@ public: { temp = me->SummonCreature(NPC_KORFAX_CHAMPION_OF_THE_LIGHT, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); temp->SetFaction(FACTION_SCARLET_CRUSADE); - me->AddThreat(temp, 0.0f); + AddThreat(temp, 0.0f); uiKorfaxGUID = temp->GetGUID(); } temp = ObjectAccessor::GetCreature(*me, uiMaxwellGUID); @@ -1578,7 +1574,7 @@ public: { temp = me->SummonCreature(NPC_LORD_MAXWELL_TYROSUS, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); temp->SetFaction(FACTION_SCARLET_CRUSADE); - me->AddThreat(temp, 0.0f); + AddThreat(temp, 0.0f); uiMaxwellGUID = temp->GetGUID(); } temp = ObjectAccessor::GetCreature(*me, uiEligorGUID); @@ -1586,7 +1582,7 @@ public: { temp = me->SummonCreature(NPC_COMMANDER_ELIGOR_DAWNBRINGER, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 600000); temp->SetFaction(FACTION_SCARLET_CRUSADE); - me->AddThreat(temp, 0.0f); + AddThreat(temp, 0.0f); uiEligorGUID = temp->GetGUID(); } temp = ObjectAccessor::GetCreature(*me, uiRayneGUID); @@ -1594,7 +1590,7 @@ public: { temp = me->SummonCreature(NPC_RAYNE, LightofDawnLoc[0].GetPositionWithOffset({ float(rand32() % 30), float(rand32() % 30), 0.0f, 0.0f }), TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 300000); temp->SetFaction(FACTION_SCARLET_CRUSADE); - me->AddThreat(temp, 0.0f); + AddThreat(temp, 0.0f); uiRayneGUID = temp->GetGUID(); } } diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp index 5dcbf9490ec..d946e98706e 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_headless_horseman.cpp @@ -606,14 +606,6 @@ public: DoCast(me, SPELL_HEAD); caster->GetMotionMaster()->Clear(false); caster->GetMotionMaster()->MoveFollow(me, 6, float(urand(0, 5))); - //DoResetThreat();//not sure if need - ThreatContainer::StorageType threatlist = caster->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (unit && unit->IsAlive() && unit != caster) - me->AddThreat(unit, caster->getThreatManager().getThreat(unit)); - } } } @@ -863,7 +855,7 @@ public: if (!who || !me->IsValidAttackTarget(who) || me->GetVictim()) return; - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); if (sprouted) DoStartMovement(who); } diff --git a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp index 92db652813a..cfe5ae32599 100644 --- a/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp +++ b/src/server/scripts/EasternKingdoms/ScarletMonastery/boss_high_inquisitor_fairbanks.cpp @@ -120,7 +120,7 @@ public: //Sleep_Timer if (Sleep_Timer <= diff) { - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0)) DoCast(target, SPELL_SLEEP); Sleep_Timer = 30000; diff --git a/src/server/scripts/EasternKingdoms/Scholomance/boss_jandice_barov.cpp b/src/server/scripts/EasternKingdoms/Scholomance/boss_jandice_barov.cpp index e4d7140e6f1..fc8e74c0052 100644 --- a/src/server/scripts/EasternKingdoms/Scholomance/boss_jandice_barov.cpp +++ b/src/server/scripts/EasternKingdoms/Scholomance/boss_jandice_barov.cpp @@ -91,7 +91,7 @@ public: DoCast(SPELL_ILLUSION); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->SetDisplayId(11686); // Invisible Model - DoModifyThreatPercent(me->GetVictim(), -99); + ModifyThreatByPercent(me->GetVictim(), -99); events.ScheduleEvent(EVENT_SET_VISIBILITY, 3000); events.ScheduleEvent(EVENT_ILLUSION, 25000); break; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp index 66ef84c2273..0f8e0fc98f7 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_brutallus.cpp @@ -321,14 +321,8 @@ public: if (BurnTimer <= diff) { - std::list<Unit*> targets; - SelectTargetList(targets, 10, SELECT_TARGET_RANDOM, 100, true); - for (std::list<Unit*>::const_iterator i = targets.begin(); i != targets.end(); ++i) - if (!(*i)->HasAura(SPELL_BURN)) - { - (*i)->CastSpell((*i), SPELL_BURN, true); - break; - } + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_BURN)) + target->CastSpell(target, SPELL_BURN, true); BurnTimer = urand(60000, 180000); } else BurnTimer -= diff; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp index 51aad495c37..c872a654a1a 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_eredar_twins.cpp @@ -120,7 +120,7 @@ public: if (temp->isDead()) temp->Respawn(); else if (temp->GetVictim()) - me->getThreatManager().addThreat(temp->GetVictim(), 0.0f); + AddThreat(temp->GetVictim(), 0.0f); } if (!me->IsInCombat()) @@ -275,7 +275,7 @@ public: temp = DoSpawnCreature(NPC_SHADOW_IMAGE, 0, 0, 0, 0, TEMPSUMMON_CORPSE_DESPAWN, 10000); if (temp && target) { - temp->AddThreat(target, 1000000); //don't change target(healers) + AddThreat(target, 1000000.0f, temp); //don't change target(healers) temp->AI()->AttackStart(target); } } @@ -372,7 +372,7 @@ public: if (temp->isDead()) temp->Respawn(); else if (temp->GetVictim()) - me->getThreatManager().addThreat(temp->GetVictim(), 0.0f); + AddThreat(temp->GetVictim(), 0.0f); } if (!me->IsInCombat()) @@ -550,7 +550,7 @@ public: Creature* sisiter = instance->GetCreature(DATA_SACROLASH); if (sisiter && !sisiter->isDead() && sisiter->GetVictim()) { - me->AddThreat(sisiter->GetVictim(), 0.0f); + AddThreat(sisiter->GetVictim(), 0.0f); DoStartNoMovement(sisiter->GetVictim()); me->Attack(sisiter->GetVictim(), false); } diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp index 045f6d956bb..88254211099 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_felmyst.cpp @@ -385,7 +385,7 @@ public: uiFlightCount = 4; break; case 9: - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT)) DoStartMovement(target); else { @@ -397,7 +397,7 @@ public: me->SetDisableGravity(false); me->HandleEmoteCommand(EMOTE_ONESHOT_LAND); EnterPhase(PHASE_GROUND); - AttackStart(SelectTarget(SELECT_TARGET_TOPAGGRO)); + AttackStart(SelectTarget(SELECT_TARGET_MAXTHREAT)); break; } ++uiFlightCount; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp index f6c02074774..5dd4a3248ac 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kalecgos.cpp @@ -208,7 +208,7 @@ public: me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE + UNIT_FLAG_NOT_SELECTABLE); me->InterruptNonMeleeSpells(true); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(); ++TalkSequence; } @@ -301,7 +301,7 @@ public: if (SpectralBlastTimer <= diff) { - ThreatContainer::StorageType const& m_threatlist = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType const& m_threatlist = me->GetThreatManager().getThreatList(); std::list<Unit*> targetList; for (ThreatContainer::StorageType::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) { @@ -648,7 +648,7 @@ public: { KalecGUID = Kalec->GetGUID(); me->CombatStart(Kalec); - me->AddThreat(Kalec, 100.0f); + AddThreat(Kalec, 100.0f); Kalec->setActive(true); } Talk(SAY_SATH_AGGRO); @@ -775,12 +775,12 @@ public: if (ResetThreat <= diff) { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType threatlist = me->GetThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) { if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) if (unit->GetPositionZ() > me->GetPositionZ() + 5) - me->getThreatManager().modifyThreatPercent(unit, -100); + me->GetThreatManager().ModifyThreatByPercent(unit, -100); } ResetThreat = 1000; } else ResetThreat -= diff; diff --git a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp index 4e841a82e14..5dbd255ecd2 100644 --- a/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp +++ b/src/server/scripts/EasternKingdoms/SunwellPlateau/boss_kiljaeden.cpp @@ -469,7 +469,7 @@ public: break; case NPC_KILJAEDEN: summoned->CastSpell(summoned, SPELL_REBIRTH, false); - summoned->AddThreat(me->GetVictim(), 1.0f); + AddThreat(me->GetVictim(), 1.0f, summoned); break; } summons.Summon(summoned); @@ -670,7 +670,7 @@ public: Talk(SAY_KJ_REFLECTION); for (uint8 i = 0; i < 4; ++i) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true, -SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true, true, -SPELL_VENGEANCE_OF_THE_BLUE_FLIGHT)) { float x, y, z; target->GetPosition(x, y, z); @@ -955,7 +955,7 @@ public: { instance->SetBossState(DATA_KILJAEDEN, IN_PROGRESS); if (Creature* pControl = instance->GetCreature(DATA_KILJAEDEN_CONTROLLER)) - pControl->AddThreat(who, 1.0f); + AddThreat(who, 1.0f, pControl); me->InterruptNonMeleeSpells(true); } @@ -991,15 +991,8 @@ public: if (FelfirePortalTimer <= diff) { if (Creature* pPortal = DoSpawnCreature(NPC_FELFIRE_PORTAL, 0, 0, 0, 0, TEMPSUMMON_TIMED_DESPAWN, 20000)) - { - ThreatContainer::StorageType const& threatlist = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - { - Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (unit) - pPortal->AddThreat(unit, 1.0f); - } - } + for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList()) + AddThreat(ref->GetVictim(), 1.0f, pPortal); FelfirePortalTimer = 20000; } else FelfirePortalTimer -= diff; @@ -1059,7 +1052,7 @@ public: if (uiSpawnFiendTimer <= diff) { if (Creature* pFiend = DoSpawnCreature(NPC_VOLATILE_FELFIRE_FIEND, 0, 0, 0, 0, TEMPSUMMON_TIMED_OR_CORPSE_DESPAWN, 20000)) - pFiend->AddThreat(SelectTarget(SELECT_TARGET_RANDOM, 0), 100000.0f); + AddThreat(SelectTarget(SELECT_TARGET_RANDOM, 0), 100000.0f, pFiend); uiSpawnFiendTimer = urand(4000, 8000); } else uiSpawnFiendTimer -= diff; } @@ -1112,7 +1105,7 @@ public: if (!bLockedTarget) { - me->AddThreat(me->GetVictim(), 10000000.0f); + AddThreat(me->GetVictim(), 10000000.0f); bLockedTarget = true; } diff --git a/src/server/scripts/EasternKingdoms/Uldaman/boss_ironaya.cpp b/src/server/scripts/EasternKingdoms/Uldaman/boss_ironaya.cpp index 5a17339b4de..0f70182260b 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/boss_ironaya.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/boss_ironaya.cpp @@ -75,18 +75,10 @@ class boss_ironaya : public CreatureScript return; //If we are <50% hp do knockaway ONCE - if (!bHasCastKnockaway && HealthBelowPct(50)) + if (!bHasCastKnockaway && HealthBelowPct(50) && me->GetVictim()) { DoCastVictim(SPELL_KNOCKAWAY, true); - - // current aggro target is knocked away pick new target - Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0); - - if (!target || target == me->GetVictim()) - target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1); - - if (target) - me->TauntApply(target); + me->GetThreatManager().ResetThreat(me->EnsureVictim()); //Shouldn't cast this agian bHasCastKnockaway = true; diff --git a/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp b/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp index 9c84b399e43..6db29b9bc6a 100644 --- a/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp +++ b/src/server/scripts/EasternKingdoms/Uldaman/uldaman.cpp @@ -93,13 +93,7 @@ class npc_jadespine_basilisk : public CreatureScript //Stop attacking target thast asleep and pick new target uiCslumberTimer = 28000; - Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0); - - if (!target || target == me->GetVictim()) - target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100, true); - - if (target) - me->TauntApply(target); + me->GetThreatManager().ResetThreat(me->GetVictim()); } else uiCslumberTimer -= uiDiff; diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp index f1b6c993a41..2983ae15477 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_akilzon.cpp @@ -333,7 +333,7 @@ class boss_akilzon : public CreatureScript Creature* creature = me->SummonCreature(NPC_SOARING_EAGLE, x, y, z, 0, TEMPSUMMON_CORPSE_DESPAWN, 0); if (creature) { - creature->AddThreat(me->GetVictim(), 1.0f); + AddThreat(me->GetVictim(), 1.0f, creature); creature->AI()->AttackStart(me->GetVictim()); BirdGUIDs[i] = creature->GetGUID(); } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp index ead3781d89b..6bced5b64d0 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_hexlord.cpp @@ -614,7 +614,7 @@ class boss_alyson_antille : public CreatureScript if (me->Attack(who, false)) { me->GetMotionMaster()->MoveChase(who, 20); - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); } } } @@ -874,7 +874,7 @@ class boss_slither : public CreatureScript if (me->Attack(who, false)) { me->GetMotionMaster()->MoveChase(who, 20); - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); } } } diff --git a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp index 1ebecc41b4b..02313eab281 100644 --- a/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp +++ b/src/server/scripts/EasternKingdoms/ZulAman/boss_zuljin.cpp @@ -302,7 +302,7 @@ class boss_zuljin : public CreatureScript case 3: case 4: DoTeleportTo(CENTER_X, CENTER_Y, CENTER_Z, 100); - DoResetThreat(); + ResetThreatList(); me->SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID, 0); me->RemoveAurasDueToSpell(Transform[Phase].unaura); DoCast(me, Transform[Phase].spell); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp index 8946edbe809..9d2a8a61a9a 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_arlokk.cpp @@ -227,7 +227,7 @@ class boss_arlokk : public CreatureScript break; case EVENT_MARK_OF_ARLOKK: { - Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, urand(1, 3), 0.0f, false, -SPELL_MARK_OF_ARLOKK); + Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, urand(1, 3), 0.0f, false, true, -SPELL_MARK_OF_ARLOKK); if (!target) target = me->GetVictim(); if (target) @@ -250,7 +250,7 @@ class boss_arlokk : public CreatureScript me->UpdateDamagePhysical(BASE_ATTACK); */ me->AttackStop(); - DoResetThreat(); + ResetThreatList(); me->SetReactState(REACT_PASSIVE); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE|UNIT_FLAG_NOT_SELECTABLE); DoCast(me, SPELL_VANISH_VISUAL); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp index 4a6feab82eb..4561a2dd924 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_grilek.cpp @@ -83,8 +83,8 @@ class boss_grilek : public CreatureScript // grilek DoCast(me, SPELL_AVATAR); if (Unit* victim = me->GetVictim()) { - if (DoGetThreat(victim)) - DoModifyThreatPercent(victim, -50); + if (GetThreat(victim)) + ModifyThreatByPercent(victim, -50); } if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1)) diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp index 63d6388d497..ba259ac2000 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jeklik.cpp @@ -117,7 +117,7 @@ class boss_jeklik : public CreatureScript { me->RemoveAurasDueToSpell(SPELL_BAT_FORM); me->SetCanFly(false); - DoResetThreat(); + ResetThreatList(); events.SetPhase(PHASE_TWO); events.ScheduleEvent(EVENT_SHADOW_WORD_PAIN, 6000, 0, PHASE_TWO); events.ScheduleEvent(EVENT_MIND_FLAY, 11000, 0, PHASE_TWO); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp index 2c6ebefd1cb..5f9e3faef3f 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_jindo.cpp @@ -124,8 +124,8 @@ class boss_jindo : public CreatureScript if (Unit* target = me->GetVictim()) { DoCast(target, SPELL_HEX, true); - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -80); + if (GetThreat(target)) + ModifyThreatByPercent(target, -80); } events.ScheduleEvent(EVENT_HEX, urand(12000, 20000)); break; @@ -143,8 +143,8 @@ class boss_jindo : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) { DoTeleportPlayer(target, TeleportLoc.GetPositionX(), TeleportLoc.GetPositionY(), TeleportLoc.GetPositionZ(), TeleportLoc.GetOrientation()); - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(target, -100); + if (GetThreat(me->GetVictim())) + ModifyThreatByPercent(target, -100); // Summon a formation of trolls for (uint8 i = 0; i < 10; ++i) diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp index 9537aaec3e5..f9176d25a9a 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_marli.cpp @@ -160,8 +160,8 @@ class boss_marli : public CreatureScript */ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease); // hack DoCastVictim(SPELL_ENVOLWINGWEB); - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(me->GetVictim(), -100); + if (GetThreat(me->GetVictim())) + ModifyThreatByPercent(me->GetVictim(), -100); events.ScheduleEvent(EVENT_CHARGE_PLAYER, 1500, 0, PHASE_THREE); events.ScheduleEvent(EVENT_TRANSFORM_BACK, 25000, 0, PHASE_THREE); events.SetPhase(PHASE_THREE); diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp index 351445c0c62..972229a1a8f 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_renataki.cpp @@ -144,8 +144,8 @@ class boss_renataki : public CreatureScript { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) { - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(me->GetVictim(), -50); + if (GetThreat(me->GetVictim())) + ModifyThreatByPercent(me->GetVictim(), -50); AttackStart(target); } diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp index 7e6a9970629..3bcc13f6df3 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_thekal.cpp @@ -172,7 +172,7 @@ class boss_thekal : public CreatureScript me->UpdateDamagePhysical(BASE_ATTACK); */ me->ApplyStatPctModifier(UNIT_MOD_DAMAGE_MAINHAND, TOTAL_PCT, DamageIncrease); // hack - DoResetThreat(); + ResetThreatList(); events.ScheduleEvent(EVENT_FRENZY, 30000, 0, PHASE_TWO); // Phase 2 events.ScheduleEvent(EVENT_FORCEPUNCH, 4000, 0, PHASE_TWO); // Phase 2 events.ScheduleEvent(EVENT_SPELL_CHARGE, 12000, 0, PHASE_TWO); // Phase 2 @@ -226,7 +226,7 @@ class boss_thekal : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { DoCast(target, SPELL_CHARGE); - DoResetThreat(); + ResetThreatList(); AttackStart(target); } events.ScheduleEvent(EVENT_CHARGE, urand(15000, 22000), 0, PHASE_TWO); @@ -503,8 +503,8 @@ class npc_zealot_zath : public CreatureScript { DoCastVictim(SPELL_GOUGE); - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(me->GetVictim(), -100); + if (GetThreat(me->GetVictim())) + ModifyThreatByPercent(me->GetVictim(), -100); Gouge_Timer = 17000 + rand32() % 10000; } else Gouge_Timer -= diff; diff --git a/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp b/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp index e8b0b59d317..9be8fab7f61 100644 --- a/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp +++ b/src/server/scripts/EasternKingdoms/ZulGurub/boss_venoxis.cpp @@ -190,7 +190,7 @@ class boss_venoxis : public CreatureScript for (uint8 i = 0; i < 10; ++i) { - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, i)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, i)) // check if target is within melee-distance if (me->IsWithinMeleeRange(target)) ++_inMeleeRange; @@ -245,7 +245,7 @@ class boss_venoxis : public CreatureScript // shapeshift at 50% health DoCast(me, SPELL_VENOXIS_TRANSFORM); Talk(SAY_VENOXIS_TRANSFORM); - DoResetThreat(); + ResetThreatList(); // phase two events (snakeform) events.ScheduleEvent(EVENT_VENOM_SPIT, 5000, 0, PHASE_TWO); diff --git a/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp b/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp index 3109ec7c92e..db23c49f437 100644 --- a/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp +++ b/src/server/scripts/EasternKingdoms/zone_isle_of_queldanas.cpp @@ -70,7 +70,7 @@ public: if (Creature* Myrmidon = me->FindNearestCreature(NPC_DARKSPINE_MYRIDON, 70)) { - me->AddThreat(Myrmidon, 100000.0f); + AddThreat(Myrmidon, 100000.0f); AttackStart(Myrmidon); } } diff --git a/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp b/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp index bc0f6ea959f..4a4e19d0225 100644 --- a/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp +++ b/src/server/scripts/EasternKingdoms/zone_silverpine_forest.cpp @@ -236,7 +236,7 @@ public: target = me; summoned->SetFaction(FACTION_ENEMY); - summoned->AddThreat(target, 32.0f); + AddThreat(target, 32.0f, summoned); summoned->AI()->AttackStart(target); } } diff --git a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp b/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp index edcfc78d510..0d399cb907e 100644 --- a/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp +++ b/src/server/scripts/EasternKingdoms/zone_stranglethorn_vale.cpp @@ -79,7 +79,7 @@ public: { me->SetUInt32Value(UNIT_NPC_EMOTESTATE, EMOTE_STATE_STUN); me->CombatStop(); //stop combat - me->DeleteThreatList(); //unsure of this + me->GetThreatManager().ClearAllThreat(); //unsure of this me->SetFaction(FACTION_HORDE_GENERIC); bReset = true; @@ -111,7 +111,7 @@ public: if (player->GetTeam() == HORDE) { me->CombatStop(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); } } } diff --git a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp index 2966af7a3c5..51dbdf19a03 100644 --- a/src/server/scripts/EasternKingdoms/zone_wetlands.cpp +++ b/src/server/scripts/EasternKingdoms/zone_wetlands.cpp @@ -118,7 +118,7 @@ public: me->RestoreFaction(); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); SetRun(false); diff --git a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp index 8c57ce77ba0..921af01bfb4 100644 --- a/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp +++ b/src/server/scripts/Kalimdor/BlackfathomDeeps/blackfathom_deeps.cpp @@ -149,7 +149,7 @@ public: { me->SetInCombatWith(player); player->SetInCombatWith(me); - me->AddThreat(player, 0.0f); + AddThreat(player, 0.0f); } } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp index 4e9fdbc0bc3..b41eb13c46c 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_anetheron.cpp @@ -105,7 +105,7 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp index 4eb9a71cff4..985f4e214a8 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_azgalor.cpp @@ -108,7 +108,7 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp index d5b43ab4d2d..25c174cb26a 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_kazrogal.cpp @@ -103,7 +103,7 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp index 9d96aa20133..d1677b2c8ef 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/boss_rage_winterchill.cpp @@ -98,7 +98,7 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp index 882689ee76d..48b8e59a5a7 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjalAI.cpp @@ -422,7 +422,7 @@ void hyjalAI::EnterEvadeMode(EvadeReason /*why*/) { if (me->GetEntry() != JAINA) me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->LoadCreaturesAddon(); diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp index b26d9081fc8..f9cd454c67e 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/BattleForMountHyjal/hyjal_trash.cpp @@ -451,7 +451,7 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } } @@ -489,7 +489,7 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } else if (instance->GetData(DATA_ALLIANCE_RETREAT) && instance->GetData(DATA_HORDE_RETREAT)){ //do overrun } @@ -566,13 +566,13 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } else { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } if (waypointId == LastOverronPos && IsOverrun) @@ -664,13 +664,13 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } else { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } if (waypointId == LastOverronPos && IsOverrun) @@ -774,13 +774,13 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } else { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } } @@ -887,13 +887,13 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } else { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } } @@ -983,13 +983,13 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } else { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } } @@ -1069,13 +1069,13 @@ public: { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } else { Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_JAINAPROUDMOORE)); if (target && target->IsAlive()) - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); } } } @@ -1162,7 +1162,7 @@ public: Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) { - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); DoCast(target, SPELL_FROST_BREATH, true); } } @@ -1287,7 +1287,7 @@ public: Creature* target = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_THRALL)); if (target && target->IsAlive()) { - me->AddThreat(target, 0.0f); + AddThreat(target, 0.0f); DoCast(target, SPELL_GARGOYLE_STRIKE, true); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp index 0705071dfb9..502f129bc5c 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/instance_the_black_morass.cpp @@ -305,10 +305,10 @@ public: if (Creature* boss = SummonedPortalBoss(temp)) { if (boss->GetEntry() == NPC_AEONUS) - boss->AddThreat(medivh, 0.0f); + boss->GetThreatManager().AddThreat(medivh, 0.0f); else { - boss->AddThreat(temp, 0.0f); + boss->GetThreatManager().AddThreat(temp, 0.0f); temp->CastSpell(boss, SPELL_RIFT_CHANNEL, false); } } diff --git a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp index 6aa008f89f5..ffb34948ebc 100644 --- a/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp +++ b/src/server/scripts/Kalimdor/CavernsOfTime/TheBlackMorass/the_black_morass.cpp @@ -312,7 +312,7 @@ public: if (Unit* Summon = DoSummon(creature_entry, pos, 30000, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT)) if (Unit* temp = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_MEDIVH))) - Summon->AddThreat(temp, 0.0f); + AddThreat(temp, 0.0f, Summon); } void DoSelectSummon() diff --git a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp index 8799facf2f6..fd3eb006619 100644 --- a/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp +++ b/src/server/scripts/Kalimdor/OnyxiasLair/boss_onyxia.cpp @@ -236,7 +236,7 @@ public: // tank selection based on phase one. If tank is not there i take nearest one if (Unit* tank = ObjectAccessor::GetUnit(*me, tankGUID)) me->GetMotionMaster()->MoveChase(tank); - else if (Unit* newtarget = SelectTarget(SELECT_TARGET_NEAREST, 0)) + else if (Unit* newtarget = SelectTarget(SELECT_TARGET_MINDISTANCE, 0)) me->GetMotionMaster()->MoveChase(newtarget); events.ScheduleEvent(EVENT_BELLOWING_ROAR, 5000); events.ScheduleEvent(EVENT_FLAME_BREATH, urand(10000, 20000)); diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp index 59432c4051b..663a857d4e2 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_ayamiss.cpp @@ -170,7 +170,7 @@ class boss_ayamiss : public CreatureScript Position VictimPos = me->EnsureVictim()->GetPosition(); me->GetMotionMaster()->MovePoint(POINT_GROUND, VictimPos); } - DoResetThreat(); + ResetThreatList(); events.ScheduleEvent(EVENT_LASH, urand(5000, 8000)); events.ScheduleEvent(EVENT_TRASH, urand(3000, 6000)); events.CancelEvent(EVENT_POISON_STINGER); diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp index 88097b1ec30..d17d45c9be6 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_buru.cpp @@ -123,7 +123,7 @@ class boss_buru : public CreatureScript if (Unit* victim = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { - DoResetThreat(); + ResetThreatList(); AttackStart(victim); Talk(EMOTE_TARGET, victim); } diff --git a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp index f38f3058f7c..55dfdc8e2d5 100644 --- a/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp +++ b/src/server/scripts/Kalimdor/RuinsOfAhnQiraj/boss_moam.cpp @@ -148,10 +148,9 @@ class boss_moam : public CreatureScript { std::list<Unit*> targetList; { - const std::list<HostileReference*>& threatlist = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER && (*itr)->getTarget()->getPowerType() == POWER_MANA) - targetList.push_back((*itr)->getTarget()); + for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList()) + if (ref->GetVictim()->GetTypeId() == TYPEID_PLAYER && ref->GetVictim()->getPowerType() == POWER_MANA) + targetList.push_back(ref->GetVictim()); } Trinity::Containers::RandomResize(targetList, 5); diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp index 779e973f330..2a775ecf9fd 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_bug_trio.cpp @@ -220,8 +220,8 @@ public: if (KnockBack_Timer <= diff) { DoCastVictim(SPELL_KNOCKBACK); - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(me->GetVictim(), -80); + if (GetThreat(me->GetVictim())) + ModifyThreatByPercent(me->GetVictim(), -80); KnockBack_Timer = urand(15000, 25000); } else KnockBack_Timer -= diff; @@ -308,7 +308,7 @@ public: if (Fear_Timer <= diff) { DoCastVictim(SPELL_FEAR); - DoResetThreat(); + ResetThreatList(); Fear_Timer = 20000; } else Fear_Timer -= diff; diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp index 6f531894c98..e5eab1ecda3 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_cthun.cpp @@ -650,8 +650,8 @@ public: //Place all units in threat list on outside of stomach Stomach_Map.clear(); - for (std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); i != me->getThreatManager().getThreatList().end(); ++i) - Stomach_Map[(*i)->getUnitGuid()] = false; //Outside stomach + for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList()) + Stomach_Map[ref->GetVictim()->GetGUID()] = false; //Outside stomach //Spawn 2 flesh tentacles FleshTentaclesKilled = 0; diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp index e03bbe211c5..9e251100c8f 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_fankriss.cpp @@ -151,8 +151,8 @@ public: { DoCast(target, SPELL_ROOT); - if (DoGetThreat(target)) - DoModifyThreatPercent(target, -100); + if (GetThreat(target)) + ModifyThreatByPercent(target, -100); Creature* Hatchling = nullptr; switch (urand(0, 2)) diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp index 8d1e8ad302e..8f19acc3a14 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_sartura.cpp @@ -119,8 +119,7 @@ public: //Attack random Gamers if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true)) { - me->AddThreat(target, 1.0f); - me->TauntApply(target); + AddThreat(target, 1.0f); AttackStart(target); } WhirlWindRandom_Timer = urand(3000, 7000); @@ -147,8 +146,7 @@ public: //Attack random Gamers if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true)) { - me->AddThreat(target, 1.0f); - me->TauntApply(target); + AddThreat(target, 1.0f); AttackStart(target); } AggroReset = true; @@ -262,8 +260,7 @@ public: //Attack random Gamers if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true)) { - me->AddThreat(target, 1.0f); - me->TauntApply(target); + AddThreat(target, 1.0f); AttackStart(target); } @@ -283,8 +280,7 @@ public: //Attack random Gamers if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true)) { - me->AddThreat(target, 1.0f); - me->TauntApply(target); + AddThreat(target, 1.0f); AttackStart(target); } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp index 76833e06841..7cb3f40898e 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_skeram.cpp @@ -166,7 +166,7 @@ class boss_skeram : public CreatureScript break; case EVENT_BLINK: DoCast(me, BlinkSpells[urand(0, 2)]); - DoResetThreat(); + ResetThreatList(); me->SetVisible(true); events.ScheduleEvent(EVENT_BLINK, urand(10000, 30000)); break; diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp index d98cf055d30..bbcf18d5b84 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_twinemperors.cpp @@ -243,7 +243,7 @@ struct boss_twinemperorsAI : public ScriptedAI { me->InterruptNonMeleeSpells(false); DoStopAttack(); - DoResetThreat(); + ResetThreatList(); DoCast(me, SPELL_TWIN_TELEPORT_VISUAL); me->AddUnitState(UNIT_STATE_STUNNED); AfterTeleport = true; @@ -272,7 +272,7 @@ struct boss_twinemperorsAI : public ScriptedAI { //DoYell(nearu->GetName(), LANG_UNIVERSAL, 0); AttackStart(nearu); - me->AddThreat(nearu, 10000); + AddThreat(nearu, 10000); } return true; } @@ -436,7 +436,7 @@ public: void CastSpellOnBug(Creature* target) override { target->SetFaction(FACTION_MONSTER); - target->AI()->AttackStart(me->getThreatManager().getHostilTarget()); + target->AI()->AttackStart(me->GetThreatManager().GetCurrentVictim()); target->AddAura(SPELL_MUTATE_BUG, target); target->SetFullHealth(); } @@ -567,7 +567,7 @@ public: if (ArcaneBurst_Timer <= diff) { - if (Unit* mvic = SelectTarget(SELECT_TARGET_NEAREST, 0, NOMINAL_MELEE_RANGE, true)) + if (Unit* mvic = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, NOMINAL_MELEE_RANGE, true)) { DoCast(mvic, SPELL_ARCANEBURST); ArcaneBurst_Timer = 5000; @@ -602,7 +602,7 @@ public: if (me->Attack(who, false)) { me->GetMotionMaster()->MoveChase(who, VEKLOR_DIST, 0); - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); } } } diff --git a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp index 189b706d153..fb654f0c7c7 100644 --- a/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp +++ b/src/server/scripts/Kalimdor/TempleOfAhnQiraj/boss_viscidus.cpp @@ -213,7 +213,7 @@ class boss_viscidus : public CreatureScript if (_phase == PHASE_GLOB && summons.empty()) { - DoResetThreat(); + ResetThreatList(); me->NearTeleportTo(ViscidusCoord.GetPositionX(), ViscidusCoord.GetPositionY(), ViscidusCoord.GetPositionZ(), diff --git a/src/server/scripts/Kalimdor/boss_azuregos.cpp b/src/server/scripts/Kalimdor/boss_azuregos.cpp index a5ade380e31..53a566fef97 100644 --- a/src/server/scripts/Kalimdor/boss_azuregos.cpp +++ b/src/server/scripts/Kalimdor/boss_azuregos.cpp @@ -118,14 +118,14 @@ class boss_azuregos : public CreatureScript case EVENT_TELEPORT: { Talk(SAY_TELEPORT); - ThreatContainer::StorageType const& threatlist = me->getThreatManager().getThreatList(); + ThreatContainer::StorageType const& threatlist = me->GetThreatManager().getThreatList(); for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) { if (Player* player = ObjectAccessor::GetPlayer(*me, (*i)->getUnitGuid())) DoTeleportPlayer(player, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ()+3, player->GetOrientation()); } - DoResetThreat(); + ResetThreatList(); events.ScheduleEvent(EVENT_TELEPORT, 30000); break; } diff --git a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp index afecffd2ff1..fe965718852 100644 --- a/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp +++ b/src/server/scripts/Kalimdor/zone_bloodmyst_isle.cpp @@ -672,7 +672,7 @@ public: if (!target) target = me; - target->AddThreat(sironas, 0.001f); + AddThreat(sironas, 0.001f, target); sironas->Attack(target, true); sironas->GetMotionMaster()->MoveChase(target); } diff --git a/src/server/scripts/Kalimdor/zone_desolace.cpp b/src/server/scripts/Kalimdor/zone_desolace.cpp index 9027b59f3e3..4360574a65f 100644 --- a/src/server/scripts/Kalimdor/zone_desolace.cpp +++ b/src/server/scripts/Kalimdor/zone_desolace.cpp @@ -90,7 +90,7 @@ public: me->UpdateEntry(NPC_TAMED_KODO); me->CombatStop(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->SetSpeedRate(MOVE_RUN, 0.6f); me->GetMotionMaster()->MoveFollow(caster, PET_FOLLOW_DIST, me->GetFollowAngle()); me->setActive(true); diff --git a/src/server/scripts/Kalimdor/zone_durotar.cpp b/src/server/scripts/Kalimdor/zone_durotar.cpp index d35c90fca0c..168c20d5654 100644 --- a/src/server/scripts/Kalimdor/zone_durotar.cpp +++ b/src/server/scripts/Kalimdor/zone_durotar.cpp @@ -174,7 +174,7 @@ class npc_tiger_matriarch : public CreatureScript _tigerGuid = summoner->GetVehicle()->GetBase()->GetGUID(); if (Unit* tiger = ObjectAccessor::GetUnit(*me, _tigerGuid)) { - me->AddThreat(tiger, 500000.0f); + AddThreat(tiger, 500000.0f); DoCast(me, SPELL_FURIOUS_BITE); } } diff --git a/src/server/scripts/Kalimdor/zone_moonglade.cpp b/src/server/scripts/Kalimdor/zone_moonglade.cpp index e8e6f5ff8d8..3dbab7098fe 100644 --- a/src/server/scripts/Kalimdor/zone_moonglade.cpp +++ b/src/server/scripts/Kalimdor/zone_moonglade.cpp @@ -301,7 +301,7 @@ public: case 0: if (Creature* mob = me->SummonCreature(ASPECT_RAVEN, AspectRavenSummon, TEMPSUMMON_CORPSE_TIMED_DESPAWN, 2000)) { - mob->AddThreat(me, 10000.0f); + AddThreat(me, 10000.0f, mob); mob->AI()->AttackStart(me); } EventTimer = 2000; diff --git a/src/server/scripts/Kalimdor/zone_silithus.cpp b/src/server/scripts/Kalimdor/zone_silithus.cpp index 34d3cc7cded..f5b6ebba946 100644 --- a/src/server/scripts/Kalimdor/zone_silithus.cpp +++ b/src/server/scripts/Kalimdor/zone_silithus.cpp @@ -1236,8 +1236,7 @@ class go_wind_stone : public GameObjectScript break; } summons->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); - summons->SendMeleeAttackStart(player); - summons->CombatStart(player); + summons->EngageWithTarget(player); } public: diff --git a/src/server/scripts/Kalimdor/zone_the_barrens.cpp b/src/server/scripts/Kalimdor/zone_the_barrens.cpp index 1705f3e8dea..4e1c211ddde 100644 --- a/src/server/scripts/Kalimdor/zone_the_barrens.cpp +++ b/src/server/scripts/Kalimdor/zone_the_barrens.cpp @@ -220,7 +220,7 @@ public: void DoFriend() { me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->StopMoving(); diff --git a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp index 30ba1180663..882b3c22410 100644 --- a/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/Ahnkahet/boss_jedoga_shadowseeker.cpp @@ -191,7 +191,7 @@ public: else { who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); } } } diff --git a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp index faaa22cf9ac..89b5268684d 100644 --- a/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp +++ b/src/server/scripts/Northrend/AzjolNerub/AzjolNerub/boss_hadronox.cpp @@ -162,7 +162,7 @@ public: bool IsInCombatWithPlayer() const { - std::list<HostileReference*> const& refs = me->getThreatManager().getThreatList(); + std::list<HostileReference*> const& refs = me->GetThreatManager().getThreatList(); for (HostileReference const* hostileRef : refs) { if (Unit const* target = hostileRef->getTarget()) diff --git a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp index 22eb9cdb04a..c74dd3dec6b 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/ObsidianSanctum/obsidian_sanctum.cpp @@ -220,7 +220,7 @@ struct dummy_dragonAI : public ScriptedAI me->SetInCombatWithZone(); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0, true)) { - me->AddThreat(target, 1.0f); + me->GetThreatManager().AddThreat(target, 1.0f); me->Attack(target, true); me->GetMotionMaster()->MoveChase(target); } diff --git a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp index 1256e5745b3..472dc16191f 100644 --- a/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp +++ b/src/server/scripts/Northrend/ChamberOfAspects/RubySanctum/boss_halion.cpp @@ -345,7 +345,7 @@ class boss_halion : public CreatureScript break; case EVENT_METEOR_STRIKE: { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_TWILIGHT_REALM)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_TWILIGHT_REALM)) { _meteorStrikePos = target->GetPosition(); me->CastSpell(_meteorStrikePos.GetPositionX(), _meteorStrikePos.GetPositionY(), _meteorStrikePos.GetPositionZ(), SPELL_METEOR_STRIKE, true, nullptr, nullptr, me->GetGUID()); @@ -356,7 +356,7 @@ class boss_halion : public CreatureScript } case EVENT_FIERY_COMBUSTION: { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_TWILIGHT_REALM)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_TWILIGHT_REALM)) me->CastSpell(target, SPELL_FIERY_COMBUSTION, TRIGGERED_IGNORE_SET_FACING); events.ScheduleEvent(EVENT_FIERY_COMBUSTION, Seconds(25)); break; @@ -527,7 +527,7 @@ class boss_twilight_halion : public CreatureScript events.ScheduleEvent(EVENT_BREATH, randtime(Seconds(10), Seconds(14))); break; case EVENT_SOUL_CONSUMPTION: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, SPELL_TWILIGHT_REALM)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, SPELL_TWILIGHT_REALM)) me->CastSpell(target, SPELL_SOUL_CONSUMPTION, TRIGGERED_IGNORE_SET_FACING); events.ScheduleEvent(EVENT_SOUL_CONSUMPTION, Seconds(20)); break; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp index 5181b125fdf..4bb64f22dfc 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/boss_grand_champions.cpp @@ -115,7 +115,7 @@ void AggroAllPlayers(Creature* temp) temp->SetReactState(REACT_AGGRESSIVE); temp->SetInCombatWith(player); player->SetInCombatWith(temp); - temp->AddThreat(player, 0.0f); + temp->GetThreatManager().AddThreat(player, 0.0f); } } } @@ -263,8 +263,8 @@ public: Player* player = itr->GetSource(); if (player && !player->IsGameMaster() && me->IsInRange(player, 8.0f, 25.0f, false)) { - DoResetThreat(); - me->AddThreat(player, 1.0f); + ResetThreatList(); + me->GetThreatManager().AddThreat(player, 1.0f); DoCast(player, SPELL_CHARGE); break; } @@ -409,8 +409,8 @@ public: Player* player = itr->GetSource(); if (player && !player->IsGameMaster() && me->IsInRange(player, 8.0f, 25.0f, false)) { - DoResetThreat(); - me->AddThreat(player, 5.0f); + ResetThreatList(); + me->GetThreatManager().AddThreat(player, 5.0f); DoCast(player, SPELL_INTERCEPT); break; } @@ -847,7 +847,7 @@ public: if (uiShootTimer <= uiDiff) { - if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0, 30.0f)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXDISTANCE, 0, 30.0f)) { uiTargetGUID = target->GetGUID(); DoCast(target, SPELL_SHOOT); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp index 4dc43888726..efedf67069f 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheChampion/trial_of_the_champion.cpp @@ -384,9 +384,7 @@ public: temp->SetHomePosition(me->GetPositionX(), me->GetPositionY(), me->GetPositionZ(), me->GetOrientation()); temp->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE); temp->SetReactState(REACT_AGGRESSIVE); - temp->SetInCombatWith(player); - player->SetInCombatWith(temp); - temp->AddThreat(player, 0.0f); + AddThreat(player, 0.0f, temp); } } } diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp index 60479c6be30..72ac4f0e499 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_anubarak_trial.cpp @@ -261,7 +261,7 @@ class boss_anubarak_trial : public CreatureScript summoned->SetDisplayId(summoned->GetCreatureTemplate()->Modelid1); if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { - summoned->CombatStart(target); + summoned->EngageWithTarget(target); Talk(EMOTE_SPIKE, target); } break; @@ -814,12 +814,11 @@ class npc_anubarak_spike : public CreatureScript DoCast(who, SPELL_MARK); me->SetSpeedRate(MOVE_RUN, 0.5f); // make sure the Spine will really follow the one he should - me->getThreatManager().clearReferences(); + ResetThreatList(); me->SetInCombatWithZone(); - me->getThreatManager().addThreat(who, std::numeric_limits<float>::max()); + AddThreat(who, 1000000.0f); me->GetMotionMaster()->Clear(true); me->GetMotionMaster()->MoveChase(who); - me->TauntApply(who); } private: diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp index ef37afffc04..d4fade43ba4 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_faction_champions.cpp @@ -611,20 +611,9 @@ struct boss_faction_championsAI : public BossAI void UpdateThreat() { - std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::const_iterator itr = tList.begin(); itr != tList.end(); ++itr) - { - Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (unit && me->getThreatManager().getThreat(unit)) - { - if (unit->GetTypeId() == TYPEID_PLAYER) - { - float threat = CalculateThreat(me->GetDistance2d(unit), (float)unit->GetArmor(), unit->GetHealth()); - me->getThreatManager().modifyThreatPercent(unit, -100); - me->AddThreat(unit, 1000000.0f * threat); - } - } - } + for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList()) + if (Player* victim = ref->GetVictim()->ToPlayer()) + ref->SetThreat(1000000.0f * CalculateThreat(me->GetDistance2d(victim), victim->GetArmor(), victim->GetHealth())); } void UpdatePower() @@ -693,7 +682,7 @@ struct boss_faction_championsAI : public BossAI Unit* SelectEnemyCaster(bool /*casting*/) { - std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList(); + std::list<HostileReference*> const& tList = me->GetThreatManager().getThreatList(); std::list<HostileReference*>::const_iterator iter; for (iter = tList.begin(); iter!=tList.end(); ++iter) { @@ -706,15 +695,10 @@ struct boss_faction_championsAI : public BossAI uint32 EnemiesInRange(float distance) { - std::list<HostileReference*> const& tList = me->getThreatManager().getThreatList(); - std::list<HostileReference*>::const_iterator iter; uint32 count = 0; - for (iter = tList.begin(); iter != tList.end(); ++iter) - { - Unit* target = ObjectAccessor::GetUnit(*me, (*iter)->getUnitGuid()); - if (target && me->GetDistance2d(target) < distance) - ++count; - } + for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList()) + if (me->GetDistance2d(ref->GetVictim()) < distance) + ++count; return count; } @@ -725,9 +709,7 @@ struct boss_faction_championsAI : public BossAI if (me->Attack(who, true)) { - me->AddThreat(who, 10.0f); - me->SetInCombatWith(who); - who->SetInCombatWith(me); + AddThreat(who, 10.0f); if (_aiType == AI_MELEE || _aiType == AI_PET) DoStartMovement(who); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp index 7b6a20c1dd7..767f46756ea 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_lord_jaraxxus.cpp @@ -161,12 +161,12 @@ class boss_jaraxxus : public CreatureScript events.ScheduleEvent(EVENT_FEL_FIREBALL, urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS)); return; case EVENT_FEL_LIGHTNING: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_LORD_HITTIN)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_LORD_HITTIN)) DoCast(target, SPELL_FEL_LIGHTING); events.ScheduleEvent(EVENT_FEL_LIGHTNING, urand(10*IN_MILLISECONDS, 15*IN_MILLISECONDS)); return; case EVENT_INCINERATE_FLESH: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_LORD_HITTIN)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_LORD_HITTIN)) { Talk(EMOTE_INCINERATE, target); Talk(SAY_INCINERATE); @@ -179,7 +179,7 @@ class boss_jaraxxus : public CreatureScript events.ScheduleEvent(EVENT_NETHER_POWER, 40*IN_MILLISECONDS); return; case EVENT_LEGION_FLAME: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_LORD_HITTIN)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_LORD_HITTIN)) { Talk(EMOTE_LEGION_FLAME, target); DoCast(target, SPELL_LEGION_FLAME); diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp index ba4c19b316d..73dd987171e 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/boss_twin_valkyr.cpp @@ -319,7 +319,7 @@ struct boss_twin_baseAI : public BossAI events.ScheduleEvent(EVENT_TWIN_SPIKE, 20 * IN_MILLISECONDS); break; case EVENT_TOUCH: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true, OtherEssenceSpellId)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 200.0f, true, true, OtherEssenceSpellId)) me->CastCustomSpell(TouchSpellId, SPELLVALUE_MAX_TARGETS, 1, target, false); events.ScheduleEvent(EVENT_TOUCH, urand(10 * IN_MILLISECONDS, 15 * IN_MILLISECONDS)); break; diff --git a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp index c966f74cd89..8a404f66cc5 100644 --- a/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp +++ b/src/server/scripts/Northrend/CrusadersColiseum/TrialOfTheCrusader/trial_of_the_crusader.cpp @@ -555,8 +555,7 @@ class npc_fizzlebang_toc : public CreatureScript { //1-shot Fizzlebang jaraxxus->CastSpell(me, 67888, false); // 67888 - Fel Lightning - me->SetInCombatWith(jaraxxus); - jaraxxus->AddThreat(me, 1000.0f); + AddThreat(me, 1000.0f, jaraxxus); jaraxxus->AI()->AttackStart(me); } _instance->SetData(TYPE_EVENT, 1160); @@ -683,7 +682,7 @@ class npc_tirion_toc : public CreatureScript break; case 400: Talk(SAY_STAGE_0_06); - me->getThreatManager().clearReferences(); + me->GetThreatManager().ClearAllThreat(); _updateTimer = 5*IN_MILLISECONDS; _instance->SetData(TYPE_EVENT, 0); break; diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp index ab35de44aeb..1bedf9f7961 100644 --- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp @@ -960,14 +960,12 @@ class npc_jaina_or_sylvanas_escape_hor : public CreatureScript void DeleteAllFromThreatList(Unit* target, ObjectGuid except) { - ThreatContainer::StorageType threatlist = target->getThreatManager().getThreatList(); - for (auto i : threatlist) - { - if (i->getUnitGuid() == except) - continue; - - i->removeReference(); - } + std::vector<ThreatReference*> toClear; + for (ThreatReference* ref : target->GetThreatManager().GetUnsortedThreatList()) + if (ref->GetVictim()->GetGUID() != except) + toClear.push_back(ref); + for (ThreatReference* ref : toClear) + ref->ClearThreat(); } void UpdateAI(uint32 diff) override @@ -1346,7 +1344,7 @@ class npc_the_lich_king_escape_hor : public CreatureScript AttackStart(victim); return me->GetVictim() != nullptr; } - else if (me->getThreatManager().getThreatList().size() < 2 && me->HasAura(SPELL_REMORSELESS_WINTER)) + else if (me->GetThreatManager().GetThreatListSize() < 2 && me->HasAura(SPELL_REMORSELESS_WINTER)) { EnterEvadeMode(EVADE_REASON_OTHER); return false; @@ -1929,7 +1927,7 @@ class npc_frostsworn_general : public CreatureScript void SummonClones() { std::list<Unit*> playerList; - SelectTargetList(playerList, 5, SELECT_TARGET_TOPAGGRO, 0.0f, true); + SelectTargetList(playerList, 5, SELECT_TARGET_MAXTHREAT, 0, 0.0f, true); for (Unit* target : playerList) { if (Creature* reflection = me->SummonCreature(NPC_REFLECTION, *target, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 3000)) @@ -2172,7 +2170,7 @@ struct npc_escape_event_trash : public ScriptedAI me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); me->SetInCombatWith(leader); leader->SetInCombatWith(me); - me->AddThreat(leader, 0.0f); + AddThreat(leader, 0.0f); } } @@ -2292,7 +2290,7 @@ class npc_risen_witch_doctor : public CreatureScript _events.ScheduleEvent(EVENT_RISEN_WITCH_DOCTOR_CURSE, urand(10000, 15000)); break; case EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT: - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, 20.0f, true)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0, 20.0f, true)) DoCast(target, SPELL_SHADOW_BOLT); _events.ScheduleEvent(EVENT_RISEN_WITCH_DOCTOR_SHADOW_BOLT, urand(2000, 3000)); break; diff --git a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp index 05bf39cb5fb..f21d4fa007c 100644 --- a/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp +++ b/src/server/scripts/Northrend/FrozenHalls/PitOfSaron/boss_krickandick.cpp @@ -197,16 +197,16 @@ class boss_ick : public CreatureScript void _ResetThreat(Unit* target) { - DoModifyThreatPercent(target, -100); - me->AddThreat(target, _tempThreat); + ModifyThreatByPercent(target, -100); + AddThreat(target, _tempThreat); } void UpdateAI(uint32 diff) override { - if (!me->IsInCombat()) + if (!me->IsEngaged()) return; - if (!me->GetVictim() && me->getThreatManager().isThreatListEmpty()) + if (!me->GetVictim() && me->GetThreatManager().IsThreatListEmpty()) { EnterEvadeMode(EVADE_REASON_NO_HOSTILES); return; @@ -638,9 +638,9 @@ class spell_krick_pursuit : public SpellScriptLoader { ick->AI()->Talk(SAY_ICK_CHASE_1, target); ick->AddAura(GetSpellInfo()->Id, target); - ENSURE_AI(boss_ick::boss_ickAI, ick->AI())->SetTempThreat(ick->getThreatManager().getThreat(target)); - ick->AddThreat(target, float(GetEffectValue())); - target->AddThreat(ick, float(GetEffectValue())); + ENSURE_AI(boss_ick::boss_ickAI, ick->AI())->SetTempThreat(ick->GetThreatManager().GetThreat(target)); + ick->GetThreatManager().AddThreat(target, float(GetEffectValue()), GetSpellInfo(), true, true); + target->GetThreatManager().AddThreat(ick, float(GetEffectValue()), GetSpellInfo(), true, true); } } } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp index 5b2248d5341..28be5f8ccc0 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_prince_council.cpp @@ -505,7 +505,7 @@ struct BloodPrincesBossAI : public BossAI { if (!_isEmpowered) { - me->AddThreat(attacker, float(damage)); + AddThreat(attacker, float(damage)); damage = 0; } } @@ -1151,8 +1151,8 @@ class npc_dark_nucleus : public CreatureScript if (attacker == me) return; - me->DeleteThreatList(); - me->AddThreat(attacker, 500000000.0f); + me->GetThreatManager().ClearAllThreat(); + AddThreat(attacker, 500000000.0f); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp index b908e1a9c35..30d57d99a75 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_blood_queen_lana_thel.cpp @@ -484,15 +484,14 @@ class boss_blood_queen_lana_thel : public CreatureScript // offtank for this encounter is the player standing closest to main tank Player* SelectRandomTarget(bool includeOfftank, std::list<Player*>* targetList = nullptr) { - std::list<HostileReference*> const& threatlist = me->getThreatManager().getThreatList(); - std::list<Player*> tempTargets; - - if (threatlist.empty()) + if (me->GetThreatManager().IsThreatListEmpty(true)) return nullptr; - for (std::list<HostileReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - if (Unit* refTarget = (*itr)->getTarget()) - if (refTarget != me->GetVictim() && refTarget->GetTypeId() == TYPEID_PLAYER && (includeOfftank || (refTarget->GetGUID() != _offtankGUID))) + std::list<Player*> tempTargets; + Unit* maintank = me->GetThreatManager().GetCurrentVictim(); + for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList()) + if (Player* refTarget = ref->GetVictim()->ToPlayer()) + if (refTarget != maintank && (includeOfftank || (refTarget->GetGUID() != _offtankGUID))) tempTargets.push_back(refTarget->ToPlayer()); if (tempTargets.empty()) diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp index 172c54fd7e0..f5568b4c298 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_deathbringer_saurfang.cpp @@ -580,7 +580,7 @@ class boss_deathbringer_saurfang : public CreatureScript } case ACTION_MARK_OF_THE_FALLEN_CHAMPION: { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_MARK_OF_THE_FALLEN_CHAMPION)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_MARK_OF_THE_FALLEN_CHAMPION)) { ++_fallenChampionCastCount; DoCast(target, SPELL_MARK_OF_THE_FALLEN_CHAMPION); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp index 5b0ea090802..dbf8aa32697 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_festergut.cpp @@ -211,8 +211,8 @@ class boss_festergut : public CreatureScript { std::list<Unit*> ranged, melee; uint32 minTargets = RAID_MODE<uint32>(3, 8, 3, 8); - SelectTargetList(ranged, 25, SELECT_TARGET_RANDOM, -5.0f, true); - SelectTargetList(melee, 25, SELECT_TARGET_RANDOM, 5.0f, true); + SelectTargetList(ranged, 25, SELECT_TARGET_RANDOM, 0, -5.0f, true); + SelectTargetList(melee, 25, SELECT_TARGET_RANDOM, 0, 5.0f, true); while (ranged.size() < minTargets) { if (melee.empty()) 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 aa0ce037619..41b836922e1 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_icecrown_gunship_battle.cpp @@ -583,7 +583,7 @@ struct gunship_npc_AI : public ScriptedAI if (!me->IsAlive() || !me->IsInCombat()) return; - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->MoveTargetedHome(); } @@ -639,7 +639,7 @@ protected: return me->GetVictim() != nullptr; } - else if (me->getThreatManager().isThreatListEmpty()) + else if (me->GetThreatManager().IsThreatListEmpty()) { EnterEvadeMode(EVADE_REASON_OTHER); return false; @@ -728,7 +728,7 @@ class npc_gunship : public CreatureScript { Creature* stalker = *itr; stalker->RemoveAllAuras(); - stalker->DeleteThreatList(); + stalker->GetThreatManager().ClearAllThreat(); stalker->CombatStop(true); } @@ -887,7 +887,7 @@ class npc_high_overlord_saurfang_igb : public CreatureScript if (!me->IsAlive()) return; - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->MoveTargetedHome(); @@ -1156,7 +1156,7 @@ class npc_muradin_bronzebeard_igb : public CreatureScript if (!me->IsAlive()) return; - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->GetMotionMaster()->MoveTargetedHome(); @@ -1492,7 +1492,7 @@ struct npc_gunship_boarding_addAI : public gunship_npc_AI { players.sort(Trinity::ObjectDistanceOrderPred(me)); for (std::list<Player*>::iterator itr = players.begin(); itr != players.end(); ++itr) - me->AddThreat(*itr, 1.0f); + AddThreat(*itr, 1.0f); AttackStart(players.front()); } diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp index 602c191cfab..8a444b3d933 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lady_deathwhisper.cpp @@ -316,9 +316,10 @@ class boss_lady_deathwhisper : public CreatureScript scheduler.Schedule(Seconds(27), [this](TaskContext dominate_mind) { Talk(SAY_DOMINATE_MIND); - for (uint8 i = 0; i < _dominateMindCount; i++) - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_DOMINATE_MIND)) - DoCast(target, SPELL_DOMINATE_MIND); + std::list<Unit*> targets; + SelectTargetList(targets, _dominateMindCount, SELECT_TARGET_RANDOM, 0, 0.0f, true, false, -SPELL_DOMINATE_MIND); + for (Unit* target : targets) + DoCast(target, SPELL_DOMINATE_MIND); dominate_mind.Repeat(Seconds(40), Seconds(45)); }); // phase one only @@ -414,7 +415,7 @@ class boss_lady_deathwhisper : public CreatureScript Talk(SAY_PHASE_2); Talk(EMOTE_PHASE_2); DoStartMovement(me->GetVictim()); - DoResetThreat(); + ResetThreatList(); damage -= me->GetPower(POWER_MANA); me->SetPower(POWER_MANA, 0); me->RemoveAurasDueToSpell(SPELL_MANA_BARRIER); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp index c13ce2ed638..ca8a9356db6 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_lord_marrowgar.cpp @@ -518,8 +518,8 @@ class spell_marrowgar_coldflame : public SpellScriptLoader void SelectTarget(std::list<WorldObject*>& targets) { targets.clear(); - // select any unit but not the tank (by owners threatlist) - Unit* target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 1, -GetCaster()->GetCombatReach(), true, -SPELL_IMPALED); + // select any unit but not the tank + Unit* target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, -GetCaster()->GetCombatReach(), true, false, -SPELL_IMPALED); if (!target) target = GetCaster()->GetAI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true); // or the tank if its solo if (!target) @@ -645,7 +645,7 @@ class spell_marrowgar_bone_spike_graveyard : public SpellScriptLoader uint8 boneSpikeCount = uint8(GetCaster()->GetMap()->GetSpawnMode() & 1 ? 3 : 1); std::list<Unit*> targets; - marrowgarAI->SelectTargetList(targets, BoneSpikeTargetSelector(marrowgarAI), boneSpikeCount, SELECT_TARGET_RANDOM); + marrowgarAI->SelectTargetList(targets, boneSpikeCount, SELECT_TARGET_RANDOM, 1, BoneSpikeTargetSelector(marrowgarAI)); if (targets.empty()) return; diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp index ca10713b47a..63d3af3931a 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_professor_putricide.cpp @@ -503,10 +503,9 @@ class boss_professor_putricide : public CreatureScript { std::list<Unit*> targetList; { - const std::list<HostileReference*>& threatlist = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr) - if ((*itr)->getTarget()->GetTypeId() == TYPEID_PLAYER) - targetList.push_back((*itr)->getTarget()); + for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList()) + if (Player* target = ref->GetVictim()->ToPlayer()) + targetList.push_back(target); } size_t half = targetList.size()/2; @@ -605,7 +604,7 @@ class boss_professor_putricide : public CreatureScript case EVENT_SLIME_PUDDLE: { std::list<Unit*> targets; - SelectTargetList(targets, 2, SELECT_TARGET_RANDOM, 0.0f, true); + SelectTargetList(targets, 2, SELECT_TARGET_RANDOM, 0, 0.0f, true); if (!targets.empty()) for (std::list<Unit*>::iterator itr = targets.begin(); itr != targets.end(); ++itr) DoCast(*itr, SPELL_SLIME_PUDDLE_TRIGGER); @@ -635,7 +634,7 @@ class boss_professor_putricide : public CreatureScript if (Is25ManRaid()) { std::list<Unit*> targets; - SelectTargetList(targets, 2, SELECT_TARGET_RANDOM, -7.0f, true); + SelectTargetList(targets, 2, SELECT_TARGET_RANDOM, 0, -7.0f, true); if (!targets.empty()) { Talk(EMOTE_MALLEABLE_GOO); @@ -925,9 +924,9 @@ class spell_putricide_ooze_channel : public SpellScriptLoader void StartAttack() { GetCaster()->ClearUnitState(UNIT_STATE_CASTING); - GetCaster()->DeleteThreatList(); + GetCaster()->GetThreatManager().ClearAllThreat(); GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit()); - GetCaster()->AddThreat(GetHitUnit(), 500000000.0f); // value seen in sniff + GetCaster()->GetThreatManager().AddThreat(GetHitUnit(), 500000000.0f, nullptr, true, true); // value seen in sniff } void Register() override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp index 337bdc560b4..e8bea735d40 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_rotface.cpp @@ -258,7 +258,7 @@ class npc_little_ooze : public CreatureScript DoCast(me, SPELL_WEAK_RADIATING_OOZE, true); DoCast(me, SPELL_GREEN_ABOMINATION_HITTIN__YA_PROC, true); events.ScheduleEvent(EVENT_STICKY_OOZE, 5000); - me->AddThreat(summoner, 500000.0f); + AddThreat(summoner, 500000.0f); } void JustDied(Unit* /*killer*/) override diff --git a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp index 36574c9e812..4bf8f97f623 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_sindragosa.cpp @@ -1540,7 +1540,7 @@ class spell_frostwarden_handler_focus_fire : public SpellScriptLoader void HandleScript(SpellEffIndex effIndex) { PreventHitDefaultEffect(effIndex); - GetCaster()->AddThreat(GetHitUnit(), float(GetEffectValue())); + GetCaster()->GetThreatManager().AddThreat(GetHitUnit(), float(GetEffectValue())); GetCaster()->GetAI()->SetData(DATA_WHELP_MARKER, 1); } @@ -1559,7 +1559,7 @@ class spell_frostwarden_handler_focus_fire : public SpellScriptLoader PreventDefaultAction(); if (Unit* caster = GetCaster()) { - caster->AddThreat(GetTarget(), -float(GetSpellInfo()->Effects[EFFECT_1].CalcValue())); + caster->GetThreatManager().AddThreat(GetTarget(), -float(GetSpellInfo()->Effects[EFFECT_1].CalcValue())); caster->GetAI()->SetData(DATA_WHELP_MARKER, 0); } } 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 b219ded2afd..97b3261f51e 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_the_lich_king.cpp @@ -972,7 +972,7 @@ class boss_the_lich_king : public CreatureScript events.ScheduleEvent(EVENT_SOUL_REAPER, urand(33000, 35000), 0, PHASE_TWO_THREE); break; case EVENT_DEFILE: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_HARVEST_SOUL_VALKYR)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_HARVEST_SOUL_VALKYR)) { Talk(EMOTE_DEFILE_WARNING); DoCast(target, SPELL_DEFILE); @@ -1789,7 +1789,7 @@ class npc_terenas_menethil : public CreatureScript if (!me->IsAlive()) return; - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(false); } @@ -2781,7 +2781,7 @@ class spell_the_lich_king_vile_spirit_move_target_search : public SpellScriptLoa return; GetCaster()->ToCreature()->AI()->AttackStart(GetHitUnit()); - GetCaster()->AddThreat(GetHitUnit(), 100000.0f); + GetCaster()->GetThreatManager().AddThreat(GetHitUnit(), 100000.0f); } 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 c558aa47d52..493b759e0f7 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/boss_valithria_dreamwalker.cpp @@ -562,7 +562,7 @@ class npc_green_dragon_combat_trigger : public CreatureScript // @TODO check out of bounds on all encounter creatures, evade if matched - std::list<HostileReference*> const& threatList = me->getThreatManager().getThreatList(); + std::list<HostileReference*> const& threatList = me->GetThreatManager().getThreatList(); if (threatList.empty()) { EnterEvadeMode(); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp index 789370d8762..2ddfa86f5fa 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/icecrown_citadel.cpp @@ -922,7 +922,7 @@ class boss_sister_svalna : public CreatureScript Talk(SAY_SVALNA_AGGRO); break; case EVENT_IMPALING_SPEAR: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_IMPALING_SPEAR)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_IMPALING_SPEAR)) { DoCast(me, SPELL_AETHER_SHIELD); DoCast(target, SPELL_IMPALING_SPEAR); diff --git a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp index 37baf7afe8d..ffc899b4d0d 100644 --- a/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp +++ b/src/server/scripts/Northrend/IcecrownCitadel/instance_icecrown_citadel.cpp @@ -1460,7 +1460,7 @@ class instance_icecrown_citadel : public InstanceMapScript if (Creature* warden = instance->SummonCreature(NPC_SPIRIT_WARDEN, SpiritWardenSpawn, nullptr, 63000)) { terenas->AI()->AttackStart(warden); - warden->AddThreat(terenas, 300000.0f); + warden->GetThreatManager().AddThreat(terenas, 300000.0f, nullptr, true, true); } } break; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp index 597471597dd..0fb00d18fd3 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_four_horsemen.cpp @@ -240,11 +240,7 @@ struct boss_four_horsemen_baseAI : public BossAI continue; if (player->IsAlive()) - { - cBoss->AddThreat(player, 0.0f); - cBoss->SetInCombatWith(player); - player->SetInCombatWith(cBoss); - } + AddThreat(player, 0.0f, cBoss); } } @@ -403,19 +399,19 @@ class boss_four_horsemen_baron : public CreatureScript { SetCombatMovement(true); me->SetReactState(REACT_AGGRESSIVE); - ThreatManager& threat = me->getThreatManager(); - if (threat.isThreatListEmpty()) + ThreatManager& threat = me->GetThreatManager(); + if (threat.IsThreatListEmpty()) { if (Unit* nearest = me->SelectNearestPlayer(5000.0f)) { - me->AddThreat(nearest, 1.0f); + AddThreat(nearest, 1.0f); AttackStart(nearest); } else ResetEncounter(); } else - AttackStart(threat.getHostilTarget()); + AttackStart(threat.GetCurrentVictim()); events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); events.ScheduleEvent(EVENT_MARK, Seconds(24)); @@ -476,19 +472,19 @@ class boss_four_horsemen_thane : public CreatureScript { SetCombatMovement(true); me->SetReactState(REACT_AGGRESSIVE); - ThreatManager& threat = me->getThreatManager(); - if (threat.isThreatListEmpty()) + ThreatManager& threat = me->GetThreatManager(); + if (threat.IsThreatListEmpty()) { if (Unit* nearest = me->SelectNearestPlayer(5000.0f)) { - me->AddThreat(nearest, 1.0f); + AddThreat(nearest, 1.0f); AttackStart(nearest); } else ResetEncounter(); } else - AttackStart(threat.getHostilTarget()); + AttackStart(threat.GetCurrentVictim()); events.ScheduleEvent(EVENT_BERSERK, Minutes(10)); events.ScheduleEvent(EVENT_MARK, Seconds(24)); @@ -567,7 +563,7 @@ class boss_four_horsemen_lady : public CreatureScript return; if (!_ourMovementFinished) return; - if (me->getThreatManager().isThreatListEmpty()) + if (me->GetThreatManager().IsThreatListEmpty()) { EnterEvadeMode(EVADE_REASON_NO_HOSTILES); return; @@ -600,7 +596,7 @@ class boss_four_horsemen_lady : public CreatureScript if (me->HasUnitState(UNIT_STATE_CASTING)) return; - if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 45.0f, true)) + if (Unit* target = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 45.0f, true)) DoCast(target, SPELL_SHADOW_BOLT); else { @@ -637,7 +633,7 @@ class boss_four_horsemen_sir : public CreatureScript return; if (!_ourMovementFinished) return; - if (me->getThreatManager().isThreatListEmpty()) + if (me->GetThreatManager().IsThreatListEmpty()) { EnterEvadeMode(EVADE_REASON_NO_HOSTILES); return; @@ -657,7 +653,7 @@ class boss_four_horsemen_sir : public CreatureScript events.Repeat(Seconds(15)); break; case EVENT_HOLYWRATH: - if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 45.0f, true)) + if (Unit* target = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 45.0f, true)) { DoCast(target, SPELL_HOLY_WRATH, true); _shouldSay = true; @@ -670,7 +666,7 @@ class boss_four_horsemen_sir : public CreatureScript if (me->HasUnitState(UNIT_STATE_CASTING)) return; - if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 45.0f, true)) + if (Unit* target = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 45.0f, true)) DoCast(target, SPELL_HOLY_BOLT); else { diff --git a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp index c09de96f7b6..3a6e67538c2 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_gothik.cpp @@ -398,7 +398,7 @@ class boss_gothik : public CreatureScript switch (action) { case ACTION_MINION_EVADE: - if (_gateIsOpen || me->getThreatManager().isThreatListEmpty()) + if (_gateIsOpen || me->GetThreatManager().IsThreatListEmpty()) return EnterEvadeMode(EVADE_REASON_NO_HOSTILES); if (_gateCanOpen) OpenGate(); @@ -424,8 +424,8 @@ class boss_gothik : public CreatureScript // thus we only do a cursory check to make sure (edge cases?) if (Player* newTarget = FindEligibleTarget(me, _gateIsOpen)) { - me->getThreatManager().resetAllAggro(); - me->AddThreat(newTarget, 1.0f); + ResetThreatList(); + AddThreat(newTarget, 1.0f); AttackStart(newTarget); } else @@ -507,7 +507,7 @@ class boss_gothik : public CreatureScript Talk(SAY_PHASE_TWO); Talk(EMOTE_PHASE_TWO); me->SetReactState(REACT_PASSIVE); - me->getThreatManager().resetAllAggro(); + ResetThreatList(); DoCastAOE(SPELL_TELEPORT_LIVE); break; case EVENT_TELEPORT: @@ -517,7 +517,7 @@ class boss_gothik : public CreatureScript me->AttackStop(); me->StopMoving(); me->SetReactState(REACT_PASSIVE); - me->getThreatManager().resetAllAggro(); + ResetThreatList(); DoCastAOE(_lastTeleportDead ? SPELL_TELEPORT_LIVE : SPELL_TELEPORT_DEAD); _lastTeleportDead = !_lastTeleportDead; @@ -598,7 +598,7 @@ struct npc_gothik_minion_baseAI : public ScriptedAI case ACTION_ACQUIRE_TARGET: if (Player* target = FindEligibleTarget(me, _gateIsOpen)) { - me->AddThreat(target, 1.0f); + AddThreat(target, 1.0f); AttackStart(target); } else @@ -626,8 +626,8 @@ struct npc_gothik_minion_baseAI : public ScriptedAI if (Player* newTarget = FindEligibleTarget(me, _gateIsOpen)) { me->RemoveAurasByType(SPELL_AURA_MOD_TAUNT); - me->getThreatManager().resetAllAggro(); - me->AddThreat(newTarget, 1.0f); + ResetThreatList(); + AddThreat(newTarget, 1.0f); AttackStart(newTarget); } else diff --git a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp index 626a7c023af..863637ca90b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_grobbulus.cpp @@ -92,7 +92,7 @@ class boss_grobbulus : public CreatureScript events.Repeat(randtime(Seconds(15), Seconds(30))); return; case EVENT_INJECT: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, -SPELL_MUTATING_INJECTION)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 0.0f, true, true, -SPELL_MUTATING_INJECTION)) DoCast(target, SPELL_MUTATING_INJECTION); events.Repeat(Seconds(8) + Milliseconds(uint32(std::round(120 * me->GetHealthPct())))); return; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp index 93b91bec9f3..faaafac710a 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_kelthuzad.cpp @@ -189,7 +189,7 @@ class KelThuzadCharmedPlayerAI : public SimpleCharmedPlayerAI { if (Unit* target = charmer->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, CharmedPlayerTargetSelectPred())) return target; - if (Unit* target = charmer->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_CHAINS)) + if (Unit* target = charmer->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_CHAINS)) return target; } return nullptr; @@ -283,10 +283,9 @@ public: { Talk(SAY_CHAINS); std::list<Unit*> targets; - SelectTargetList(targets, 3, SELECT_TARGET_RANDOM, 0.0f, true); + SelectTargetList(targets, 3, SELECT_TARGET_RANDOM, 0, 0.0f, true, false); for (Unit* target : targets) - if (me->GetVictim() != target) // skip MT - DoCast(target, SPELL_CHAINS); + DoCast(target, SPELL_CHAINS); } } @@ -426,7 +425,7 @@ public: me->CastStop(); events.SetPhase(PHASE_TWO); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_IMMUNE_TO_PC); - me->getThreatManager().resetAllAggro(); + ResetThreatList(); me->SetReactState(REACT_AGGRESSIVE); Talk(EMOTE_PHASE_TWO); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp index 1627cba08b9..1a6bbccdb30 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_maexxna.cpp @@ -139,7 +139,7 @@ public: case EVENT_WRAP: { std::list<Unit*> targets; - SelectTargetList(targets, WebTargetSelector(me), RAID_MODE(1, 2), SELECT_TARGET_RANDOM); + SelectTargetList(targets, RAID_MODE(1, 2), SELECT_TARGET_RANDOM, 1, WebTargetSelector(me)); if (!targets.empty()) { Talk(EMOTE_WEB_WRAP); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp index 9394ececc08..b7333e90e2e 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_noth.cpp @@ -128,7 +128,7 @@ public: DoZoneInCombat(); - if (me->getThreatManager().isThreatListEmpty()) + if (!me->IsThreatened()) Reset(); else { @@ -235,7 +235,7 @@ public: case EVENT_BLINK: DoCastAOE(SPELL_CRIPPLE, true); DoCastAOE(SPELL_BLINK); - DoResetThreat(); + ResetThreatList(); justBlinked = true; events.Repeat(Seconds(40)); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp index 92dcdf95da4..c1fdc5b950e 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_patchwerk.cpp @@ -119,41 +119,31 @@ public: { // Hateful Strike targets the highest non-MT threat in melee range on 10man // and the higher HP target out of the two highest non-MT threats in melee range on 25man - float MostThreat = 0.0f; - Unit* secondThreatTarget = nullptr; - Unit* thirdThreatTarget = nullptr; - - std::list<HostileReference*>::const_iterator i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { // find second highest - Unit* target = (*i)->getTarget(); - if (target->IsAlive() && target != me->GetVictim() && (*i)->getThreat() >= MostThreat && me->IsWithinMeleeRange(target)) - { - MostThreat = (*i)->getThreat(); - secondThreatTarget = target; - } - } - - if (secondThreatTarget && Is25ManRaid()) - { // find third highest - MostThreat = 0.0f; - i = me->getThreatManager().getThreatList().begin(); - for (; i != me->getThreatManager().getThreatList().end(); ++i) - { - Unit* target = (*i)->getTarget(); - if (target->IsAlive() && target != me->GetVictim() && target != secondThreatTarget && (*i)->getThreat() >= MostThreat && me->IsWithinMeleeRange(target)) - { - MostThreat = (*i)->getThreat(); - thirdThreatTarget = target; - } - } + ThreatReference* secondThreat = nullptr; + ThreatReference* thirdThreat = nullptr; + + ThreatManager const& mgr = me->GetThreatManager(); + Unit* currentVictim = mgr.GetCurrentVictim(); + auto const& pair = mgr.GetSortedThreatList(); + auto it = pair.begin(), end = pair.end(); + if (it == end) + EnterEvadeMode(EVADE_REASON_NO_HOSTILES); + + if ((*it)->GetVictim() != currentVictim) + secondThreat = *it; + if ((!secondThreat || Is25ManRaid()) && (++it != end)) + { + if ((*it)->GetVictim() != currentVictim) + (secondThreat ? thirdThreat : secondThreat) = *it; + if (!thirdThreat && Is25ManRaid() && (++it != end)) + thirdThreat = *it; } Unit* pHatefulTarget = nullptr; - if (!thirdThreatTarget) - pHatefulTarget = secondThreatTarget; - else if (secondThreatTarget) - pHatefulTarget = (secondThreatTarget->GetHealth() < thirdThreatTarget->GetHealth()) ? thirdThreatTarget : secondThreatTarget; + if (!thirdThreat) + pHatefulTarget = secondThreat->GetVictim(); + else if (secondThreat) + pHatefulTarget = (secondThreat->GetVictim()->GetHealth() < thirdThreat->GetVictim()->GetHealth()) ? thirdThreat->GetVictim() : secondThreat->GetVictim(); if (!pHatefulTarget) pHatefulTarget = me->GetVictim(); @@ -162,11 +152,11 @@ public: // add threat to highest threat targets if (me->GetVictim() && me->IsWithinMeleeRange(me->GetVictim())) - me->getThreatManager().addThreat(me->GetVictim(), HATEFUL_THREAT_AMT); - if (secondThreatTarget) - me->getThreatManager().addThreat(secondThreatTarget, HATEFUL_THREAT_AMT); - if (thirdThreatTarget) - me->getThreatManager().addThreat(thirdThreatTarget, HATEFUL_THREAT_AMT); // this will only ever be used in 25m + AddThreat(me->GetVictim(), HATEFUL_THREAT_AMT); + if (secondThreat) + secondThreat->AddThreat(HATEFUL_THREAT_AMT); + if (thirdThreat) + thirdThreat->AddThreat(HATEFUL_THREAT_AMT); events.Repeat(Seconds(1)); break; diff --git a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp index 4679fb17358..58da5a92295 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_razuvious.cpp @@ -231,7 +231,7 @@ class npc_dk_understudy : public CreatureScript { me->SetReactState(REACT_AGGRESSIVE); if (Unit* charmer = ObjectAccessor::GetUnit(*me, _charmer)) - me->AddThreat(charmer, 100000.0f); + AddThreat(charmer, 100000.0f); DoZoneInCombat(nullptr, 250.0f); } } diff --git a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp index 205a098d077..8e2f093863b 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_sapphiron.cpp @@ -310,7 +310,7 @@ class boss_sapphiron : public CreatureScript _iceboltTargets.clear(); std::list<Unit*> targets; - SelectTargetList(targets, RAID_MODE(2, 3), SELECT_TARGET_RANDOM, 200.0f, true); + SelectTargetList(targets, RAID_MODE(2, 3), SELECT_TARGET_RANDOM, 0, 200.0f, true); for (Unit* target : targets) if (target) _iceboltTargets.push_back(target->GetGUID()); diff --git a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp index a74dd052695..d6a36680c33 100644 --- a/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp +++ b/src/server/scripts/Northrend/Naxxramas/boss_thaddius.cpp @@ -399,7 +399,7 @@ public: me->SetReactState(REACT_AGGRESSIVE); DoZoneInCombat(); - if (Unit* closest = SelectTarget(SELECT_TARGET_NEAREST, 0, 500.0f)) + if (Unit* closest = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 500.0f)) AttackStart(closest); else // if there is no nearest target, then there is no target, meaning we should reset { @@ -564,7 +564,7 @@ public: if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) if (feugen->GetVictim()) { - me->AddThreat(feugen->EnsureVictim(), 0.0f); + AddThreat(feugen->EnsureVictim(), 0.0f); me->SetInCombatWith(feugen->EnsureVictim()); } break; @@ -606,11 +606,8 @@ public: thaddius->AI()->DoAction(ACTION_STALAGG_AGGRO); if (Creature* feugen = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FEUGEN))) - if (!feugen->IsInCombat()) - { - feugen->AddThreat(who, 0.0f); - feugen->SetInCombatWith(who); - } + if (!feugen->IsEngaged()) + AddThreat(who, 0.0f, feugen); } void DamageTaken(Unit* /*who*/, uint32& damage) override @@ -833,7 +830,7 @@ public: if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) if (stalagg->GetVictim()) { - me->AddThreat(stalagg->EnsureVictim(), 0.0f); + AddThreat(stalagg->EnsureVictim(), 0.0f); me->SetInCombatWith(stalagg->EnsureVictim()); } staticFieldTimer = 6 * IN_MILLISECONDS; @@ -877,10 +874,7 @@ public: if (Creature* stalagg = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_STALAGG))) if (!stalagg->IsInCombat()) - { - stalagg->AddThreat(who, 0.0f); - stalagg->SetInCombatWith(who); - } + AddThreat(who, 0.0f, stalagg); } void DamageTaken(Unit* /*who*/, uint32& damage) override @@ -1213,39 +1207,39 @@ class spell_thaddius_magnetic_pull : public SpellScriptLoader if (!stalagg) return; - Unit* feugenTank = feugen->GetVictim(); - Unit* stalaggTank = stalagg->GetVictim(); + ThreatManager& feugenThreat = feugen->GetThreatManager(); + ThreatManager& stalaggThreat = stalagg->GetThreatManager(); + + Unit* feugenTank = feugenThreat.GetCurrentVictim(); + Unit* stalaggTank = stalaggThreat.GetCurrentVictim(); if (!feugenTank || !stalaggTank) return; - ThreatManager& feugenThreat = feugen->getThreatManager(); - ThreatManager& stalaggThreat = stalagg->getThreatManager(); - if (feugenTank == stalaggTank) // special behavior if the tanks are the same (taken from retail) { - float feugenTankThreat = feugenThreat.getThreat(feugenTank); - float stalaggTankThreat = stalaggThreat.getThreat(stalaggTank); + float feugenTankThreat = feugenThreat.GetThreat(feugenTank); + float stalaggTankThreat = stalaggThreat.GetThreat(stalaggTank); - feugenThreat.addThreat(feugenTank, stalaggTankThreat - feugenTankThreat); - stalaggThreat.addThreat(stalaggTank, feugenTankThreat - stalaggTankThreat); + feugen->GetThreatManager().AddThreat(feugenTank, stalaggTankThreat - feugenTankThreat, nullptr, true, true); + stalagg->GetThreatManager().AddThreat(stalaggTank, feugenTankThreat - stalaggTankThreat, nullptr, true, true); feugen->CastSpell(stalaggTank, SPELL_MAGNETIC_PULL_EFFECT, true); } else // normal case, two tanks { - float feugenTankThreat = feugenThreat.getThreat(feugenTank); - float feugenOtherThreat = feugenThreat.getThreat(stalaggTank); - float stalaggTankThreat = stalaggThreat.getThreat(stalaggTank); - float stalaggOtherThreat = stalaggThreat.getThreat(feugenTank); + float feugenTankThreat = feugenThreat.GetThreat(feugenTank); + float feugenOtherThreat = feugenThreat.GetThreat(stalaggTank); + float stalaggTankThreat = stalaggThreat.GetThreat(stalaggTank); + float stalaggOtherThreat = stalaggThreat.GetThreat(feugenTank); // set the two entries in feugen's threat table to be equal to the ones in stalagg's - feugenThreat.addThreat(stalaggTank, stalaggTankThreat - feugenOtherThreat); - feugenThreat.addThreat(feugenTank, stalaggOtherThreat - feugenTankThreat); + stalagg->GetThreatManager().AddThreat(stalaggTank, stalaggTankThreat - feugenOtherThreat, nullptr, true, true); + stalagg->GetThreatManager().AddThreat(feugenTank, stalaggOtherThreat - feugenTankThreat, nullptr, true, true); // set the two entries in stalagg's threat table to be equal to the ones in feugen's - stalaggThreat.addThreat(feugenTank, feugenTankThreat - stalaggOtherThreat); - stalaggThreat.addThreat(stalaggTank, feugenOtherThreat - stalaggTankThreat); + stalagg->GetThreatManager().AddThreat(feugenTank, feugenTankThreat - stalaggOtherThreat, nullptr, true, true); + stalagg->GetThreatManager().AddThreat(stalaggTank, feugenOtherThreat - stalaggTankThreat, nullptr, true, true); // pull the two tanks across feugenTank->CastSpell(stalaggTank, SPELL_MAGNETIC_PULL_EFFECT, true); diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp index dcf26afa14b..b6dd3924c06 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/boss_malygos.cpp @@ -955,7 +955,7 @@ public: case EVENT_SURGE_OF_POWER_P_THREE: if (GetDifficulty() == RAID_DIFFICULTY_10MAN_NORMAL) { - if (Unit* tempSurgeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, SPELL_RIDE_RED_DRAGON_BUDDY)) + if (Unit* tempSurgeTarget = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, false, true, SPELL_RIDE_RED_DRAGON_BUDDY)) { if (Vehicle* drakeVehicle = tempSurgeTarget->GetVehicleKit()) { @@ -979,7 +979,7 @@ public: events.ScheduleEvent(EVENT_SURGE_OF_POWER_P_THREE, urand(9, 18)*IN_MILLISECONDS, 0, PHASE_THREE); break; case EVENT_STATIC_FIELD: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, false, SPELL_RIDE_RED_DRAGON_BUDDY)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 60.0f, false, true, SPELL_RIDE_RED_DRAGON_BUDDY)) DoCast(target, SPELL_STATIC_FIELD_MISSLE, true); events.ScheduleEvent(EVENT_STATIC_FIELD, urand(15, 30)*IN_MILLISECONDS, 0, PHASE_THREE); @@ -1827,13 +1827,11 @@ class spell_malygos_vortex_visual : public SpellScriptLoader { if (Creature* caster = GetCaster()->ToCreature()) { - ThreatContainer::StorageType const& m_threatlist = caster->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator itr = m_threatlist.begin(); itr!= m_threatlist.end(); ++itr) + for (ThreatReference* ref : caster->GetThreatManager().GetUnsortedThreatList()) { - if (Unit* target = (*itr)->getTarget()) + if (Player* targetPlayer = ref->GetVictim()->ToPlayer()) { - Player* targetPlayer = target->ToPlayer(); - if (!targetPlayer || targetPlayer->IsGameMaster()) + if (targetPlayer->IsGameMaster()) continue; if (InstanceScript* instance = caster->GetInstanceScript()) diff --git a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp index ef10057f180..f1ab2dfb0cb 100644 --- a/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp +++ b/src/server/scripts/Northrend/Nexus/EyeOfEternity/instance_eye_of_eternity.cpp @@ -181,26 +181,20 @@ public: { if (Creature* malygos = instance->GetCreature(malygosGUID)) { - ThreatContainer::StorageType const& threatList = malygos->getThreatManager().getThreatList(); for (GuidList::const_iterator itr_vortex = vortexTriggers.begin(); itr_vortex != vortexTriggers.end(); ++itr_vortex) { - if (threatList.empty()) - return; - uint8 counter = 0; if (Creature* trigger = instance->GetCreature(*itr_vortex)) { // each trigger have to cast the spell to 5 players. - for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) + for (auto* ref : malygos->GetThreatManager().GetUnsortedThreatList()) { if (counter >= 5) break; - if (Unit* target = (*itr)->getTarget()) + if (Player* player = ref->GetVictim()->ToPlayer()) { - Player* player = target->ToPlayer(); - - if (!player || player->IsGameMaster() || player->HasAura(SPELL_VORTEX_4)) + if (player->IsGameMaster() || player->HasAura(SPELL_VORTEX_4)) continue; player->CastSpell(trigger, SPELL_VORTEX_4, true); diff --git a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp index 459b9cb188d..a7c8a2536db 100644 --- a/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp +++ b/src/server/scripts/Northrend/Nexus/Oculus/boss_urom.cpp @@ -290,7 +290,7 @@ class boss_urom : public CreatureScript { me->RemoveAllAuras(); me->CombatStop(false); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); } void SpellHit(Unit* /*caster*/, SpellInfo const* spellInfo) override diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp index 604fdeb6123..e22448a54ef 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfLightning/boss_volkhan.cpp @@ -135,7 +135,7 @@ public: { if (me->Attack(who, true)) { - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); me->SetInCombatWith(who); who->SetInCombatWith(me); @@ -328,7 +328,7 @@ public: // 4 - Wait for delay to expire if (m_uiDelay_Timer <= diff) { - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0)) { me->SetReactState(REACT_AGGRESSIVE); me->SetInCombatWith(target); @@ -410,7 +410,7 @@ public: { if (me->Attack(who, true)) { - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); me->SetInCombatWith(who); who->SetInCombatWith(me); diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp index 6463c0c1aef..5c3b98f3984 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/boss_maiden_of_grief.cpp @@ -115,7 +115,7 @@ class boss_maiden_of_grief : public CreatureScript events.ScheduleEvent(EVENT_STORM_OF_GRIEF, urand(15000, 20000)); break; case EVENT_SHOCK_OF_SORROW: - DoResetThreat(); + ResetThreatList(); Talk(SAY_STUN); DoCastAOE(SPELL_SHOCK_OF_SORROW); events.ScheduleEvent(EVENT_SHOCK_OF_SORROW, urand(20000, 30000)); diff --git a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp index 2e926b17710..fc54e6fec54 100644 --- a/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp +++ b/src/server/scripts/Northrend/Ulduar/HallsOfStone/halls_of_stone.cpp @@ -384,7 +384,7 @@ public: void JustSummoned(Creature* summoned) override { lDwarfGUIDList.push_back(summoned->GetGUID()); - summoned->AddThreat(me, 0.0f); + AddThreat(me, 0.0f, summoned); summoned->AI()->AttackStart(me); } 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 aacf9332a75..72a911d398e 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 @@ -593,8 +593,8 @@ class boss_algalon_the_observer : public CreatureScript //! Workaround for Creature::_IsTargetAcceptable returning false //! for creatures that start combat in REACT_PASSIVE and UNIT_FLAG_NOT_SELECTABLE //! causing them to immediately evade - if (!me->getThreatManager().isThreatListEmpty()) - AttackStart(me->getThreatManager().getHostilTarget()); + if (!me->GetThreatManager().IsThreatListEmpty()) + AttackStart(me->GetThreatManager().SelectVictim()); for (uint32 i = 0; i < LIVING_CONSTELLATION_COUNT; ++i) if (Creature* summon = DoSummon(NPC_LIVING_CONSTELLATION, ConstellationPos[i], 0, TEMPSUMMON_DEAD_DESPAWN)) summon->SetReactState(REACT_PASSIVE); diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp index 0a22fafb95e..4e69e9c2bc6 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_assembly_of_iron.cpp @@ -630,7 +630,7 @@ class boss_stormcaller_brundir : public CreatureScript me->RemoveAurasDueToSpell(SPELL_LIGHTNING_TENDRILS_VISUAL); DoStartMovement(me->GetVictim()); events.CancelEvent(EVENT_GROUND); - me->getThreatManager().resetAllAggro(); + ResetThreatList(); break; case EVENT_MOVE_POSITION: if (me->IsWithinMeleeRange(me->GetVictim())) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp index b9983785a18..aa6e8e955b4 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_auriaya.cpp @@ -152,7 +152,7 @@ class boss_auriaya : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { summoned->AI()->AttackStart(target); - summoned->AddThreat(target, 250.0f); + AddThreat(target, 250.0f, summoned); DoZoneInCombat(summoned); } @@ -374,7 +374,7 @@ class npc_sanctum_sentry : public CreatureScript case EVENT_POUNCE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { - me->AddThreat(target, 100.0f); + AddThreat(target, 100.0f); AttackStart(target); DoCast(target, SPELL_SAVAGE_POUNCE); } @@ -443,7 +443,7 @@ class npc_feral_defender : public CreatureScript case EVENT_FERAL_POUNCE: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { - me->AddThreat(target, 100.0f); + AddThreat(target, 100.0f); AttackStart(target); DoCast(target, SPELL_FERAL_POUNCE); } @@ -452,7 +452,7 @@ class npc_feral_defender : public CreatureScript case EVENT_RUSH: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true)) { - me->AddThreat(target, 100.0f); + AddThreat(target, 100.0f); AttackStart(target); DoCast(target, SPELL_FERAL_RUSH); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp index b8846cace28..b436f196b40 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_freya.cpp @@ -351,8 +351,7 @@ class boss_freya : public CreatureScript Elder[n]->CastSpell(me, SPELL_IRONBRANCH_ESSENCE, true); Elder[n]->RemoveLootMode(LOOT_MODE_DEFAULT); //! Why? Elder[n]->AI()->AttackStart(who); - Elder[n]->AddThreat(who, 250.0f); - Elder[n]->SetInCombatWith(who); + AddThreat(who, 250.0f, Elder[n]); ++elderCount; } } @@ -447,7 +446,7 @@ class boss_freya : public CreatureScript break; case EVENT_STRENGTHENED_IRON_ROOTS: Talk(EMOTE_IRON_ROOTS); - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, -SPELL_ROOTS_FREYA)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_ROOTS_FREYA)) target->CastSpell(target, SPELL_ROOTS_FREYA, true); // This must be cast by Target self events.ScheduleEvent(EVENT_STRENGTHENED_IRON_ROOTS, urand(12000, 20000)); break; @@ -632,7 +631,7 @@ class boss_freya : public CreatureScript Elder->RemoveAllAuras(); Elder->AttackStop(); Elder->CombatStop(true); - Elder->DeleteThreatList(); + Elder->GetThreatManager().ClearAllThreat(); Elder->AI()->DoAction(ACTION_ELDER_FREYA_KILLED); } } @@ -662,7 +661,7 @@ class boss_freya : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 250.0f, true)) { summoned->AI()->AttackStart(target); - summoned->AddThreat(target, 250.0f); + AddThreat(target, 250.0f, summoned); DoZoneInCombat(summoned); } } @@ -959,7 +958,7 @@ class boss_elder_ironbranch : public CreatureScript events.ScheduleEvent(EVENT_IMPALE, urand(15000, 25000)); break; case EVENT_IRON_ROOTS: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, -SPELL_ROOTS_IRONBRANCH)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_ROOTS_IRONBRANCH)) target->CastSpell(target, SPELL_ROOTS_IRONBRANCH, true); events.ScheduleEvent(EVENT_IRON_ROOTS, urand(10000, 20000)); break; @@ -1036,7 +1035,7 @@ class npc_detonating_lasher : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true)) { // Switching to other target - modify aggro of new target by 20% from current target's aggro - me->AddThreat(target, me->getThreatManager().getThreat(me->GetVictim(), false) * 1.2f); + AddThreat(target, me->GetThreatManager().GetThreat(me->GetVictim()) * 1.2f); AttackStart(target); } changeTargetTimer = urand(5000, 10000); @@ -1303,7 +1302,7 @@ class npc_ancient_conservator : public CreatureScript if (natureFuryTimer <= diff) { - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, -SPELL_NATURE_FURY)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_NATURE_FURY)) DoCast(target, SPELL_NATURE_FURY); me->AddAura(SPELL_CONSERVATOR_GRIP, me); natureFuryTimer = 5000; diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp index a7a90595ffe..5e24c699f78 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_hodir.cpp @@ -233,7 +233,7 @@ class npc_flash_freeze : public CreatureScript { targetGUID = summoner->GetGUID(); me->SetInCombatWith(summoner); - me->AddThreat(summoner, 250.0f); + AddThreat(summoner, 250.0f); if (Unit* target = ObjectAccessor::GetUnit(*me, targetGUID)) { DoCast(target, SPELL_BLOCK_OF_ICE, true); @@ -277,8 +277,8 @@ class npc_ice_block : public CreatureScript summoner->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_STUNNED | UNIT_FLAG_PACIFIED); summoner->SetControlled(true, UNIT_STATE_ROOT); me->SetInCombatWith(summoner); - me->AddThreat(summoner, 250.0f); - summoner->AddThreat(me, 250.0f); + AddThreat(summoner, 250.0f); + AddThreat(me, 250.0f, summoner); if (Creature* target = ObjectAccessor::GetCreature(*me, targetGUID)) { DoCast(target, SPELL_FLASH_FREEZE_HELPER, true); @@ -487,7 +487,7 @@ class boss_hodir : public CreatureScript if (gettingColdInHereTimer <= diff && gettingColdInHere) { - std::list<HostileReference*> ThreatList = me->getThreatManager().getThreatList(); + std::list<HostileReference*> ThreatList = me->GetThreatManager().getThreatList(); for (std::list<HostileReference*>::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) if (Aura* BitingColdAura = target->GetAura(SPELL_BITING_COLD_TRIGGERED)) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp index 57ace8ec195..b17a5343f71 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_kologarn.cpp @@ -303,7 +303,7 @@ class boss_kologarn : public CreatureScript break; } case EVENT_FOCUSED_EYEBEAM: - if (Unit* eyebeamTargetUnit = SelectTarget(SELECT_TARGET_FARTHEST, 0, 0, true)) + if (Unit* eyebeamTargetUnit = SelectTarget(SELECT_TARGET_MAXDISTANCE, 0, 0, true)) { eyebeamTarget = eyebeamTargetUnit->GetGUID(); DoCast(me, SPELL_SUMMON_FOCUSED_EYEBEAM, true); @@ -367,7 +367,7 @@ class StoneGripTargetSelector : public std::unary_function<Unit*, bool> bool operator()(WorldObject* target) { - if (target == _victim && _me->getThreatManager().getThreatList().size() > 1) + if (target == _victim && _me->GetThreatManager().GetThreatListSize() > 1) return true; if (target->GetTypeId() != TYPEID_PLAYER) @@ -399,7 +399,7 @@ class spell_ulduar_stone_grip_cast_target : public SpellScriptLoader void FilterTargetsInitial(std::list<WorldObject*>& unitList) { // Remove "main tank" and non-player targets - unitList.remove_if(StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetVictim())); + unitList.remove_if(StoneGripTargetSelector(GetCaster()->ToCreature(), GetCaster()->GetThreatManager().GetCurrentVictim())); // Maximum affected targets per difficulty mode uint32 maxTargets = 1; if (GetSpellInfo()->Id == 63981) diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp index 9ed4f098ed6..4859e376779 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_mimiron.cpp @@ -1291,9 +1291,9 @@ class npc_mimiron_assault_bot : public CreatureScript if (me->HasUnitState(UNIT_STATE_ROOT)) { - if (Unit* newTarget = SelectTarget(SELECT_TARGET_NEAREST, 0, 30.0f, true)) + if (Unit* newTarget = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 30.0f, true)) { - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); AttackStart(newTarget); } } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp index cfa977166ad..118c293755a 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_thorim.cpp @@ -607,7 +607,7 @@ class boss_thorim : public CreatureScript if (type != EFFECT_MOTION_TYPE || id != EVENT_JUMP) return; - me->getThreatManager().resetAllAggro(); + ResetThreatList(); SetBoundary(&ArenaBoundaries); } diff --git a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp index 66970ee996f..7f3a2120e88 100644 --- a/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp +++ b/src/server/scripts/Northrend/Ulduar/Ulduar/boss_yogg_saron.cpp @@ -3026,7 +3026,7 @@ class spell_yogg_saron_hate_to_zero : public SpellScriptLoader // 63984 { if (Unit* target = GetHitUnit()) if (target->CanHaveThreatList()) - target->getThreatManager().modifyThreatPercent(GetCaster(), -100); + target->GetThreatManager().ModifyThreatByPercent(GetCaster(), -100); } void Register() override diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp index 6300fa0e9c1..3d2fa75ecac 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_ingvar_the_plunderer.cpp @@ -228,7 +228,7 @@ class boss_ingvar_the_plunderer : public CreatureScript case EVENT_JUST_TRANSFORMED: ScheduleSecondPhase(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NOT_SELECTABLE); - if (Unit* target = me->getThreatManager().getHostilTarget()) + if (Unit* target = me->GetThreatManager().SelectVictim()) AttackStart(target); else { diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp index b10a6a97e04..bb4b78e55f5 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardeKeep/boss_keleseth.cpp @@ -202,7 +202,7 @@ class boss_keleseth : public CreatureScript events.ScheduleEvent(EVENT_SHADOWBOLT, urand(2, 3) * IN_MILLISECONDS); break; case EVENT_FROST_TOMB: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, -SPELL_FROST_TOMB)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_FROST_TOMB)) { Talk(SAY_FROST_TOMB); Talk(SAY_FROST_TOMB_EMOTE, target); @@ -294,7 +294,7 @@ class npc_vrykul_skeleton : public CreatureScript switch (eventId) { case EVENT_DECREPIFY: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, -SPELL_DECREPIFY)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0, 0.0f, true, true, -SPELL_DECREPIFY)) DoCast(target, SPELL_DECREPIFY); events.ScheduleEvent(EVENT_DECREPIFY, urand(1, 5)*IN_MILLISECONDS); break; diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp index 4ba41149c45..effd1741bf1 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_skadi.cpp @@ -603,7 +603,7 @@ public: _scheduler .Schedule(Seconds(13), [this](TaskContext net) { - if (Unit* target = SelectTarget(SELECT_TARGET_FARTHEST, 0, 30, true)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXDISTANCE, 0, 30, true)) DoCast(target, SPELL_NET); net.Repeat(); }) diff --git a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp index 83b25986222..d4cd2a1637f 100644 --- a/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp +++ b/src/server/scripts/Northrend/UtgardeKeep/UtgardePinnacle/boss_ymiron.cpp @@ -193,7 +193,7 @@ public: case NPC_AVENGING_SPIRIT: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { - summon->AddThreat(target, 0.0f); + AddThreat(target, 0.0f, summon); summon->AI()->AttackStart(target); } break; diff --git a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp index 7f8d987ef31..e06087a738b 100644 --- a/src/server/scripts/Northrend/VioletHold/violet_hold.cpp +++ b/src/server/scripts/Northrend/VioletHold/violet_hold.cpp @@ -1122,7 +1122,7 @@ class npc_azure_stalker : public CreatureScript task.Schedule(Milliseconds(1300), [this](TaskContext /*task*/) { - if (Unit* target = SelectTarget(SELECT_TARGET_NEAREST, 0, 5.0f)) + if (Unit* target = SelectTarget(SELECT_TARGET_MINDISTANCE, 0, 5.0f)) DoCast(target, SPELL_BACKSTAB); }); diff --git a/src/server/scripts/Northrend/zone_borean_tundra.cpp b/src/server/scripts/Northrend/zone_borean_tundra.cpp index 2e62c09bc17..50818339887 100644 --- a/src/server/scripts/Northrend/zone_borean_tundra.cpp +++ b/src/server/scripts/Northrend/zone_borean_tundra.cpp @@ -721,7 +721,7 @@ public: Creature* owner = GetOwner()->ToCreature(); owner->RemoveAllAurasExceptType(SPELL_AURA_DUMMY); owner->CombatStop(true); - owner->DeleteThreatList(); + owner->GetThreatManager().ClearAllThreat(); owner->GetMotionMaster()->Clear(false); owner->GetMotionMaster()->MoveFollow(GetCaster(), 4.0f, 0.0f); owner->CastSpell(owner, SPELL_SUBDUED, true); diff --git a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp index c97fa51a502..a6340227270 100644 --- a/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp +++ b/src/server/scripts/Outland/Auchindoun/SethekkHalls/boss_talon_king_ikiss.cpp @@ -101,7 +101,7 @@ public: if (IsHeroic()) DoCast(SelectTarget(SELECT_TARGET_RANDOM, 0), SPELL_POLYMORPH); else - DoCast(SelectTarget(SELECT_TARGET_TOPAGGRO, 1), SPELL_POLYMORPH); + DoCast(SelectTarget(SELECT_TARGET_MAXTHREAT, 1), SPELL_POLYMORPH); events.ScheduleEvent(EVENT_POLYMORPH, urand(15000, 17500)); break; case EVENT_ARCANE_VOLLEY: 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 f0a47bd8604..5a2278ab48b 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 @@ -110,15 +110,13 @@ class boss_blackheart_the_inciter : public CreatureScript { DoCast(me, SPELL_INCITE_CHAOS); - std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + for (ThreatReference* ref : me->GetThreatManager().GetUnsortedThreatList()) { - if (Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) - if (target->GetTypeId() == TYPEID_PLAYER) - me->CastSpell(target, SPELL_INCITE_CHAOS_B, true); + if (Player* target = ref->GetVictim()->ToPlayer()) + me->CastSpell(target, SPELL_INCITE_CHAOS_B, true); } - DoResetThreat(); + ResetThreatList(); events.ScheduleEvent(EVENT_INCITE_CHAOS, 40000); break; } diff --git a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp index 896deca41f7..edaab7cd9cb 100644 --- a/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp +++ b/src/server/scripts/Outland/Auchindoun/ShadowLabyrinth/boss_murmur.cpp @@ -156,16 +156,7 @@ class boss_murmur : public CreatureScript return; if (!me->IsWithinMeleeRange(me->GetVictim())) - { - ThreatContainer::StorageType threatlist = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i != threatlist.end(); ++i) - if (Unit* target = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid())) - if (me->IsWithinMeleeRange(target)) - { - me->TauntApply(target); - break; - } - } + me->GetThreatManager().ResetThreat(me->GetVictim()); DoMeleeAttackIfReady(); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp index 085ea796f05..037eaa82d99 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_gurtogg_bloodboil.cpp @@ -218,7 +218,7 @@ public: if (Unit* oldTarget = me->GetVictim()) { _oldTargetGUID = oldTarget->GetGUID(); - _oldThreat = DoGetThreat(oldTarget); + _oldThreat = GetThreat(oldTarget); } _targetGUID = target->GetGUID(); DoCastSelf(SPELL_FEL_RAGE_SELF, true); @@ -294,9 +294,9 @@ public: if (Unit* oldTarget = ObjectAccessor::GetUnit(*me, _oldTargetGUID)) if (Unit* currentTarget = ObjectAccessor::GetUnit(*me, _targetGUID)) { - DoModifyThreatPercent(currentTarget, -100); + ModifyThreatByPercent(currentTarget, -100); AttackStart(oldTarget); - me->AddThreat(oldTarget, _oldThreat); + AddThreat(oldTarget, _oldThreat); Initialize(); } } diff --git a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp index a7bfbf317c3..1b450a352be 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_illidan.cpp @@ -539,10 +539,7 @@ public: BossAI::JustSummoned(summon); if (summon->GetEntry() == NPC_ILLIDARI_ELITE) if (Creature* akama = instance->GetCreature(DATA_AKAMA)) - { - summon->CombatStart(akama); - summon->AddThreat(akama, 1000.0f); - } + AddThreat(akama, 1000.0f, summon); } void SummonedCreatureDies(Creature* summon, Unit* /*killer*/) override @@ -939,7 +936,7 @@ public: events.ScheduleEvent(EVENT_SCHEDULE_DEMON_SPELLS, Seconds(15)); break; case EVENT_SCHEDULE_DEMON_SPELLS: - DoResetThreat(); + ResetThreatList(); ScheduleEvents(GROUP_PHASE_DEMON, GROUP_PHASE_DEMON); break; case EVENT_DEMON_TEXT: @@ -948,7 +945,7 @@ public: case EVENT_RESUME_COMBAT_DEMON: { uint8 group = _phase == PHASE_3 ? GROUP_PHASE_3 : GROUP_PHASE_4; - DoResetThreat(); + ResetThreatList(); ScheduleEvents(group, group); me->LoadEquipment(1, true); break; diff --git a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp index e2ec4990ccd..c84a3504f61 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_supremus.cpp @@ -116,7 +116,7 @@ public: me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_ATTACK_ME, true); DoCast(SPELL_SNARE_SELF); } - DoResetThreat(); + ResetThreatList(); DoZoneInCombat(); events.ScheduleEvent(EVENT_SWITCH_PHASE, Seconds(60)); } @@ -126,11 +126,10 @@ public: uint32 health = 0; Unit* target = nullptr; - ThreatContainer::StorageType threatList = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr) + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) { - Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (unit && me->IsWithinMeleeRange(unit)) + Unit* unit = ref->GetVictim(); + if (me->IsWithinMeleeRange(unit)) { if (unit->GetHealth() > health) { @@ -162,8 +161,8 @@ public: case EVENT_SWITCH_TARGET: if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true)) { - DoResetThreat(); - me->AddThreat(target, 1000000.0f); + ResetThreatList(); + AddThreat(target, 1000000.0f); DoCast(target, SPELL_CHARGE); Talk(EMOTE_NEW_TARGET); } diff --git a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp index 4061eed85ec..67ed253f247 100644 --- a/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp +++ b/src/server/scripts/Outland/BlackTemple/boss_teron_gorefiend.cpp @@ -193,7 +193,7 @@ public: events.Repeat(Seconds(30), Seconds(40)); break; case EVENT_SHADOW_DEATH: - if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, -SPELL_SPIRITUAL_VENGEANCE)) + if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, 100.0f, true, true, -SPELL_SPIRITUAL_VENGEANCE)) DoCast(target, SPELL_SHADOW_OF_DEATH); events.Repeat(Seconds(30), Seconds(35)); break; @@ -337,16 +337,16 @@ public: { if (Creature* teron = _instance->GetCreature(DATA_TERON_GOREFIEND)) { - Unit* target = teron->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, -SPELL_SPIRITUAL_VENGEANCE); + Unit* target = teron->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0, 100.0f, true, true, -SPELL_SPIRITUAL_VENGEANCE); // He should target Vengeful Spirits only if has no other player available if (!target) target = teron->AI()->SelectTarget(SELECT_TARGET_RANDOM, 0); if (target) { - DoResetThreat(); + ResetThreatList(); AttackStart(target); - me->AddThreat(target, 1000000.0f); + AddThreat(target, 1000000.0f); targetGUID = target->GetGUID(); } } diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp index c9727c196ef..5d9ed583fd6 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_hydross_the_unstable.cpp @@ -292,7 +292,7 @@ public: MarkOfHydross_Count = 0; Talk(SAY_SWITCH_TO_CLEAN); - DoResetThreat(); + ResetThreatList(); SummonBeams(); // spawn 4 adds @@ -376,7 +376,7 @@ public: CorruptedForm = true; Talk(SAY_SWITCH_TO_CORRUPT); - DoResetThreat(); + ResetThreatList(); DeSummonBeams(); // spawn 4 adds diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp index e8259aa34dd..c82dd2e4646 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lady_vashj.cpp @@ -355,7 +355,6 @@ public: // Shock Burst // Randomly used in Phases 1 and 3 on Vashj's target, it's a Shock spell doing 8325-9675 nature damage and stunning the target for 5 seconds, during which she will not attack her target but switch to the next person on the aggro list. DoCastVictim(SPELL_SHOCK_BLAST); - me->TauntApply(me->GetVictim()); ShockBlastTimer = 1000 + rand32() % 14000; // random cooldown } else ShockBlastTimer -= diff; @@ -439,11 +438,10 @@ public: if (CheckTimer <= diff) { bool inMeleeRange = false; - std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); - for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) { - Unit* target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (target && target->IsWithinDistInMap(me, 5)) // if in melee range + Unit* target = ref->GetVictim(); + if (target->IsWithinMeleeRange(me)) // if in melee range { inMeleeRange = true; break; @@ -691,7 +689,7 @@ public: void EnterCombat(Unit* who) override { - me->AddThreat(who, 0.1f); + AddThreat(who, 0.1f); } void UpdateAI(uint32 diff) override diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp index ced4aeb9fd3..36963a137c2 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_leotheras_the_blind.cpp @@ -132,7 +132,7 @@ public: if (done_by->GetGUID() != victimGUID && done_by->GetGUID() != me->GetGUID()) { damage = 0; - DoModifyThreatPercent(done_by, -100); + ModifyThreatByPercent(done_by, -100); } } @@ -150,11 +150,11 @@ public: if (me->EnsureVictim()->GetGUID() != victimGUID) { - DoModifyThreatPercent(me->GetVictim(), -100); + ModifyThreatByPercent(me->GetVictim(), -100); Unit* owner = ObjectAccessor::GetUnit(*me, victimGUID); if (owner && owner->IsAlive()) { - me->AddThreat(owner, 999999); + AddThreat(owner, 999999); AttackStart(owner); } else if (owner && owner->isDead()) { @@ -335,7 +335,7 @@ public: Unit* victim = nullptr; victim = ObjectAccessor::GetUnit(*me, instance->GetGuidData(DATA_LEOTHERAS_EVENT_STARTER)); if (victim) - me->getThreatManager().addThreat(victim, 1); + AddThreat(victim, 1); StartEvent(); } } @@ -387,7 +387,7 @@ public: if (unit_target && unit_target->IsAlive()) { unit->CastSpell(unit_target, SPELL_CONSUMING_MADNESS, true); - DoModifyThreatPercent(unit_target, -100); + ModifyThreatByPercent(unit_target, -100); } } } @@ -442,7 +442,7 @@ public: Unit* newTarget = SelectTarget(SELECT_TARGET_RANDOM, 0); if (newTarget) { - DoResetThreat(); + ResetThreatList(); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MovePoint(0, newTarget->GetPositionX(), newTarget->GetPositionY(), newTarget->GetPositionZ()); } @@ -460,7 +460,7 @@ public: Whirlwind_Timer = 15000; NeedThreatReset = false; - DoResetThreat(); + ResetThreatList(); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveChase(me->GetVictim()); } @@ -526,16 +526,17 @@ public: //Summon Inner Demon if (InnerDemons_Timer <= diff) { - ThreatContainer::StorageType const & ThreatList = me->getThreatManager().getThreatList(); - std::vector<Unit*> TargetList; - for (ThreatContainer::StorageType::const_iterator itr = ThreatList.begin(); itr != ThreatList.end(); ++itr) + ThreatManager const& mgr = me->GetThreatManager(); + std::list<Unit*> TargetList; + Unit* currentVictim = mgr.GetCurrentVictim(); + for (ThreatReference* ref : mgr.GetSortedThreatList()) { - Unit* tempTarget = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (tempTarget && tempTarget->GetTypeId() == TYPEID_PLAYER && tempTarget->GetGUID() != me->EnsureVictim()->GetGUID() && TargetList.size()<5) - TargetList.push_back(tempTarget); + if (Player* tempTarget = ref->GetVictim()->ToPlayer()) + if (tempTarget != currentVictim && TargetList.size()<5) + TargetList.push_back(tempTarget); } //SpellInfo* spell = GET_SPELL(SPELL_INSIDIOUS_WHISPER); - for (std::vector<Unit*>::const_iterator itr = TargetList.begin(); itr != TargetList.end(); ++itr) + for (auto itr = TargetList.begin(), end = TargetList.end(); itr != end; ++itr) { if ((*itr) && (*itr)->IsAlive()) { diff --git a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp index e93ea5e7ec9..cbcf43c3aed 100644 --- a/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp +++ b/src/server/scripts/Outland/CoilfangReservoir/SerpentShrine/boss_lurker_below.cpp @@ -229,9 +229,9 @@ public: return; } - if (me->getThreatManager().getThreatList().empty()) // check if should evade + if (!me->IsThreatened()) // check if should evade { - if (me->IsInCombat()) + if (me->IsEngaged()) EnterEvadeMode(); return; } @@ -361,7 +361,7 @@ public: else PhaseTimer -= diff; - if (me->getThreatManager().getThreatList().empty()) // check if should evade + if (!me->IsThreatened()) // check if should evade { EnterEvadeMode(); return; diff --git a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp index 4d65803a7cd..f6ad97f6328 100644 --- a/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp +++ b/src/server/scripts/Outland/GruulsLair/boss_gruul.cpp @@ -206,7 +206,7 @@ class boss_gruul : public CreatureScript // Hurtful Strike if (m_uiHurtfulStrike_Timer <= diff) { - Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1); + Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 1); if (target && me->IsWithinMeleeRange(me->GetVictim())) DoCast(target, SPELL_HURTFUL_STRIKE); diff --git a/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp index b3aafe004a6..57423f63ab0 100644 --- a/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp +++ b/src/server/scripts/Outland/GruulsLair/boss_high_king_maulgar.cpp @@ -249,7 +249,7 @@ public: if (me->Attack(who, true)) { - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); me->SetInCombatWith(who); who->SetInCombatWith(me); @@ -558,17 +558,14 @@ public: //BlastWave_Timer if (BlastWave_Timer <= diff) { - Unit* target = nullptr; - std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); std::vector<Unit*> target_list; - for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr!= t_list.end(); ++itr) + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) { - target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - //15 yard radius minimum - if (target && target->IsWithinDist(me, 15, false)) + Unit* target = ref->GetVictim(); + if (target && target->IsWithinDist(me, 15, false)) // 15 yard radius minimum target_list.push_back(target); - target = nullptr; } + Unit* target = nullptr; if (!target_list.empty()) target = *(target_list.begin() + rand32() % target_list.size()); diff --git a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp index ecfecf2073e..88cf3e61bc7 100644 --- a/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/HellfireRamparts/boss_vazruden_the_herald.cpp @@ -142,7 +142,7 @@ class boss_nazan : public CreatureScript me->SetDisableGravity(false); me->SetWalk(true); me->GetMotionMaster()->Clear(); - if (Unit* victim = SelectTarget(SELECT_TARGET_NEAREST, 0)) + if (Unit* victim = SelectTarget(SELECT_TARGET_MINDISTANCE, 0)) AttackStart(victim); DoStartMovement(me->GetVictim()); Talk(EMOTE); diff --git a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp index 967e01a5cef..8d181927fb4 100644 --- a/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp +++ b/src/server/scripts/Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp @@ -345,8 +345,8 @@ class boss_warbringer_omrogg : public CreatureScript if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { DoYellForThreat(); - DoResetThreat(); - me->AddThreat(target, 0.0f); + ResetThreatList(); + AddThreat(target, 0.0f); } ResetThreat_Timer = 25000 + rand32() % 15000; } diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp index 4e891c9ba7a..9b683770be0 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_alar.cpp @@ -211,7 +211,7 @@ class boss_alar : public CreatureScript void UpdateAI(uint32 diff) override { - if (!me->IsInCombat()) // sometimes IsInCombat but !incombat, faction bug? + if (!me->IsEngaged()) return; if (Berserk_Timer <= diff) @@ -328,7 +328,7 @@ class boss_alar : public CreatureScript if (Phase1) { - if (me->getThreatManager().getThreatList().empty()) + if (!me->IsThreatened()) { EnterEvadeMode(); return; diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp index 78ba67004bc..d3aa6b7e1fa 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_kaelthas.cpp @@ -413,11 +413,11 @@ struct advisorbase_ai : public ScriptedAI if (!Target) Target = me->GetVictim(); - DoResetThreat(); + ResetThreatList(); AttackStart(Target); me->GetMotionMaster()->Clear(); me->GetMotionMaster()->MoveChase(Target); - me->AddThreat(Target, 0.0f); + AddThreat(Target, 0.0f); } } } @@ -563,7 +563,7 @@ class boss_kaelthas : public CreatureScript { DoAction(ACTION_START_ENCOUNTER); who->SetInCombatWith(me); - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); me->SetTarget(who->GetGUID()); } } @@ -624,7 +624,7 @@ class boss_kaelthas : public CreatureScript me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE); me->RemoveAurasDueToSpell(SPELL_FULLPOWER); - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0)) AttackStart(target); DoAction(ACTION_SCHEDULE_COMBAT_EVENTS); @@ -709,7 +709,7 @@ class boss_kaelthas : public CreatureScript Talk(SAY_PHASE4_INTRO2); // Sometimes people can collect Aggro in Phase 1-3. Reset threat before releasing Kael. - DoResetThreat(); + ResetThreatList(); me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE | UNIT_FLAG_PACIFIED); @@ -909,7 +909,7 @@ class boss_thaladred_the_darkener : public CreatureScript void EnterCombat(Unit* who) override { Talk(SAY_THALADRED_AGGRO); - me->AddThreat(who, 5000000.0f); + AddThreat(who, 5000000.0f); } void JustDied(Unit* killer) override @@ -932,8 +932,8 @@ class boss_thaladred_the_darkener : public CreatureScript { if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 0)) { - DoResetThreat(); - me->AddThreat(target, 5000000.0f); + ResetThreatList(); + AddThreat(target, 5000000.0f); Talk(EMOTE_THALADRED_GAZE, target); Gaze_Timer = 8500; } @@ -1092,7 +1092,7 @@ class boss_grand_astromancer_capernian : public CreatureScript if (me->Attack(who, true)) { - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); me->SetInCombatWith(who); who->SetInCombatWith(me); @@ -1142,12 +1142,10 @@ class boss_grand_astromancer_capernian : public CreatureScript { bool InMeleeRange = false; Unit* target = nullptr; - ThreatContainer::StorageType const& threatlist = me->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator i = threatlist.begin(); i!= threatlist.end(); ++i) + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) { - Unit* unit = ObjectAccessor::GetUnit(*me, (*i)->getUnitGuid()); - //if in melee range - if (unit && unit->IsWithinDistInMap(me, 5)) + Unit* unit = ref->GetVictim(); + if (unit->IsWithinMeleeRange(me)) { InMeleeRange = true; target = unit; @@ -1422,7 +1420,7 @@ class npc_phoenix_egg_tk : public CreatureScript void JustSummoned(Creature* summoned) override { - summoned->AddThreat(me->GetVictim(), 0.0f); + AddThreat(me->GetVictim(), 0.0f, summoned); summoned->CastSpell(summoned, SPELL_REBIRTH, false); } diff --git a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp index 962228a215a..e583463d7d4 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/boss_void_reaver.cpp @@ -111,20 +111,13 @@ class boss_void_reaver : public CreatureScript break; case EVENT_ARCANE_ORB: { - Unit* target = nullptr; - std::list<HostileReference*> t_list = me->getThreatManager().getThreatList(); std::vector<Unit*> target_list; - for (std::list<HostileReference*>::const_iterator itr = t_list.begin(); itr != t_list.end(); ++itr) - { - target = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid()); - if (!target) - continue; - // exclude pets & totems, 18 yard radius minimum - if (target->GetTypeId() == TYPEID_PLAYER && target->IsAlive() && !target->IsWithinDist(me, 18, false)) - target_list.push_back(target); - target = nullptr; - } + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) + if (Player* target = ref->GetVictim()->ToPlayer()) + if (target->IsAlive() && !target->IsWithinDist(me, 18, false)) + target_list.push_back(target); + Unit* target; if (!target_list.empty()) target = *(target_list.begin() + rand32() % target_list.size()); else @@ -139,8 +132,8 @@ class boss_void_reaver : public CreatureScript case EVENT_KNOCK_AWAY: DoCastVictim(SPELL_KNOCK_AWAY); // Drop 25% aggro - if (DoGetThreat(me->GetVictim())) - DoModifyThreatPercent(me->GetVictim(), -25); + if (GetThreat(me->GetVictim())) + ModifyThreatByPercent(me->GetVictim(), -25); events.ScheduleEvent(EVENT_KNOCK_AWAY, 30000); break; diff --git a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.cpp b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.cpp index 1cbb522552c..fb2361f2837 100644 --- a/src/server/scripts/Outland/TempestKeep/Eye/the_eye.cpp +++ b/src/server/scripts/Outland/TempestKeep/Eye/the_eye.cpp @@ -79,16 +79,11 @@ class npc_crystalcore_devastator : public CreatureScript //Knockaway_Timer if (Knockaway_Timer <= diff) { - DoCastVictim(SPELL_KNOCKAWAY, true); - - // current aggro target is knocked away pick new target - Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0); - - if (!target || target == me->GetVictim()) - target = SelectTarget(SELECT_TARGET_TOPAGGRO, 1); - - if (target) - me->TauntApply(target); + if (Unit* victim = me->GetVictim()) + { + DoCastVictim(SPELL_KNOCKAWAY, true); + me->GetThreatManager().ResetThreat(victim); + } Knockaway_Timer = 23000; } diff --git a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp index 15f70ada7a7..e5f9e43711a 100644 --- a/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp +++ b/src/server/scripts/Outland/TempestKeep/Mechanar/boss_nethermancer_sepethrea.cpp @@ -215,7 +215,6 @@ class npc_ragin_flames : public CreatureScript if (inferno_Timer <= diff) { DoCastVictim(SPELL_INFERNO); - me->TauntApply(me->GetVictim()); inferno_Timer = 10000; } else inferno_Timer -= diff; diff --git a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp index d571c155dbe..7954efd9a61 100644 --- a/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp +++ b/src/server/scripts/Outland/TempestKeep/arcatraz/arcatraz.cpp @@ -117,7 +117,7 @@ class npc_millhouse_manastorm : public CreatureScript { if (me->Attack(who, true)) { - me->AddThreat(who, 0.0f); + AddThreat(who, 0.0f); me->SetInCombatWith(who); who->SetInCombatWith(me); me->GetMotionMaster()->MoveChase(who, 25.0f); diff --git a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp index 7c80a20aba9..7b6bed80c8a 100644 --- a/src/server/scripts/Outland/zone_hellfire_peninsula.cpp +++ b/src/server/scripts/Outland/zone_hellfire_peninsula.cpp @@ -99,7 +99,7 @@ public: me->SetFaction(FACTION_FRIENDLY); me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); Talk(SAY_FREE); return; @@ -971,7 +971,7 @@ public: _events.Reset(); me->RestoreFaction(); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER); me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); @@ -996,7 +996,7 @@ public: case EVENT_ATTACK: me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC); me->SetFaction(FACTION_MONSTER_2); - me->CombatStart(ObjectAccessor::GetPlayer(*me, _playerGUID)); + me->EngageWithTarget(ObjectAccessor::GetPlayer(*me, _playerGUID)); _events.ScheduleEvent(EVENT_FIREBALL, 1); _events.ScheduleEvent(EVENT_FROSTNOVA, Seconds(5)); break; diff --git a/src/server/scripts/Outland/zone_netherstorm.cpp b/src/server/scripts/Outland/zone_netherstorm.cpp index 8f8fc39a2b3..6fcf5c37004 100644 --- a/src/server/scripts/Outland/zone_netherstorm.cpp +++ b/src/server/scripts/Outland/zone_netherstorm.cpp @@ -431,21 +431,14 @@ public: // some code to cast spell Mana Burn on random target which has mana if (ManaBurnTimer <= diff) { - std::list<HostileReference*> AggroList = me->getThreatManager().getThreatList(); std::list<Unit*> UnitsWithMana; - - for (std::list<HostileReference*>::const_iterator itr = AggroList.begin(); itr != AggroList.end(); ++itr) - { - if (Unit* unit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid())) - { - if (unit->GetCreateMana() > 0) - UnitsWithMana.push_back(unit); - } - } + for (auto* ref : me->GetThreatManager().GetUnsortedThreatList()) + if (ref->GetVictim()->GetPower(POWER_MANA)) + UnitsWithMana.push_back(ref->GetVictim()); if (!UnitsWithMana.empty()) { DoCast(Trinity::Containers::SelectRandomContainerElement(UnitsWithMana), SPELL_MANA_BURN); - ManaBurnTimer = 8000 + (rand32() % 10 * 1000); // 8-18 sec cd + ManaBurnTimer = urand(8000, 18000); // 8-18 sec cd } else ManaBurnTimer = 3500; diff --git a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp index 9e89c34fe72..d7f9ff9e4bd 100644 --- a/src/server/scripts/Outland/zone_shadowmoon_valley.cpp +++ b/src/server/scripts/Outland/zone_shadowmoon_valley.cpp @@ -398,13 +398,11 @@ public: Unit* Dragonmaw = me->FindNearestCreature(NPC_DRAGONMAW_SUBJUGATOR, 50); if (Dragonmaw) { - me->AddThreat(Dragonmaw, 100000.0f); + AddThreat(Dragonmaw, 100000.0f); AttackStart(Dragonmaw); } - HostileReference* ref = me->getThreatManager().getOnlineContainer().getReferenceByTarget(caster); - if (ref) - ref->removeReference(); + me->GetThreatManager().ClearThreat(caster); } } @@ -908,7 +906,7 @@ public: if (Player* AggroTarget = ObjectAccessor::GetPlayer(*me, AggroTargetGUID)) { me->SetTarget(AggroTarget->GetGUID()); - me->AddThreat(AggroTarget, 1); + AddThreat(AggroTarget, 1); me->HandleEmoteCommand(EMOTE_ONESHOT_POINT); } break; diff --git a/src/server/scripts/Outland/zone_terokkar_forest.cpp b/src/server/scripts/Outland/zone_terokkar_forest.cpp index 1ccb7950fa0..758db799ea4 100644 --- a/src/server/scripts/Outland/zone_terokkar_forest.cpp +++ b/src/server/scripts/Outland/zone_terokkar_forest.cpp @@ -97,7 +97,7 @@ public: me->SetFaction(FACTION_FRIENDLY); me->SetStandState(UNIT_STAND_STATE_SIT); me->RemoveAllAuras(); - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); UnkorUnfriendly_Timer = 60000; } diff --git a/src/server/scripts/Pet/pet_hunter.cpp b/src/server/scripts/Pet/pet_hunter.cpp index b68511ea7f5..20dcf5fb5d7 100644 --- a/src/server/scripts/Pet/pet_hunter.cpp +++ b/src/server/scripts/Pet/pet_hunter.cpp @@ -239,7 +239,7 @@ class spell_pet_guard_dog : public SpellScriptLoader caster->CastSpell((Unit*)nullptr, SPELL_PET_GUARD_DOG_HAPPINESS, true, nullptr, aurEff); float addThreat = CalculatePct(ASSERT_NOTNULL(eventInfo.GetSpellInfo())->Effects[EFFECT_0].CalcValue(caster), aurEff->GetAmount()); - eventInfo.GetProcTarget()->AddThreat(caster, addThreat); + eventInfo.GetProcTarget()->GetThreatManager().AddThreat(caster, addThreat, GetSpellInfo(), false, true); } void Register() override diff --git a/src/server/scripts/Pet/pet_mage.cpp b/src/server/scripts/Pet/pet_mage.cpp index b782f550c3b..49c2b418258 100644 --- a/src/server/scripts/Pet/pet_mage.cpp +++ b/src/server/scripts/Pet/pet_mage.cpp @@ -82,21 +82,13 @@ class npc_pet_mage_mirror_image : public CreatureScript continue; } // else compare best fit unit with current unit - ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr) + float threat = (*iter)->GetThreatManager().GetThreat(owner); + // Check if best fit hostile unit hs lower threat than this current unit + if (highestThreat < threat) { - // Try to find threat referenced to owner - if ((*trig_citr)->getTarget() == owner) - { - // Check if best fit hostile unit hs lower threat than this current unit - if (highestThreat < (*trig_citr)->getThreat()) - { - // If so, update best fit unit - highestThreat = (*trig_citr)->getThreat(); - highestThreatUnit = (*iter); - break; - } - } + // If so, update best fit unit + highestThreat = threat; + highestThreatUnit = (*iter); } // In case no unit with threat was found so far, always check for nearest unit (only for players) if ((*iter)->GetTypeId() == TYPEID_PLAYER) @@ -118,30 +110,7 @@ class npc_pet_mage_mirror_image : public CreatureScript bool IsInThreatList(Unit* target) { Unit* owner = me->GetCharmerOrOwner(); - - std::list<Unit*> targets; - Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(me, me, 30.0f); - Trinity::UnitListSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(me, targets, u_check); - Cell::VisitAllObjects(me, searcher, 40.0f); - - for (std::list<Unit*>::const_iterator iter = targets.begin(); iter != targets.end(); ++iter) - { - if ((*iter) == target) - { - // Consider only units without CC - if (!(*iter)->HasBreakableByDamageCrowdControlAura((*iter))) - { - ThreatContainer::StorageType triggers = (*iter)->getThreatManager().getThreatList(); - for (ThreatContainer::StorageType::const_iterator trig_citr = triggers.begin(); trig_citr != triggers.end(); ++trig_citr) - { - // Try to find threat referenced to owner - if ((*trig_citr)->getTarget() == owner) - return true; - } - } - } - } - return false; + return owner && target->IsThreatenedBy(owner); } void InitializeAI() override diff --git a/src/server/scripts/Pet/pet_priest.cpp b/src/server/scripts/Pet/pet_priest.cpp index 09dc6c07439..02db0a5c1bd 100644 --- a/src/server/scripts/Pet/pet_priest.cpp +++ b/src/server/scripts/Pet/pet_priest.cpp @@ -49,7 +49,7 @@ class npc_pet_pri_lightwell : public CreatureScript if (!me->IsAlive()) return; - me->DeleteThreatList(); + me->GetThreatManager().ClearAllThreat(); me->CombatStop(true); me->ResetPlayerDamageReq(); } diff --git a/src/server/scripts/Spells/spell_shaman.cpp b/src/server/scripts/Spells/spell_shaman.cpp index 5b89beaee2c..72208d73653 100644 --- a/src/server/scripts/Spells/spell_shaman.cpp +++ b/src/server/scripts/Spells/spell_shaman.cpp @@ -1608,7 +1608,7 @@ public: // Threat reduction is around 10% confirmed in retail and from wiki Unit* attacker = eventInfo.GetActor(); if (attacker->IsAlive()) - attacker->getThreatManager().modifyThreatPercent(target, -10); + attacker->GetThreatManager().ModifyThreatByPercent(target, -10); } } } diff --git a/src/server/scripts/Spells/spell_warlock.cpp b/src/server/scripts/Spells/spell_warlock.cpp index 1b602210889..4ff38244435 100644 --- a/src/server/scripts/Spells/spell_warlock.cpp +++ b/src/server/scripts/Spells/spell_warlock.cpp @@ -1373,7 +1373,7 @@ class spell_warl_soulshatter : public SpellScriptLoader Unit* caster = GetCaster(); if (Unit* target = GetHitUnit()) { - if (target->CanHaveThreatList() && target->getThreatManager().getThreat(caster) > 0.0f) + if (target->CanHaveThreatList() && target->GetThreatManager().IsThreatenedBy(caster, true)) caster->CastSpell(target, SPELL_WARLOCK_SOULSHATTER, true); } } diff --git a/src/server/scripts/World/boss_emerald_dragons.cpp b/src/server/scripts/World/boss_emerald_dragons.cpp index 65bd57c2a16..f510b5c6839 100644 --- a/src/server/scripts/World/boss_emerald_dragons.cpp +++ b/src/server/scripts/World/boss_emerald_dragons.cpp @@ -156,7 +156,7 @@ struct emerald_dragonAI : public WorldBossAI return; } - if (Unit* target = SelectTarget(SELECT_TARGET_TOPAGGRO, 0, -50.0f, true)) + if (Unit* target = SelectTarget(SELECT_TARGET_MAXTHREAT, 0, -50.0f, true)) DoCast(target, SPELL_SUMMON_PLAYER); DoMeleeAttackIfReady(); diff --git a/src/server/scripts/World/npcs_special.cpp b/src/server/scripts/World/npcs_special.cpp index 8fc60e6ace7..03631c5b808 100644 --- a/src/server/scripts/World/npcs_special.cpp +++ b/src/server/scripts/World/npcs_special.cpp @@ -1810,7 +1810,7 @@ public: void DamageTaken(Unit* doneBy, uint32& damage) override { - me->AddThreat(doneBy, float(damage)); // just to create threat reference + AddThreat(doneBy, float(damage)); // just to create threat reference _damageTimes[doneBy->GetGUID()] = time(nullptr); damage = 0; } |