AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
ThreatManager Class Reference

#include "ThreatManager.h"

Classes

class  Heap
 
class  ThreatListIterator
 

Public Member Functions

 ThreatManager (Unit *owner)
 
 ~ThreatManager ()
 
void Initialize ()
 
void Update (uint32 tdiff)
 
UnitGetOwner () const
 
bool CanHaveThreatList () const
 
UnitGetCurrentVictim ()
 
UnitGetLastVictim () const
 
UnitGetAnyTarget () const
 
bool IsThreatListEmpty (bool includeOffline=false) const
 
bool IsThreatenedBy (ObjectGuid const &who, bool includeOffline=false) const
 
bool IsThreatenedBy (Unit const *who, bool includeOffline=false) const
 
float GetThreat (Unit const *who, bool includeOffline=false) const
 
size_t GetThreatListSize () const
 
uint32 GetThreatListPlayerCount (bool includeOffline=false) const
 
Acore::IteratorPair< ThreatListIteratorGetUnsortedThreatList () const
 
Acore::IteratorPair< ThreatListIteratorGetSortedThreatList () const
 
std::vector< ThreatReference * > GetModifiableThreatList ()
 
bool IsThreateningAnyone (bool includeOffline=false) const
 
bool IsThreateningTo (ObjectGuid const &who, bool includeOffline=false) const
 
bool IsThreateningTo (Unit const *who, bool includeOffline=false) const
 
auto const & GetThreatenedByMeList () const
 
void EvaluateSuppressed (bool canExpire=false)
 
void AddThreat (Unit *target, float amount, SpellInfo const *spell=nullptr, bool ignoreModifiers=false, bool ignoreRedirects=false)
 == AFFECT MY THREAT LIST ==
 
void ScaleThreat (Unit *target, float factor)
 
void ModifyThreatByPercent (Unit *target, int32 percent)
 
void ResetThreat (Unit *target)
 
void MatchUnitThreatToHighestThreat (Unit *target)
 
void TauntUpdate ()
 
void ResetAllThreat ()
 
void ClearThreat (Unit *target)
 
void ClearThreat (ThreatReference *ref)
 
void ClearAllThreat ()
 
void FixateTarget (Unit *target)
 
void ClearFixate ()
 
UnitGetFixateTarget () const
 
void ForwardThreatForAssistingMe (Unit *assistant, float baseAmount, SpellInfo const *spell=nullptr, bool ignoreModifiers=false)
 == AFFECT OTHERS' THREAT LISTS ==
 
void ResetAllMyThreatOnOthers ()
 
void RemoveMeFromThreatLists ()
 
void UpdateMyTempModifiers ()
 
void UpdateMySpellSchoolModifiers ()
 
void SetTauntStateForTesting (Unit *target, uint32 state)
 
void RegisterRedirectThreat (uint32 spellId, ObjectGuid const &victim, uint32 pct)
 == REDIRECT SYSTEM ==
 
void UnregisterRedirectThreat (uint32 spellId)
 
void UnregisterRedirectThreat (uint32 spellId, ObjectGuid const &victim)
 
bool HasRedirects () const
 
void ResetAllRedirects ()
 
 ThreatManager (ThreatManager const &)=delete
 
ThreatManageroperator= (ThreatManager const &)=delete
 

Static Public Member Functions

static bool CanHaveThreatList (Unit const *who)
 

Static Public Attributes

static const uint32 THREAT_UPDATE_INTERVAL = 1000u
 

Private Member Functions

void SendClearAllThreatToClients () const
 
void SendRemoveToClients (Unit const *victim) const
 
void SendThreatListToClients (bool newHighest) const
 
void PutThreatListRef (ObjectGuid const &guid, ThreatReference *ref)
 == MY THREAT LIST ==
 
void PurgeThreatListRef (ObjectGuid const &guid)
 
void ProcessAIUpdates ()
 
void RegisterForAIUpdate (ObjectGuid const &guid)
 
void UpdateVictim ()
 
ThreatReference const * ReselectVictim ()
 
void PutThreatenedByMeRef (ObjectGuid const &guid, ThreatReference *ref)
 == OTHERS' THREAT LISTS ==
 
void PurgeThreatenedByMeRef (ObjectGuid const &guid)
 
void UpdateRedirectInfo ()
 

Static Private Member Functions

static bool CompareReferencesLT (ThreatReference const *a, ThreatReference const *b, float aWeight)
 
static float CalculateModifiedThreat (float threat, Unit const *victim, SpellInfo const *spell)
 

Private Attributes

Unit *const _owner
 
bool _ownerCanHaveThreatList
 
bool _needClientUpdate
 
uint32 _updateTimer
 
std::unique_ptr< Heap_sortedThreatList
 
std::unordered_map< ObjectGuid, ThreatReference * > _myThreatListEntries
 
std::vector< ObjectGuid_needsAIUpdate
 
ThreatReference const * _currentVictimRef
 
ThreatReference const * _fixateRef
 
std::unordered_map< ObjectGuid, ThreatReference * > _threatenedByMe
 
std::array< float, MAX_SPELL_SCHOOL_singleSchoolModifiers
 
std::unordered_map< std::underlying_type< SpellSchoolMask >::type, float > _multiSchoolModifiers
 
std::vector< std::pair< ObjectGuid, uint32 > > _redirectInfo
 
std::unordered_map< uint32, std::unordered_map< ObjectGuid, uint32 > > _redirectRegistry
 

Static Private Attributes

static const CompareThreatLessThan CompareThreat
 

Friends

class ThreatReference
 
class ThreatReferenceImpl
 
struct CompareThreatLessThan
 
class debug_commandscript
 

Detailed Description

Constructor & Destructor Documentation

◆ ThreatManager() [1/2]

