35#include <boost/heap/fibonacci_heap.hpp>
39class ThreatManager::Heap :
public boost::heap::fibonacci_heap<ThreatReference const*, boost::heap::compare<CompareThreatLessThan>>
191 if (tWho->GetSummonerGUID().IsPlayer())
198 _sortedThreatList(
std::make_unique<
Heap>()), _currentVictimRef(nullptr), _fixateRef(nullptr)
247 if (!ref->IsOffline())
257 if (ref->IsAvailable())
267 return (includeOffline || it->second->IsAvailable());
276 return (includeOffline || it->second->IsAvailable()) ? it->second->GetThreat() : 0.0f;
290 if (ref->IsAvailable() && ref->GetOwner()->GetTypeId() ==
TYPEID_PLAYER)
304 return (itr++)->second;
325 std::vector<ThreatReference*> list;
337 if (pair.second->IsAvailable())
347 return (includeOffline || it->second->IsAvailable());
355 bool const shouldBeSuppressed = pair.second->ShouldBeSuppressed();
356 if (pair.second->IsOnline() && shouldBeSuppressed)
359 pair.second->HeapNotifyDecreased();
361 else if (canExpire && pair.second->IsSuppressed() && !shouldBeSuppressed)
364 pair.second->HeapNotifyIncreased();
383 AddThreat(vehicle, amount, spell, ignoreModifiers, ignoreRedirects);
394 AddThreat(privateObjectOwner, amount, spell, ignoreModifiers, ignoreRedirects);
414 if (!ignoreModifiers)
418 if (!ignoreRedirects && amount > 0.0f)
421 if (!redirInfo.empty())
423 float const origAmount = amount;
425 for (
size_t i = 0; i < redirInfo.size(); ++i)
427 auto const pair = redirInfo[i];
428 Unit* redirTarget =
nullptr;
431 redirTarget = it->second->_victim;
437 float amountRedirected =
CalculatePct(origAmount, pair.second);
438 AddThreat(redirTarget, amountRedirected, spell,
true,
true);
439 amount -= amountRedirected;
487 it->second->ScaleThreat(std::max<float>(factor,0.0f));
515 std::unordered_map<ObjectGuid, ThreatReference::TauntState> tauntStates;
517 for (
auto it = tauntEffects.begin(), end = tauntEffects.end(); it != end; ++it)
522 auto it = tauntStates.find(pair.first);
523 if (it != tauntStates.end())
524 pair.second->UpdateTauntState(it->second);
526 pair.second->UpdateTauntState();
536 pair.second->ScaleThreat(0.0f);
615 if (oldVictimRef && oldVictimRef->
IsOffline())
616 oldVictimRef =
nullptr;
623 if (!oldVictimRef || highest == oldVictimRef)
641 if (next == oldVictimRef)
653 ABORT_MSG(
"Current victim not found in sorted threat list even though it has a reference - manager desync!");
684 if (threatEntry->pctMod != 1.0f)
685 threat *= threatEntry->pctMod;
722 threat *= it->second;
741 std::vector<Creature*> canBeThreatened, cannotBeThreatened;
746 canBeThreatened.push_back(owner);
748 cannotBeThreatened.push_back(owner);
751 if (!canBeThreatened.empty())
753 float const perTarget = baseAmount / canBeThreatened.size();
754 for (
Creature* threatened : canBeThreatened)
758 for (
Creature* threatened : cannotBeThreatened)
759 threatened->GetThreatManager().AddThreat(assistant, 0.0f, spell,
true);
767 ref->_mgr.ClearThreat(
_owner);
775 mod += eff->GetAmount();
781 bool const isIncrease = (it->second->_tempModifier < mod);
784 it->second->_tempModifier = mod;
786 it->second->HeapNotifyIncreased();
788 it->second->HeapNotifyDecreased();
819 auto& victimMap = it->second;
820 auto it2 = victimMap.find(victim);
821 if (it2 == victimMap.end())
823 victimMap.erase(it2);
848 size_t countPos = data.
wpos();
853 if (!ref->IsAvailable())
855 data << ref->GetVictim()->GetPackGUID();
856 data <<
uint32(ref->GetThreat() * 100);
890 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());
906 for (
auto const& victimPair : pair.second)
908 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_ATTR3_NO_INITIAL_AGGRO
@ SPELL_AURA_MOD_TOTAL_THREAT
@ UNIT_FLAG_IMMUNE_TO_NPC
@ UNIT_FLAG_PLAYER_CONTROLLED
T CalculatePct(T base, U pct)
void put(std::size_t pos, T value)
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 CanCreatureAttack(Unit const *victim, bool force=true) const
SpellSchoolMask GetMeleeDamageSchoolMask(WeaponAttackType=BASE_ATTACK, uint8=0) const override
std::string ToString() const
static Creature * ToCreature(Object *o)
PackedGuid const & GetPackGUID() const
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 RemoveMeFromThreatLists()
void PutThreatListRef(ObjectGuid const &guid, ThreatReference *ref)
== MY THREAT LIST ==
bool IsThreateningTo(ObjectGuid const &who, bool includeOffline=false) const
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
uint32 GetThreatListPlayerCount(bool includeOffline=false) 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.
constexpr iterator begin() const
bool IsWithinMeleeRange(Unit const *obj) const
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
ThreatManager & GetThreatManager()
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
@ SMSG_HIGHEST_THREAT_UPDATE
TC_GAME_API Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
auto MapGetValuePtr(M &map, typename M::key_type const &key)