30#include <boost/heap/fibonacci_heap.hpp>
34class ThreatManager::Heap :
public boost::heap::fibonacci_heap<ThreatReference const*, boost::heap::compare<CompareThreatLessThan>>
186 if (tWho->GetSummonerGUID().IsPlayer())
193 _sortedThreatList(
std::make_unique<
Heap>()), _currentVictimRef(nullptr), _fixateRef(nullptr)
242 if (!ref->IsOffline())
252 if (ref->IsAvailable())
262 return (includeOffline || it->second->IsAvailable());
271 return (includeOffline || it->second->IsAvailable()) ? it->second->GetThreat() : 0.0f;
288 return (itr++)->second;
309 std::vector<ThreatReference*> list;
321 if (pair.second->IsAvailable())
331 return (includeOffline || it->second->IsAvailable());
339 bool const shouldBeSuppressed = pair.second->ShouldBeSuppressed();
340 if (pair.second->IsOnline() && shouldBeSuppressed)
343 pair.second->HeapNotifyDecreased();
345 else if (canExpire && pair.second->IsSuppressed() && !shouldBeSuppressed)
348 pair.second->HeapNotifyIncreased();
367 AddThreat(vehicle, amount, spell, ignoreModifiers, ignoreRedirects);
378 AddThreat(privateObjectOwner, amount, spell, ignoreModifiers, ignoreRedirects);
398 if (!ignoreModifiers)
402 if (!ignoreRedirects && amount > 0.0f)
405 if (!redirInfo.empty())
407 float const origAmount = amount;
409 for (
size_t i = 0; i < redirInfo.size(); ++i)
411 auto const pair = redirInfo[i];
412 Unit* redirTarget =
nullptr;
415 redirTarget = it->second->_victim;
421 float amountRedirected =
CalculatePct(origAmount, pair.second);
422 AddThreat(redirTarget, amountRedirected, spell,
true,
true);
423 amount -= amountRedirected;
471 it->second->ScaleThreat(std::max<float>(factor,0.0f));
499 std::unordered_map<ObjectGuid, uint32> tauntStates;
501 for (
AuraEffect const* tauntEffect : tauntEffects)
502 tauntStates[tauntEffect->GetCasterGUID()] = ++tauntPriority;
506 auto it = tauntStates.find(pair.first);
507 if (it != tauntStates.end())
510 pair.second->UpdateTauntState();
520 pair.second->ScaleThreat(0.0f);
599 if (oldVictimRef && oldVictimRef->
IsOffline())
600 oldVictimRef =
nullptr;
607 if (!oldVictimRef || highest == oldVictimRef)
625 if (next == oldVictimRef)
637 ABORT_MSG(
"Current victim not found in sorted threat list even though it has a reference - manager desync!");
668 if (threatEntry->pctMod != 1.0f)
669 threat *= threatEntry->pctMod;
706 threat *= it->second;
725 std::vector<Creature*> canBeThreatened, cannotBeThreatened;
730 canBeThreatened.push_back(owner);
732 cannotBeThreatened.push_back(owner);
735 if (!canBeThreatened.empty())
737 float const perTarget = baseAmount / canBeThreatened.size();
738 for (
Creature* threatened : canBeThreatened)
742 for (
Creature* threatened : cannotBeThreatened)
743 threatened->GetThreatManager().AddThreat(assistant, 0.0f, spell,
true);
748 std::vector<ThreatReference*> threatReferencesToRemove;
751 if (!unitFilter || unitFilter(ref->GetOwner()))
752 threatReferencesToRemove.push_back(ref);
755 ref->_mgr.ClearThreat(
_owner);
762 mod += eff->GetAmount();
768 bool const isIncrease = (it->second->_tempModifier < mod);
771 it->second->_tempModifier = mod;
773 it->second->HeapNotifyIncreased();
775 it->second->HeapNotifyDecreased();
806 auto& victimMap = it->second;
807 auto it2 = victimMap.find(victim);
808 if (it2 == victimMap.end())
810 victimMap.erase(it2);
840 auto fillSharedPacketDataAndSend = [&](
auto& packet)
846 if (!ref->IsAvailable())
850 threatInfo.
UnitGUID = ref->GetVictim()->GetGUID();
852 packet.ThreatList.push_back(threatInfo);
861 fillSharedPacketDataAndSend(highestThreatUpdate);
866 fillSharedPacketDataAndSend(threatUpdate);
897 ASSERT(!inMap,
"Duplicate threatened-by-me reference at %p being inserted on %s for %s - memory leak!", ref,
_owner->
GetGUID().
ToString().c_str(), guid.
ToString().c_str());
913 for (
auto const& victimPair : pair.second)
915 uint32 thisPct = std::min<uint32>(100 - totalPct, victimPair.second);
#define ASSERT_NOTNULL(pointer)
@ SPELL_SCHOOL_MASK_NORMAL
@ SPELL_SCHOOL_MASK_SHADOW
@ SPELL_SCHOOL_MASK_ARCANE
@ SPELL_SCHOOL_MASK_NATURE
@ SPELL_SCHOOL_MASK_FROST
@ SPELL_ATTR2_NO_INITIAL_THREAT
@ SPELL_ATTR4_NO_HELPFUL_THREAT
@ SPELL_AURA_MOD_TOTAL_THREAT
@ UNIT_FLAG_IMMUNE_TO_NPC
@ UNIT_FLAG_PLAYER_CONTROLLED
T CalculatePct(T base, U pct)
bool SetInCombatWith(Unit *who, bool addSecondUnitSuppressed=false)
bool IsInCombatWith(ObjectGuid const &who) const
virtual void JustStartedThreateningMe(Unit *who)
bool _IsTargetAcceptable(Unit const *target) const
bool IsThreatFeedbackDisabled() const
SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType=BASE_ATTACK) const override
bool CanCreatureAttack(Unit const *victim, bool force=true) const
std::string ToString() const
static Creature * ToCreature(Object *o)
static ObjectGuid GetGUID(Object const *o)
SpellSchoolMask GetSchoolMask() const
bool HasAttribute(SpellAttr0 attribute) const
std::unordered_map< ObjectGuid, ThreatReference * > _threatenedByMe
bool CanHaveThreatList() const
ThreatManager(Unit *owner)
static float CalculateModifiedThreat(float threat, Unit const *victim, SpellInfo const *spell)
void SendClearAllThreatToClients() const
void EvaluateSuppressed(bool canExpire=false)
void UnregisterRedirectThreat(uint32 spellId)
void ForwardThreatForAssistingMe(Unit *assistant, float baseAmount, SpellInfo const *spell=nullptr, bool ignoreModifiers=false)
== AFFECT OTHERS' THREAT LISTS ==
std::vector< std::pair< ObjectGuid, uint32 > > _redirectInfo
bool IsThreatenedBy(ObjectGuid const &who, bool includeOffline=false) const
void PutThreatListRef(ObjectGuid const &guid, ThreatReference *ref)
== MY THREAT LIST ==
bool IsThreateningTo(ObjectGuid const &who, bool includeOffline=false) const
void RemoveMeFromThreatLists(bool(*unitFilter)(Unit const *otherUnit))
Unit * GetCurrentVictim()
static const uint32 THREAT_UPDATE_INTERVAL
void PutThreatenedByMeRef(ObjectGuid const &guid, ThreatReference *ref)
== OTHERS' THREAT LISTS ==
void RegisterForAIUpdate(ObjectGuid const &guid)
void SendThreatListToClients(bool newHighest) const
void UpdateRedirectInfo()
std::array< float, MAX_SPELL_SCHOOL > _singleSchoolModifiers
void UpdateMySpellSchoolModifiers()
static bool CompareReferencesLT(ThreatReference const *a, ThreatReference const *b, float aWeight)
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetUnsortedThreatList() const
std::unordered_map< uint32, std::unordered_map< ObjectGuid, uint32 > > _redirectRegistry
static const CompareThreatLessThan CompareThreat
std::unique_ptr< Heap > _sortedThreatList
void ScaleThreat(Unit *target, float factor)
void ClearThreat(Unit *target)
ThreatReference const * _currentVictimRef
Unit * GetAnyTarget() const
Unit * GetLastVictim() const
std::unordered_map< ObjectGuid, ThreatReference * > _myThreatListEntries
bool _ownerCanHaveThreatList
void FixateTarget(Unit *target)
bool IsThreatListEmpty(bool includeOffline=false) const
std::vector< ObjectGuid > _needsAIUpdate
void Update(uint32 tdiff)
void PurgeThreatListRef(ObjectGuid const &guid)
void AddThreat(Unit *target, float amount, SpellInfo const *spell=nullptr, bool ignoreModifiers=false, bool ignoreRedirects=false)
== AFFECT MY THREAT LIST ==
bool IsThreateningAnyone(bool includeOffline=false) const
ThreatReference const * _fixateRef
ThreatReference const * ReselectVictim()
void SendRemoveToClients(Unit const *victim) const
Trinity::IteratorPair< ThreatListIterator, std::nullptr_t > GetSortedThreatList() const
std::vector< ThreatReference * > GetModifiableThreatList()
void RegisterRedirectThreat(uint32 spellId, ObjectGuid const &victim, uint32 pct)
== REDIRECT SYSTEM ==
std::unordered_map< std::underlying_type< SpellSchoolMask >::type, float > _multiSchoolModifiers
Unit * GetFixateTarget() const
friend class ThreatReferenceImpl
void UpdateMyTempModifiers()
void PurgeThreatenedByMeRef(ObjectGuid const &guid)
float GetThreat(Unit const *who, bool includeOffline=false) const
void MatchUnitThreatToHighestThreat(Unit *target)
size_t GetThreatListSize() const
ThreatManager::Heap::handle_type _handle
ThreatReferenceImpl(ThreatManager *mgr, Unit *victim)
static bool FlagsAllowFighting(Unit const *a, Unit const *b)
void HeapNotifyDecreased()
void ScaleThreat(float factor)
void HeapNotifyIncreased()
@ ONLINE_STATE_SUPPRESSED
bool ShouldBeSuppressed() const
OnlineState GetOnlineState() const
bool ShouldBeOffline() const
void UpdateTauntState(TauntState state=TAUNT_STATE_NONE)
void AddThreat(float amount)
Utility class to enable range for loop syntax for multimap.equal_range uses.
bool IsWithinMeleeRange(Unit const *obj) const
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
ThreatManager & GetThreatManager()
std::forward_list< AuraEffect * > AuraEffectList
Unit * GetVehicleBase() const
bool HasUnitFlag(UnitFlags flags) const
TempSummon * ToTempSummon()
bool HasAuraType(AuraType auraType) const
bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
float GetTotalAuraMultiplierByMiscMask(AuraType auraType, uint32 misc_mask) const
bool HasUnitState(const uint32 f) const
uint32 HasUnitTypeMask(uint32 mask) const
bool HasBreakableByDamageAuraType(AuraType type, uint32 excludeAura=0) const
CombatManager & GetCombatManager()
virtual bool IsEngaged() const
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
ObjectGuid GetPrivateObjectOwner() const
bool IsPrivateObject() const
bool CanSeeOrDetect(WorldObject const *obj, bool implicitDetect=false, bool distanceCheck=false, bool checkAlert=false) const
Player * GetSpellModOwner() const
ObjectGuid HighestThreatGUID
WorldPacket const * Write() override
WorldPacket const * Write() override
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
auto MapGetValuePtr(M &map, typename M::key_type const &key)