ThreatManager::ThreatManager ( Unit owner)
213 _sortedThreatList(std::make_unique<Heap>()), _currentVictimRef(nullptr), _fixateRef(nullptr)
214{
215 for (int8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
216 _singleSchoolModifiers[i] = 1.0f;
217}
std::int8_t int8
Definition Define.h:105
constexpr auto MAX_SPELL_SCHOOL
Definition SharedDefines.h:280
uint32 _updateTimer
Definition ThreatManager.h:210
static const uint32 THREAT_UPDATE_INTERVAL
Definition ThreatManager.h:94
std::array< float, MAX_SPELL_SCHOOL > _singleSchoolModifiers
Definition ThreatManager.h:227
std::unique_ptr< Heap > _sortedThreatList
Definition ThreatManager.h:211
ThreatReference const * _currentVictimRef
Definition ThreatManager.h:220
bool _ownerCanHaveThreatList
Definition ThreatManager.h:195
bool _needClientUpdate
Definition ThreatManager.h:209
Unit *const _owner
Definition ThreatManager.h:194
ThreatReference const * _fixateRef
Definition ThreatManager.h:221

References _singleSchoolModifiers, and MAX_SPELL_SCHOOL.

◆ ~ThreatManager()

ThreatManager::~ThreatManager ( )
220{
221 ASSERT(_myThreatListEntries.empty(), "ThreatManager::~ThreatManager - %s: we still have %zu things threatening us, one of them is %s.", _owner->GetGUID().ToString().c_str(), _myThreatListEntries.size(), _myThreatListEntries.begin()->first.ToString().c_str());
222 ASSERT(_sortedThreatList->empty(), "ThreatManager::~ThreatManager - %s: we still have %zu things threatening us, one of them is %s.", _owner->GetGUID().ToString().c_str(), _sortedThreatList->size(), (*_sortedThreatList->begin())->GetVictim()->GetGUID().ToString().c_str());
223 ASSERT(_threatenedByMe.empty(), "ThreatManager::~ThreatManager - %s: we are still threatening %zu things, one of them is %s.", _owner->GetGUID().ToString().c_str(), _threatenedByMe.size(), _threatenedByMe.begin()->first.ToString().c_str());
224}
#define ASSERT
Definition Errors.h:68
std::string ToString() const
Definition ObjectGuid.cpp:47
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:114
std::unordered_map< ObjectGuid, ThreatReference * > _threatenedByMe
Definition ThreatManager.h:226
std::unordered_map< ObjectGuid, ThreatReference * > _myThreatListEntries
Definition ThreatManager.h:212

References _myThreatListEntries, _owner, _sortedThreatList, _threatenedByMe, ASSERT, Object::GetGUID(), and ObjectGuid::ToString().

◆ ThreatManager() [2/2]

ThreatManager::ThreatManager ( ThreatManager const &  )
delete

Member Function Documentation

◆ AddThreat()

void ThreatManager::AddThreat ( Unit target,
float  amount,
SpellInfo const *  spell = nullptr,
bool  ignoreModifiers = false,
bool  ignoreRedirects = false 
)

== AFFECT MY THREAT LIST ==

389{
390 // step 1: we can shortcut if the spell has one of the NO_THREAT attrs set - nothing will happen
391 if (spell)
392 {
393 if (spell->HasAttribute(SPELL_ATTR1_NO_THREAT))
394 return;
395 if (!_owner->IsEngaged() && spell->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS))
396 return;
397 }
398
399 // while riding a vehicle, all threat goes to the vehicle, not the pilot
400 if (Unit* vehicle = target->GetVehicleBase())
401 {
402 AddThreat(vehicle, amount, spell, ignoreModifiers, ignoreRedirects);
403 if (target->HasUnitTypeMask(UNIT_MASK_ACCESSORY)) // accessories are fully treated as components of the parent and cannot have threat
404 return;
405 amount = 0.0f;
406 }
407
408 // if we cannot actually have a threat list, we instead just set combat state and avoid creating threat refs altogether
409 if (!CanHaveThreatList())
410 {
411 CombatManager& combatMgr = _owner->GetCombatManager();
412 if (!combatMgr.SetInCombatWith(target))
413 return;
414 // traverse redirects and put them in combat, too
415 for (auto const& pair : target->GetThreatMgr()._redirectInfo)
416 if (!combatMgr.IsInCombatWith(pair.first))
417 if (Unit* redirTarget = ObjectAccessor::GetUnit(*_owner, pair.first))
418 combatMgr.SetInCombatWith(redirTarget);
419 return;
420 }
421
422 // apply threat modifiers to the amount
423 if (!ignoreModifiers)
424 amount = CalculateModifiedThreat(amount, target, spell);
425
426 // if we're increasing threat, send some/all of it to redirection targets instead if applicable
427 if (!ignoreRedirects && amount > 0.0f)
428 {
429 auto const& redirInfo = target->GetThreatMgr()._redirectInfo;
430 if (!redirInfo.empty())
431 {
432 float const origAmount = amount;
433 // intentional iteration by index - there's a nested AddThreat call further down that might cause AI calls which might modify redirect info through spells
434 for (size_t i = 0; i < redirInfo.size(); ++i)
435 {
436 auto const pair = redirInfo[i]; // (victim,pct)
437 Unit* redirTarget = nullptr;
438 auto it = _myThreatListEntries.find(pair.first); // try to look it up in our threat list first (faster)
439 if (it != _myThreatListEntries.end())
440 redirTarget = it->second->_victim;
441 else
442 redirTarget = ObjectAccessor::GetUnit(*_owner, pair.first);
443
444 if (redirTarget)
445 {
446 float amountRedirected = CalculatePct(origAmount, pair.second);
447 AddThreat(redirTarget, amountRedirected, spell, true, true);
448 amount -= amountRedirected;
449 }
450 }
451 }
452 }
453
454 // ensure we're in combat (threat implies combat!)
455 if (!_owner->GetCombatManager().SetInCombatWith(target)) // if this returns false, we're not actually in combat, and thus cannot have threat!
456 return; // typical causes: bad scripts trying to add threat to GMs, dead targets etc
457
458 // ok, now we actually apply threat
459 // check if we already have an entry - if we do, just increase threat for that entry and we're done
460 auto it = _myThreatListEntries.find(target->GetGUID());
461 if (it != _myThreatListEntries.end())
462 {
463 ThreatReference* const ref = it->second;
464
465 // SUPPRESSED threat states don't go back to ONLINE until threat is caused by them (retail behavior)
467 if (!ref->ShouldBeSuppressed())
468 {
470 ref->HeapNotifyIncreased();
471 }
472
473 if (ref->IsOnline())
474 ref->AddThreat(amount);
475
476 return;
477 }
478
479 // ok, we're now in combat - create the threat list reference and push it to the respective managers
480 ThreatReference* ref = new ThreatReferenceImpl(this, target);
481 PutThreatListRef(target->GetGUID(), ref);
483
484 ref->UpdateOffline();
485 if (ref->IsOnline()) // we only add the threat if the ref is currently available
486 ref->AddThreat(amount);
487 // Note: AI update registration is handled inside UpdateOffline() when transitioning from OFFLINE
488
490 UpdateVictim();
491 else
493}
@ SPELL_ATTR1_NO_THREAT
Definition SharedDefines.h:417
@ SPELL_ATTR3_SUPPRESS_TARGET_PROCS
Definition SharedDefines.h:498
@ UNIT_MASK_ACCESSORY
Definition UnitDefines.h:168
T CalculatePct(T base, U pct)
Definition Util.h:52
Definition CombatManager.h:104
bool SetInCombatWith(Unit *who, bool addSecondUnitSuppressed=false)
Definition CombatManager.cpp:213
bool CanHaveThreatList() const
Definition ThreatManager.h:109
static float CalculateModifiedThreat(float threat, Unit const *victim, SpellInfo const *spell)
Definition ThreatManager.cpp:699
std::vector< std::pair< ObjectGuid, uint32 > > _redirectInfo
Definition ThreatManager.h:231
void PutThreatListRef(ObjectGuid const &guid, ThreatReference *ref)
== MY THREAT LIST ==
Definition ThreatManager.cpp:892
void PutThreatenedByMeRef(ObjectGuid const &guid, ThreatReference *ref)
== OTHERS' THREAT LISTS ==
Definition ThreatManager.cpp:916
void AddThreat(Unit *target, float amount, SpellInfo const *spell=nullptr, bool ignoreModifiers=false, bool ignoreRedirects=false)
== AFFECT MY THREAT LIST ==
Definition ThreatManager.cpp:388
void ProcessAIUpdates()
Definition ThreatManager.cpp:678
friend class ThreatReferenceImpl
Definition ThreatManager.h:259
void UpdateVictim()
Definition ThreatManager.cpp:608
Definition ThreatManager.h:265
void UpdateOffline()
Definition ThreatManager.cpp:75
void HeapNotifyIncreased()
Definition ThreatManager.cpp:179
@ ONLINE_STATE_ONLINE
Definition ThreatManager.h:268
@ ONLINE_STATE_SUPPRESSED
Definition ThreatManager.h:268
bool ShouldBeSuppressed() const
Definition ThreatManager.cpp:123
OnlineState GetOnlineState() const
Definition ThreatManager.h:273
bool IsOnline() const
Definition ThreatManager.h:274
OnlineState _online
Definition ThreatManager.h:311
void AddThreat(float amount)
Definition ThreatManager.cpp:51
Definition Unit.h:664
Unit * GetVehicleBase() const
Definition Unit.cpp:14927
ThreatManager & GetThreatMgr()
Definition Unit.h:951
uint32 HasUnitTypeMask(uint32 mask) const
Definition Unit.h:741
CombatManager & GetCombatManager()
Definition Unit.h:953
virtual bool IsEngaged() const
Definition Unit.h:931
Definition ObjectAccessor.h:61
Unit * GetUnit(WorldObject const &, ObjectGuid const &guid)
Definition ObjectAccessor.cpp:199

References _currentVictimRef, _myThreatListEntries, ThreatReference::_online, _owner, _redirectInfo, ThreatReference::AddThreat(), AddThreat(), CalculateModifiedThreat(), CalculatePct(), CanHaveThreatList(), Unit::GetCombatManager(), Object::GetGUID(), ThreatReference::GetOnlineState(), Unit::GetThreatMgr(), ObjectAccessor::GetUnit(), Unit::GetVehicleBase(), SpellInfo::HasAttribute(), Unit::HasUnitTypeMask(), ThreatReference::HeapNotifyIncreased(), Unit::IsEngaged(), CombatManager::IsInCombatWith(), ThreatReference::IsOnline(), ThreatReference::ONLINE_STATE_ONLINE, ThreatReference::ONLINE_STATE_SUPPRESSED, ProcessAIUpdates(), PutThreatenedByMeRef(), PutThreatListRef(), CombatManager::SetInCombatWith(), ThreatReference::ShouldBeSuppressed(), SPELL_ATTR1_NO_THREAT, SPELL_ATTR3_SUPPRESS_TARGET_PROCS, ThreatReferenceImpl, UNIT_MASK_ACCESSORY, ThreatReference::UpdateOffline(), and UpdateVictim().

Referenced by AddThreat(), Unit::AddThreat(), ScriptedAI::DoAddThreat(), Spell::EffectThreat(), Unit::EngageWithTarget(), TemporaryThreatModifierEvent::Execute(), ForwardThreatForAssistingMe(), spell_pet_guard_dog::HandleProc(), Spell::HandleThreatSpells(), MatchUnitThreatToHighestThreat(), SmartScript::ProcessAction(), boss_priestess_lackey_commonAI::RecalculateThreat(), boss_faction_championsAI::RecalculateThreat(), boss_drakkisath::boss_drakkisathAI::UpdateAI(), boss_grilek::boss_grilekAI::UpdateAI(), boss_gothik::boss_gothikAI::UpdateAI(), and boss_netherspite::UpdatePortals().

◆ CalculateModifiedThreat()

float ThreatManager::CalculateModifiedThreat ( float  threat,
Unit const *  victim,
SpellInfo const *  spell 
)
staticprivate
700{
701 // modifiers by spell
702 if (spell)
703 {
704 if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(spell->Id))
705 if (threatEntry->pctMod != 1.0f) // flat/AP modifiers handled in Spell::HandleThreatSpells
706 threat *= threatEntry->pctMod;
707
708 if (Player* modOwner = victim->GetSpellModOwner())
709 modOwner->ApplySpellMod(spell->Id, SPELLMOD_THREAT, threat);
710 }
711
712 // modifiers by effect school
713 ThreatManager const& victimMgr = victim->GetThreatMgr();
714 SpellSchoolMask const mask = spell ? spell->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL;
715 switch (mask)
716 {
718 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_NORMAL];
719 break;
721 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_HOLY];
722 break;
724 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_FIRE];
725 break;
727 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_NATURE];
728 break;
730 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_FROST];
731 break;
733 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_SHADOW];
734 break;
736 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_ARCANE];
737 break;
738 default:
739 {
740 auto it = victimMgr._multiSchoolModifiers.find(mask);
741 if (it != victimMgr._multiSchoolModifiers.end())
742 {
743 threat *= it->second;
744 break;
745 }
746 float mod = victim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, mask);
747 victimMgr._multiSchoolModifiers[mask] = mod;
748 threat *= mod;
749 break;
750 }
751 }
752 return threat;
753}
@ SPELL_SCHOOL_SHADOW
Definition SharedDefines.h:276
@ SPELL_SCHOOL_NORMAL
Definition SharedDefines.h:271
@ SPELL_SCHOOL_NATURE
Definition SharedDefines.h:274
@ SPELL_SCHOOL_FROST
Definition SharedDefines.h:275
@ SPELL_SCHOOL_ARCANE
Definition SharedDefines.h:277
@ SPELL_SCHOOL_FIRE
Definition SharedDefines.h:273
@ SPELL_SCHOOL_HOLY
Definition SharedDefines.h:272
SpellSchoolMask
Definition SharedDefines.h:283
@ SPELL_SCHOOL_MASK_NORMAL
Definition SharedDefines.h:285
@ SPELL_SCHOOL_MASK_SHADOW
Definition SharedDefines.h:290
@ SPELL_SCHOOL_MASK_ARCANE
Definition SharedDefines.h:291
@ SPELL_SCHOOL_MASK_NATURE
Definition SharedDefines.h:288
@ SPELL_SCHOOL_MASK_HOLY
Definition SharedDefines.h:286
@ SPELL_SCHOOL_MASK_FIRE
Definition SharedDefines.h:287
@ SPELL_SCHOOL_MASK_FROST
Definition SharedDefines.h:289
@ SPELL_AURA_MOD_THREAT
Definition SpellAuraDefines.h:73
@ SPELLMOD_THREAT
Definition SpellDefines.h:78
#define sSpellMgr
Definition SpellMgr.h:815
Definition Player.h:1084
Definition ThreatManager.h:90
std::unordered_map< std::underlying_type< SpellSchoolMask >::type, float > _multiSchoolModifiers
Definition ThreatManager.h:228
Player * GetSpellModOwner() const
Definition Unit.cpp:12885
Definition SpellMgr.h:372

References _multiSchoolModifiers, _singleSchoolModifiers, SpellInfo::GetSchoolMask(), Unit::GetSpellModOwner(), Unit::GetThreatMgr(), Unit::GetTotalAuraMultiplierByMiscMask(), SpellInfo::Id, SPELL_AURA_MOD_THREAT, SPELL_SCHOOL_ARCANE, SPELL_SCHOOL_FIRE, SPELL_SCHOOL_FROST, SPELL_SCHOOL_HOLY, SPELL_SCHOOL_MASK_ARCANE, SPELL_SCHOOL_MASK_FIRE, SPELL_SCHOOL_MASK_FROST, SPELL_SCHOOL_MASK_HOLY, SPELL_SCHOOL_MASK_NATURE, SPELL_SCHOOL_MASK_NORMAL, SPELL_SCHOOL_MASK_SHADOW, SPELL_SCHOOL_NATURE, SPELL_SCHOOL_NORMAL, SPELL_SCHOOL_SHADOW, SPELLMOD_THREAT, and sSpellMgr.

Referenced by AddThreat().

◆ CanHaveThreatList() [1/2]

bool ThreatManager::CanHaveThreatList ( ) const
inline
109{ return _ownerCanHaveThreatList; }

Referenced by AddThreat(), Initialize(), and Update().

◆ CanHaveThreatList() [2/2]

bool ThreatManager::CanHaveThreatList ( Unit const *  who)
static
190{
191 if (!who)
192 return false;
193
194 Creature const* cWho = who->ToCreature();
195 // only creatures can have threat list
196 if (!cWho)
197 return false;
198
199 // pets, totems and triggers cannot have threat list
200 if (cWho->IsPet() || cWho->IsTotem() || cWho->IsTrigger())
201 return false;
202
203 // summons cannot have a threat list if they were summoned by a player
205 if (TempSummon const* tWho = cWho->ToTempSummon())
206 if (tWho->GetSummonerGUID().IsPlayer())
207 return false;
208
209 return true;
210}
@ UNIT_MASK_GUARDIAN
Definition UnitDefines.h:161
@ UNIT_MASK_MINION
Definition UnitDefines.h:160
Definition Creature.h:47
bool IsTrigger() const
Definition Creature.h:80
Creature * ToCreature()
Definition Object.h:206
Definition TemporarySummon.h:50
bool IsPet() const
Definition Unit.h:797
TempSummon * ToTempSummon()
Definition Unit.h:731
bool IsTotem() const
Definition Unit.h:799

References Unit::HasUnitTypeMask(), Unit::IsPet(), Unit::IsTotem(), Creature::IsTrigger(), Object::ToCreature(), Unit::ToTempSummon(), UNIT_MASK_GUARDIAN, and UNIT_MASK_MINION.

Referenced by Unit::CanHaveThreatList(), and debug_commandscript::HandleDebugThreatListCommand().

◆ ClearAllThreat()

void ThreatManager::ClearAllThreat ( )
576{
577 if (!_myThreatListEntries.empty())
578 {
580 do
581 _myThreatListEntries.begin()->second->UnregisterAndFree();
582 while (!_myThreatListEntries.empty());
583 }
584}
void SendClearAllThreatToClients() const
Definition ThreatManager.cpp:856

References _myThreatListEntries, and SendClearAllThreatToClients().

Referenced by TestCreature::CleanupCombatState(), boss_eadric::boss_eadricAI::DamageTaken(), boss_paletress::boss_paletressAI::DamageTaken(), boss_grand_champion::boss_grand_championAI::DamageTaken(), npc_magister_aledis::DamageTaken(), npc_tapoke_slim_jahn::npc_tapoke_slim_jahnAI::DamageTaken(), npc_dark_nucleus::npc_dark_nucleusAI::DamageTaken(), npc_crok_scourgebane::npc_crok_scourgebaneAI::DoAction(), npc_spark_of_ionar::DoAction(), npc_taskmaster_fizzule::npc_taskmaster_fizzuleAI::DoFriend(), npc_unkor_the_ruthless::npc_unkor_the_ruthlessAI::DoNice(), CombatManager::EndAllPvECombat(), npc_tirion_fordring_tft::npc_tirion_fordringAI::EnterEvadeMode(), GuardAI::EnterEvadeMode(), boss_doomrel::boss_doomrelAI::EnterEvadeMode(), npc_varian_wrynn::npc_varian_wrynnAI::EnterEvadeMode(), npc_thrall_bfu::npc_thrall_bfuAI::EnterEvadeMode(), npc_pos_freed_slave::npc_pos_freed_slaveAI::EnterEvadeMode(), npc_high_overlord_saurfang_igb::npc_high_overlord_saurfang_igbAI::EnterEvadeMode(), npc_muradin_bronzebeard_igb::npc_muradin_bronzebeard_igbAI::EnterEvadeMode(), gunship_npc_AI::EnterEvadeMode(), npc_gunship_boarding_addAI::EnterEvadeMode(), npc_terenas_menethil::npc_terenas_menethilAI::EnterEvadeMode(), violet_hold_trashAI::EnterEvadeMode(), npc_pet_hunter_snake_trap::EnterEvadeMode(), npc_escortAI::EnterEvadeMode(), FollowerAI::EnterEvadeMode(), npc_crystalline_frayer::EnterSeedPod(), npc_raging_flames::FixateRandomTarget(), spell_q11919_q11940_drake_hunt_aura::HandleEffectRemove(), PetAI::HandleReturnMovement(), boss_urom::boss_uromAI::LeaveCombat(), spell_halion_twilight_phasing_aura::OnApply(), spell_halion_twilight_phasing_aura::OnRemove(), spell_putricide_ooze_channel::StartAttack(), npc_highlord_darion_mograine::npc_highlord_darion_mograineAI::UpdateAI(), npc_snobold_vassal::npc_snobold_vassalAI::UpdateAI(), boss_malygos::UpdateAI(), and npc_aeranas::npc_aeranasAI::UpdateAI().

◆ ClearFixate()

void ThreatManager::ClearFixate ( )
inline
167{ FixateTarget(nullptr); }
void FixateTarget(Unit *target)
Definition ThreatManager.cpp:586

◆ ClearThreat() [1/2]

void ThreatManager::ClearThreat ( ThreatReference ref)
568{
570 ref->UnregisterAndFree();
572 UpdateVictim();
573}
void SendRemoveToClients(Unit const *victim) const
Definition ThreatManager.cpp:863
void UnregisterAndFree()
Definition ThreatManager.cpp:160
Unit *const _victim
Definition ThreatManager.h:310

References _currentVictimRef, ThreatReference::_victim, SendRemoveToClients(), ThreatReference::UnregisterAndFree(), and UpdateVictim().

◆ ClearThreat() [2/2]

void ThreatManager::ClearThreat ( Unit target)
561{
562 auto it = _myThreatListEntries.find(target->GetGUID());
563 if (it != _myThreatListEntries.end())
564 ClearThreat(it->second);
565}
void ClearThreat(Unit *target)
Definition ThreatManager.cpp:560

References _myThreatListEntries, ClearThreat(), and Object::GetGUID().

Referenced by ThreatReference::ClearThreat(), ClearThreat(), CombatReference::EndCombat(), UnitAI::EvadeTimerExpired(), and boss_gothik::boss_gothikAI::UpdateAI().

◆ CompareReferencesLT()

bool ThreatManager::CompareReferencesLT ( ThreatReference const *  a,
ThreatReference const *  b,
float  aWeight 
)
staticprivate
691{
692 if (a->_online != b->_online) // online state precedence (ONLINE > SUPPRESSED > OFFLINE)
693 return a->_online < b->_online;
694 if (a->_taunted != b->_taunted) // taunt state precedence (TAUNT > NONE > DETAUNT)
695 return a->_taunted < b->_taunted;
696 return (a->GetThreat() * aWeight < b->GetThreat());
697}
float GetThreat(Unit const *who, bool includeOffline=false) const
Definition ThreatManager.cpp:286

References ThreatReference::_online, ThreatReference::_taunted, ThreatReference::GetThreat(), and GetThreat().

Referenced by CompareThreatLessThan::operator()(), and ReselectVictim().

◆ EvaluateSuppressed()

void ThreatManager::EvaluateSuppressed ( bool  canExpire = false)
371{
372 for (auto const& pair : _threatenedByMe)
373 {
374 bool const shouldBeSuppressed = pair.second->ShouldBeSuppressed();
375 if (pair.second->IsOnline() && shouldBeSuppressed)
376 {
377 pair.second->_online = ThreatReference::ONLINE_STATE_SUPPRESSED;
378 pair.second->HeapNotifyDecreased();
379 }
380 else if (canExpire && pair.second->IsSuppressed() && !shouldBeSuppressed)
381 {
382 pair.second->_online = ThreatReference::ONLINE_STATE_ONLINE;
383 pair.second->HeapNotifyIncreased();
384 }
385 }
386}

References _threatenedByMe, ThreatReference::ONLINE_STATE_ONLINE, and ThreatReference::ONLINE_STATE_SUPPRESSED.

Referenced by Spell::EffectSanctuary(), AuraEffect::HandleAuraModDmgImmunity(), AuraEffect::HandleAuraModSchoolImmunity(), AuraEffect::HandleAuraModStun(), AuraEffect::HandleModConfuse(), Player::SetInWater(), and TauntUpdate().

◆ FixateTarget()

void ThreatManager::FixateTarget ( Unit target)
587{
588 if (target)
589 {
590 auto it = _myThreatListEntries.find(target->GetGUID());
591 if (it != _myThreatListEntries.end())
592 {
593 _fixateRef = it->second;
594 return;
595 }
596 }
597 _fixateRef = nullptr;
598}

References _fixateRef, _myThreatListEntries, and Object::GetGUID().

◆ ForwardThreatForAssistingMe()

void ThreatManager::ForwardThreatForAssistingMe ( Unit assistant,
float  baseAmount,
SpellInfo const *  spell = nullptr,
bool  ignoreModifiers = false 
)

== AFFECT OTHERS' THREAT LISTS ==

756{
757 if (spell && spell->HasAttribute(SPELL_ATTR1_NO_THREAT)) // shortcut, none of the calls would do anything
758 return;
759 if (_threatenedByMe.empty())
760 return;
761
762 std::vector<Creature*> canBeThreatened, cannotBeThreatened;
763 for (auto const& pair : _threatenedByMe)
764 {
765 Creature* owner = pair.second->GetOwner();
767 canBeThreatened.push_back(owner);
768 else
769 cannotBeThreatened.push_back(owner);
770 }
771
772 if (!canBeThreatened.empty()) // targets under CC cannot gain assist threat - split evenly among the rest
773 {
774 float const perTarget = baseAmount / canBeThreatened.size();
775 for (Creature* threatened : canBeThreatened)
776 threatened->GetThreatMgr().AddThreat(assistant, perTarget, spell, ignoreModifiers);
777 }
778
779 for (Creature* threatened : cannotBeThreatened)
780 threatened->GetThreatMgr().AddThreat(assistant, 0.0f, spell, true);
781}
@ UNIT_STATE_CONTROLLED
Definition UnitDefines.h:218
Unit * GetOwner() const
Definition Unit.cpp:7619
bool HasUnitState(const uint32 f) const
Definition Unit.h:736

References _threatenedByMe, AddThreat(), Unit::GetOwner(), Unit::GetThreatMgr(), SpellInfo::HasAttribute(), Unit::HasUnitState(), SPELL_ATTR1_NO_THREAT, and UNIT_STATE_CONTROLLED.

Referenced by Spell::DoAllEffectOnTarget(), Spell::DoSpellHitOnUnit(), Spell::EffectDispel(), Spell::EffectDispelMechanic(), Unit::EnergizeBySpell(), AuraEffect::HandleObsModPowerAuraTick(), AuraEffect::HandlePeriodicEnergizeAuraTick(), AuraEffect::HandlePeriodicHealAurasTick(), AuraEffect::HandlePeriodicHealthLeechAuraTick(), and Spell::HandleThreatSpells().

◆ GetAnyTarget()

Unit * ThreatManager::GetAnyTarget ( ) const
260{
261 for (ThreatReference const* ref : *_sortedThreatList)
262 if (!ref->IsOffline())
263 return ref->GetVictim();
264 return nullptr;
265}

References _sortedThreatList, and Unit::GetVictim().

◆ GetCurrentVictim()

◆ GetFixateTarget()

Unit * ThreatManager::GetFixateTarget ( ) const
601{
602 if (_fixateRef)
603 return _fixateRef->GetVictim();
604 else
605 return nullptr;
606}

References _fixateRef, and ThreatReference::GetVictim().

Referenced by debug_commandscript::HandleDebugThreatListCommand().

◆ GetLastVictim()

Unit * ThreatManager::GetLastVictim ( ) const

◆ GetModifiableThreatList()

std::vector< ThreatReference * > ThreatManager::GetModifiableThreatList ( )
343{
344 std::vector<ThreatReference*> list;
345 list.reserve(_myThreatListEntries.size());
346 for (auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end(); it != end; ++it)
347 list.push_back(const_cast<ThreatReference*>(*it));
348 return list;
349}

References _myThreatListEntries, and _sortedThreatList.

Referenced by SmartScript::ProcessAction(), and Unit::SetPhaseMask().

◆ GetOwner()

Unit * ThreatManager::GetOwner ( ) const
inline
107{ return _owner; }

◆ GetSortedThreatList()

Acore::IteratorPair< ThreatManager::ThreatListIterator > ThreatManager::GetSortedThreatList ( ) const
328{
329 auto itr = _sortedThreatList->ordered_begin();
330 auto end = _sortedThreatList->ordered_end();
331 std::function<ThreatReference const* ()> generator = [itr, end]() mutable -> ThreatReference const*
332 {
333 if (itr == end)
334 return nullptr;
335
336 return *(itr++);
337 };
338 std::function<ThreatReference const* ()> endGenerator = []() -> ThreatReference const* { return nullptr; };
339 return { ThreatListIterator{ std::move(generator) }, ThreatListIterator{ std::move(endGenerator) } };
340}

References _sortedThreatList.

Referenced by boss_hazzarah::CanAIAttack(), boss_renataki::boss_renatakiAI::CanAIAttack(), debug_commandscript::HandleDebugThreatListCommand(), UnitAI::SelectTargetList(), and boss_patchwerk::boss_patchwerkAI::UpdateAI().

◆ GetThreat()

float ThreatManager::GetThreat ( Unit const *  who,
bool  includeOffline = false 
) const

◆ GetThreatenedByMeList()

◆ GetThreatListPlayerCount()

uint32 ThreatManager::GetThreatListPlayerCount ( bool  includeOffline = false) const
300{
301 uint32 returnValue = 0;
302 for (ThreatReference const* ref : *_sortedThreatList)
303 {
304 if (!includeOffline && !ref->IsAvailable())
305 continue;
306 if (ref->GetVictim()->IsPlayer())
307 ++returnValue;
308 }
309 return returnValue;
310}
std::uint32_t uint32
Definition Define.h:107

References _sortedThreatList.

◆ GetThreatListSize()

◆ GetUnsortedThreatList()

Acore::IteratorPair< ThreatManager::ThreatListIterator > ThreatManager::GetUnsortedThreatList ( ) const
313{
314 auto itr = _myThreatListEntries.begin();
315 auto end = _myThreatListEntries.end();
316 std::function<ThreatReference const* ()> generator = [itr, end]() mutable -> ThreatReference const*
317 {
318 if (itr == end)
319 return nullptr;
320
321 return (itr++)->second;
322 };
323 std::function<ThreatReference const* ()> endGenerator = []() -> ThreatReference const* { return nullptr; };
324 return { ThreatListIterator{ std::move(generator) }, ThreatListIterator{ std::move(endGenerator) } };
325}

References _myThreatListEntries, and Acore::IteratorPair< iterator >::begin().

Referenced by boss_lady_deathwhisper::boss_lady_deathwhisperAI::DamageTaken(), boss_ysondre::boss_ysondreAI::DamageTaken(), UnitAI::DoAddAuraToAllHostilePlayers(), UnitAI::DoCastToAllHostilePlayers(), boss_faction_championsAI::EnemiesInRange(), boss_supremus::FindHatefulStrikeTarget(), SmartScript::GetTargets(), spell_kaelthas_nether_beam::HandleScriptEffect(), boss_thaddius::boss_thaddiusAI::IsAnyPlayerInMeleeRange(), NPCStaveQuestAI::IsFairFight(), boss_hadronox::IsInCombatWithPlayer(), boss_attumen::IsSummonedBy(), boss_blackheart_the_inciter::JustEngagedWith(), spell_malygos_vortex_visual::OnRemove(), SmartScript::ProcessEvent(), boss_priestess_lackey_commonAI::RecalculateThreat(), boss_faction_championsAI::RecalculateThreat(), boss_faction_championsAI::SelectEnemyCaster(), UnitAI::SelectTargetList(), npc_scholomance_occultist::npc_scholomance_occultistAI::SelectUnitCasting(), npc_frostwing_vrykul::npc_frostwing_vrykulAI::SpellHitTarget(), NPCStaveQuestAI::StorePlayerGUID(), boss_nefarian::UpdateAI(), boss_mandokir::boss_mandokirAI::UpdateAI(), boss_renataki::boss_renatakiAI::UpdateAI(), npc_green_dragon_combat_trigger::npc_green_dragon_combat_triggerAI::UpdateAI(), boss_gothik::boss_gothikAI::UpdateAI(), boss_kelthuzad::boss_kelthuzadAI::UpdateAI(), boss_sapphiron::boss_sapphironAI::UpdateAI(), boss_the_lurker_below::UpdateAI(), and instance_eye_of_eternity::VortexHandling().

◆ HasRedirects()

bool ThreatManager::HasRedirects ( ) const
inline
190{ return !_redirectRegistry.empty(); }
std::unordered_map< uint32, std::unordered_map< ObjectGuid, uint32 > > _redirectRegistry
Definition ThreatManager.h:232

Referenced by spell_hun_misdirection::CheckProc().

◆ Initialize()

◆ IsThreatenedBy() [1/2]

bool ThreatManager::IsThreatenedBy ( ObjectGuid const &  who,
bool  includeOffline = false 
) const
278{
279 auto it = _myThreatListEntries.find(who);
280 if (it == _myThreatListEntries.end())
281 return false;
282 return (includeOffline || it->second->IsAvailable());
283}

References _myThreatListEntries.

Referenced by UnitAI::EvadeTimerExpired(), Unit::IsThreatenedBy(), and IsThreatenedBy().

◆ IsThreatenedBy() [2/2]

bool ThreatManager::IsThreatenedBy ( Unit const *  who,
bool  includeOffline = false 
) const
284{ return IsThreatenedBy(who->GetGUID(), includeOffline); }
bool IsThreatenedBy(ObjectGuid const &who, bool includeOffline=false) const
Definition ThreatManager.cpp:277

References Object::GetGUID(), and IsThreatenedBy().

◆ IsThreateningAnyone()

bool ThreatManager::IsThreateningAnyone ( bool  includeOffline = false) const
352{
353 if (includeOffline)
354 return !_threatenedByMe.empty();
355 for (auto const& pair : _threatenedByMe)
356 if (pair.second->IsAvailable())
357 return true;
358 return false;
359}

References _threatenedByMe.

Referenced by WorldSession::HandleMoveWorldportAck().

◆ IsThreateningTo() [1/2]

bool ThreatManager::IsThreateningTo ( ObjectGuid const &  who,
bool  includeOffline = false 
) const
362{
363 auto it = _threatenedByMe.find(who);
364 if (it == _threatenedByMe.end())
365 return false;
366 return (includeOffline || it->second->IsAvailable());
367}

References _threatenedByMe.

Referenced by IsThreateningTo().

◆ IsThreateningTo() [2/2]

bool ThreatManager::IsThreateningTo ( Unit const *  who,
bool  includeOffline = false 
) const
368{ return IsThreateningTo(who->GetGUID(), includeOffline); }
bool IsThreateningTo(ObjectGuid const &who, bool includeOffline=false) const
Definition ThreatManager.cpp:361

References Object::GetGUID(), and IsThreateningTo().

◆ IsThreatListEmpty()

◆ MatchUnitThreatToHighestThreat()

void ThreatManager::MatchUnitThreatToHighestThreat ( Unit target)
503{
504 if (_sortedThreatList->empty())
505 return;
506
507 auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end();
508 ThreatReference const* highest = *it;
509 if (!highest->IsAvailable())
510 return;
511
512 if (highest->IsTaunting() && ((++it) != end)) // might need to skip this - max threat could be the preceding element (there is only one taunt element)
513 {
514 ThreatReference const* a = *it;
515 if (a->IsAvailable() && a->GetThreat() > highest->GetThreat())
516 highest = a;
517 }
518
519 AddThreat(target, highest->GetThreat() - GetThreat(target, true), nullptr, true, true);
520}
bool IsTaunting() const
Definition ThreatManager.h:279
float GetThreat() const
Definition ThreatManager.h:272

References _sortedThreatList, AddThreat(), ThreatReference::GetThreat(), GetThreat(), ThreatReference::IsAvailable(), and ThreatReference::IsTaunting().

Referenced by Spell::EffectTaunt().

◆ ModifyThreatByPercent()

◆ operator=()

ThreatManager & ThreatManager::operator= ( ThreatManager const &  )
delete

◆ ProcessAIUpdates()

void ThreatManager::ProcessAIUpdates ( )
private
679{
681 std::vector<ObjectGuid> v(std::move(_needsAIUpdate)); // _needsAIUpdate is now empty in case this triggers a recursive call
682 if (!ai)
683 return;
684 for (ObjectGuid const& guid : v)
685 if (ThreatReference const* ref = Acore::Containers::MapGetValuePtr(_myThreatListEntries, guid))
686 ai->JustStartedThreateningMe(ref->GetVictim());
687}
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:85
Definition CreatureAI.h:69
Definition ObjectGuid.h:118
std::vector< ObjectGuid > _needsAIUpdate
Definition ThreatManager.h:216
auto MapGetValuePtr(M &map, typename M::key_type const &key) -> decltype(AddressOrSelf(map.find(key) ->second))
Definition Containers.h:216
Definition AsioHacksFwd.h:47

References _myThreatListEntries, _needsAIUpdate, _owner, ASSERT_NOTNULL, CreatureAI::JustStartedThreateningMe(), Acore::Containers::MapGetValuePtr(), and Object::ToCreature().

Referenced by AddThreat(), and UpdateVictim().

◆ PurgeThreatenedByMeRef()

void ThreatManager::PurgeThreatenedByMeRef ( ObjectGuid const &  guid)
private
924{
925 auto it = _threatenedByMe.find(guid);
926 if (it != _threatenedByMe.end())
927 _threatenedByMe.erase(it);
928}

References _threatenedByMe.

Referenced by ThreatReference::UnregisterAndFree().

◆ PurgeThreatListRef()

void ThreatManager::PurgeThreatListRef ( ObjectGuid const &  guid)
private
902{
903 auto it = _myThreatListEntries.find(guid);
904 if (it == _myThreatListEntries.end())
905 return;
906 ThreatReference* ref = it->second;
907 _myThreatListEntries.erase(it);
908 _sortedThreatList->erase(static_cast<ThreatReferenceImpl*>(ref)->_handle);
909
910 if (_fixateRef == ref)
911 _fixateRef = nullptr;
912 if (_currentVictimRef == ref)
913 _currentVictimRef = nullptr;
914}
Definition ThreatManager.cpp:168

References _currentVictimRef, _fixateRef, _myThreatListEntries, and _sortedThreatList.

Referenced by ThreatReference::UnregisterAndFree().

◆ PutThreatenedByMeRef()

void ThreatManager::PutThreatenedByMeRef ( ObjectGuid const &  guid,
ThreatReference ref 
)
private

== OTHERS' THREAT LISTS ==

917{
918 auto& inMap = _threatenedByMe[guid];
919 ASSERT(!inMap, "Duplicate threatened-by-me reference at %p being inserted on %s for %s - memory leak!", (void*)ref, _owner->GetGUID().ToString().c_str(), guid.ToString().c_str());
920 inMap = ref;
921}

References _owner, _threatenedByMe, ASSERT, Object::GetGUID(), and ObjectGuid::ToString().

Referenced by AddThreat().

◆ PutThreatListRef()

void ThreatManager::PutThreatListRef ( ObjectGuid const &  guid,
ThreatReference ref 
)
private

== MY THREAT LIST ==

893{
894 _needClientUpdate = true;
895 auto& inMap = _myThreatListEntries[guid];
896 ASSERT(!inMap, "Duplicate threat reference at %p being inserted on %s for %s - memory leak!", (void*)ref, _owner->GetGUID().ToString().c_str(), guid.ToString().c_str());
897 inMap = ref;
898 static_cast<ThreatReferenceImpl*>(ref)->_handle = _sortedThreatList->push(ref);
899}

References _myThreatListEntries, _needClientUpdate, _owner, _sortedThreatList, ASSERT, Object::GetGUID(), and ObjectGuid::ToString().

Referenced by AddThreat().

◆ RegisterForAIUpdate()

void ThreatManager::RegisterForAIUpdate ( ObjectGuid const &  guid)
inlineprivate
215{ _needsAIUpdate.push_back(guid); }

Referenced by ThreatReference::UpdateOffline().

◆ RegisterRedirectThreat()

void ThreatManager::RegisterRedirectThreat ( uint32  spellId,
ObjectGuid const &  victim,
uint32  pct 
)

== REDIRECT SYSTEM ==

827{
828 _redirectRegistry[spellId][victim] = pct;
830}
void UpdateRedirectInfo()
Definition ThreatManager.cpp:930

References _redirectRegistry, and UpdateRedirectInfo().

Referenced by Spell::EffectRedirectThreat().

◆ RemoveMeFromThreatLists()

void ThreatManager::RemoveMeFromThreatLists ( )

◆ ReselectVictim()

ThreatReference const * ThreatManager::ReselectVictim ( )
private
624{
625 if (_sortedThreatList->empty())
626 return nullptr;
627
628 for (auto const& pair : _myThreatListEntries)
629 pair.second->UpdateOffline(); // AI notifies are processed in ::UpdateVictim caller
630
631 // fixated target is always preferred
633 return _fixateRef;
634
635 ThreatReference const* oldVictimRef = _currentVictimRef;
636 if (oldVictimRef && oldVictimRef->IsOffline())
637 oldVictimRef = nullptr;
638 // in 99% of cases - we won't need to actually look at anything beyond the first element
639 ThreatReference const* highest = _sortedThreatList->top();
640
641 // if the highest reference is offline, the entire list is offline, and we indicate this
642 if (!highest->IsAvailable())
643 return nullptr;
644 // if we have no old victim, or old victim is still highest, then highest is our target and we're done
645 if (!oldVictimRef || highest == oldVictimRef)
646 return highest;
647 // if highest threat doesn't break 110% of old victim, nothing below it is going to do so either; new victim = old victim and done
648 if (!ThreatManager::CompareReferencesLT(oldVictimRef, highest, 1.1f))
649 return oldVictimRef;
650 // if highest threat breaks 130%, it's our new target regardless of range (and we're done)
651 if (ThreatManager::CompareReferencesLT(oldVictimRef, highest, 1.3f))
652 return highest;
653 // if it doesn't break 130%, we need to check if it's melee - if yes, it breaks 110% (we checked earlier) and is our new target
654 if (_owner->IsWithinMeleeRange(highest->_victim))
655 return highest;
656 // If we get here, highest threat is ranged, but below 130% of current - there might be a melee that breaks 110% below us somewhere
657 auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end();
658 while (it != end)
659 {
660 ThreatReference const* next = *it;
661 // if we've found current victim, we're done (nothing above is higher, and nothing below can be higher)
662 if (next == oldVictimRef)
663 return next;
664 // if next isn't above 110% threat, then nothing below it can be either - we're done, old victim stays
665 if (!ThreatManager::CompareReferencesLT(oldVictimRef, next, 1.1f))
666 return oldVictimRef;
667 // if next is melee, he's above 110% and our new victim
669 return next;
670 // otherwise the next highest target may still be a melee above 110% and we need to look further
671 ++it;
672 }
673 // we should have found the old victim at some point in the loop above
674 ASSERT(false && "Current victim not found in sorted threat list even though it has a reference - manager desync!");
675 return nullptr;
676}
static bool CompareReferencesLT(ThreatReference const *a, ThreatReference const *b, float aWeight)
Definition ThreatManager.cpp:690
bool IsOffline() const
Definition ThreatManager.h:277
bool IsWithinMeleeRange(Unit const *obj, float dist=0.f) const
Definition Unit.cpp:768

References _currentVictimRef, _fixateRef, _myThreatListEntries, _owner, _sortedThreatList, ThreatReference::_victim, ASSERT, CompareReferencesLT(), ThreatReference::IsAvailable(), ThreatReference::IsOffline(), Unit::IsWithinMeleeRange(), and ThreatReference::UpdateOffline().

Referenced by UpdateVictim().

◆ ResetAllMyThreatOnOthers()

void ThreatManager::ResetAllMyThreatOnOthers ( )
784{
785 for (auto const& pair : _threatenedByMe)
786 pair.second->ScaleThreat(0.0f);
787}

References _threatenedByMe.

◆ ResetAllRedirects()

void ThreatManager::ResetAllRedirects ( )
inline

◆ ResetAllThreat()

◆ ResetThreat()

◆ ScaleThreat()

void ThreatManager::ScaleThreat ( Unit target,
float  factor 
)
496{
497 auto it = _myThreatListEntries.find(target->GetGUID());
498 if (it != _myThreatListEntries.end())
499 it->second->ScaleThreat(std::max<float>(factor, 0.0f));
500}

References _myThreatListEntries, and Object::GetGUID().

◆ SendClearAllThreatToClients()

void ThreatManager::SendClearAllThreatToClients ( ) const
private
857{
859 data << _owner->GetPackGUID();
860 _owner->SendMessageToSet(&data, false);
861}
PackedGuid const & GetPackGUID() const
Definition Object.h:116
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:2108
Definition WorldPacket.h:26
@ SMSG_THREAT_CLEAR
Definition Opcodes.h:1187

References _owner, Object::GetPackGUID(), WorldObject::SendMessageToSet(), and SMSG_THREAT_CLEAR.

Referenced by ClearAllThreat().

◆ SendRemoveToClients()

void ThreatManager::SendRemoveToClients ( Unit const *  victim) const
private
864{
866 data << _owner->GetPackGUID();
867 data << victim->GetPackGUID();
868 _owner->SendMessageToSet(&data, false);
869}
@ SMSG_THREAT_REMOVE
Definition Opcodes.h:1186

References _owner, Object::GetPackGUID(), WorldObject::SendMessageToSet(), and SMSG_THREAT_REMOVE.

Referenced by ClearThreat(), and ThreatReference::UpdateOffline().

◆ SendThreatListToClients()

void ThreatManager::SendThreatListToClients ( bool  newHighest) const
private
872{
873 WorldPacket data(newHighest ? SMSG_HIGHEST_THREAT_UPDATE : SMSG_THREAT_UPDATE, (_sortedThreatList->size() + 2) * 8); // guess
874 data << _owner->GetPackGUID();
875 if (newHighest)
877 size_t countPos = data.wpos();
878 data << uint32(0); // placeholder
879 uint32 count = 0;
880 for (ThreatReference const* ref : *_sortedThreatList)
881 {
882 if (!ref->IsAvailable())
883 continue;
884 data << ref->GetVictim()->GetPackGUID();
885 data << uint32(ref->GetThreat() * 100);
886 ++count;
887 }
888 data.put<uint32>(countPos, count);
889 _owner->SendMessageToSet(&data, false);
890}
std::size_t wpos() const
Definition ByteBuffer.h:330
void put(std::size_t pos, T value)
Definition ByteBuffer.h:137
@ SMSG_THREAT_UPDATE
Definition Opcodes.h:1185
@ SMSG_HIGHEST_THREAT_UPDATE
Definition Opcodes.h:1184

References _currentVictimRef, _owner, _sortedThreatList, Object::GetPackGUID(), ThreatReference::GetVictim(), ByteBuffer::put(), WorldObject::SendMessageToSet(), SMSG_HIGHEST_THREAT_UPDATE, SMSG_THREAT_UPDATE, and ByteBuffer::wpos().

Referenced by UpdateVictim().

◆ SetTauntStateForTesting()

void ThreatManager::SetTauntStateForTesting ( Unit target,
uint32  state 
)
547{
548 auto it = _myThreatListEntries.find(target->GetGUID());
549 if (it != _myThreatListEntries.end())
550 it->second->UpdateTauntState(
551 static_cast<ThreatReference::TauntState>(state));
552}
TauntState
Definition ThreatManager.h:267

References _myThreatListEntries, and Object::GetGUID().

◆ TauntUpdate()

void ThreatManager::TauntUpdate ( )
523{
525
527 std::unordered_map<ObjectGuid, ThreatReference::TauntState> tauntStates;
528 // Only the last taunt effect applied by something still on our threat list is considered
529 for (auto it = tauntEffects.begin(), end = tauntEffects.end(); it != end; ++it)
530 tauntStates[(*it)->GetCasterGUID()] = ThreatReference::TauntState(state++);
531
532 for (auto const& pair : _myThreatListEntries)
533 {
534 auto it = tauntStates.find(pair.first);
535 if (it != tauntStates.end())
536 pair.second->UpdateTauntState(it->second);
537 else
538 pair.second->UpdateTauntState();
539 }
540
541 // taunt aura update also re-evaluates all suppressed states (retail behavior)
542 EvaluateSuppressed(true);
543}
@ SPELL_AURA_MOD_TAUNT
Definition SpellAuraDefines.h:74
void EvaluateSuppressed(bool canExpire=false)
Definition ThreatManager.cpp:370
@ TAUNT_STATE_TAUNT
Definition ThreatManager.h:267
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1428
std::vector< AuraEffect * > AuraEffectList
Definition Unit.h:680

References _myThreatListEntries, _owner, EvaluateSuppressed(), Unit::GetAuraEffectsByType(), SPELL_AURA_MOD_TAUNT, and ThreatReference::TAUNT_STATE_TAUNT.

Referenced by AuraEffect::HandleModDetaunt(), and AuraEffect::HandleModTaunt().

◆ UnregisterRedirectThreat() [1/2]

◆ UnregisterRedirectThreat() [2/2]

void ThreatManager::UnregisterRedirectThreat ( uint32  spellId,
ObjectGuid const &  victim 
)
842{
843 auto it = _redirectRegistry.find(spellId);
844 if (it == _redirectRegistry.end())
845 return;
846 auto& victimMap = it->second;
847 auto it2 = victimMap.find(victim);
848 if (it2 == victimMap.end())
849 return;
850 victimMap.erase(it2);
851 if (victimMap.empty())
852 _redirectRegistry.erase(it);
854}

References _redirectRegistry, and UpdateRedirectInfo().

◆ Update()

void ThreatManager::Update ( uint32  tdiff)
232{
233 if (!CanHaveThreatList() || IsThreatListEmpty(true))
234 return;
235 if (_updateTimer <= tdiff)
236 {
237 UpdateVictim();
239 }
240 else
241 _updateTimer -= tdiff;
242}
bool IsThreatListEmpty(bool includeOffline=false) const
Definition ThreatManager.cpp:267

References _updateTimer, CanHaveThreatList(), IsThreatListEmpty(), THREAT_UPDATE_INTERVAL, and UpdateVictim().

Referenced by Creature::Update().

◆ UpdateMySpellSchoolModifiers()

void ThreatManager::UpdateMySpellSchoolModifiers ( )
820{
821 for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
823 _multiSchoolModifiers.clear();
824}
std::uint8_t uint8
Definition Define.h:109
float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
Definition Unit.cpp:6247

References _multiSchoolModifiers, _owner, _singleSchoolModifiers, Unit::GetTotalAuraMultiplierByMiscMask(), MAX_SPELL_SCHOOL, and SPELL_AURA_MOD_THREAT.

Referenced by AuraEffect::HandleModThreat().

◆ UpdateMyTempModifiers()

void ThreatManager::UpdateMyTempModifiers ( )
799{
800 int32 mod = 0;
801 for (AuraEffect const* eff : _owner->GetAuraEffectsByType(SPELL_AURA_MOD_TOTAL_THREAT))
802 mod += eff->GetAmount();
803
804 if (_threatenedByMe.empty())
805 return;
806
807 auto it = _threatenedByMe.begin();
808 bool const isIncrease = (it->second->_tempModifier < mod);
809 do
810 {
811 it->second->_tempModifier = mod;
812 if (isIncrease)
813 it->second->HeapNotifyIncreased();
814 else
815 it->second->HeapNotifyDecreased();
816 } while ((++it) != _threatenedByMe.end());
817}
std::int32_t int32
Definition Define.h:103
@ SPELL_AURA_MOD_TOTAL_THREAT
Definition SpellAuraDefines.h:166
Definition SpellAuraEffects.h:39

References _owner, _threatenedByMe, Unit::GetAuraEffectsByType(), and SPELL_AURA_MOD_TOTAL_THREAT.

Referenced by AuraEffect::HandleAuraModTotalThreat().

◆ UpdateRedirectInfo()

void ThreatManager::UpdateRedirectInfo ( )
private
931{
932 _redirectInfo.clear();
933 uint32 totalPct = 0;
934 for (auto const& pair : _redirectRegistry) // (spellid, victim -> pct)
935 for (auto const& victimPair : pair.second) // (victim,pct)
936 {
937 uint32 thisPct = std::min<uint32>(100 - totalPct, victimPair.second);
938 if (thisPct > 0)
939 {
940 _redirectInfo.push_back({ victimPair.first, thisPct });
941 totalPct += thisPct;
942 ASSERT(totalPct <= 100);
943 if (totalPct == 100)
944 return;
945 }
946 }
947}

References _redirectInfo, _redirectRegistry, and ASSERT.

Referenced by RegisterRedirectThreat(), UnregisterRedirectThreat(), and UnregisterRedirectThreat().

◆ UpdateVictim()

void ThreatManager::UpdateVictim ( )
private
609{
610 ThreatReference const* const newVictim = ReselectVictim();
611 bool const newHighest = newVictim && (newVictim != _currentVictimRef);
612
613 _currentVictimRef = newVictim;
614 if (newHighest || _needClientUpdate)
615 {
616 SendThreatListToClients(newHighest);
617 _needClientUpdate = false;
618 }
619
621}
void SendThreatListToClients(bool newHighest) const
Definition ThreatManager.cpp:871
ThreatReference const * ReselectVictim()
Definition ThreatManager.cpp:623

References _currentVictimRef, _needClientUpdate, ProcessAIUpdates(), ReselectVictim(), and SendThreatListToClients().

Referenced by AddThreat(), ClearThreat(), GetCurrentVictim(), and Update().

Friends And Related Symbol Documentation

◆ CompareThreatLessThan

friend struct CompareThreatLessThan
friend

◆ debug_commandscript

friend class debug_commandscript
friend

◆ ThreatReference

friend class ThreatReference
friend

◆ ThreatReferenceImpl

friend class ThreatReferenceImpl
friend

Referenced by AddThreat().

Member Data Documentation

◆ _currentVictimRef

◆ _fixateRef

ThreatReference const* ThreatManager::_fixateRef
private

◆ _multiSchoolModifiers

std::unordered_map<std::underlying_type<SpellSchoolMask>::type, float> ThreatManager::_multiSchoolModifiers
mutableprivate

◆ _myThreatListEntries

◆ _needClientUpdate

◆ _needsAIUpdate

std::vector<ObjectGuid> ThreatManager::_needsAIUpdate
private

Referenced by ProcessAIUpdates().

◆ _owner

◆ _ownerCanHaveThreatList

bool ThreatManager::_ownerCanHaveThreatList
private

Referenced by Initialize().

◆ _redirectInfo

std::vector<std::pair<ObjectGuid, uint32> > ThreatManager::_redirectInfo
private

◆ _redirectRegistry

std::unordered_map<uint32, std::unordered_map<ObjectGuid, uint32> > ThreatManager::_redirectRegistry
private

◆ _singleSchoolModifiers

std::array<float, MAX_SPELL_SCHOOL> ThreatManager::_singleSchoolModifiers
private

◆ _sortedThreatList

◆ _threatenedByMe

◆ _updateTimer

uint32 ThreatManager::_updateTimer
private

Referenced by Update().

◆ CompareThreat

const CompareThreatLessThan ThreatManager::CompareThreat
staticprivate

◆ THREAT_UPDATE_INTERVAL

const uint32 ThreatManager::THREAT_UPDATE_INTERVAL = 1000u
static

Referenced by Update().


The documentation for this class was generated from the following files: