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 UpdateVictimForTesting ()
 
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:212
static const uint32 THREAT_UPDATE_INTERVAL
Definition ThreatManager.h:94
std::array< float, MAX_SPELL_SCHOOL > _singleSchoolModifiers
Definition ThreatManager.h:229
std::unique_ptr< Heap > _sortedThreatList
Definition ThreatManager.h:213
ThreatReference const * _currentVictimRef
Definition ThreatManager.h:222
bool _ownerCanHaveThreatList
Definition ThreatManager.h:197
bool _needClientUpdate
Definition ThreatManager.h:211
Unit *const _owner
Definition ThreatManager.h:196
ThreatReference const * _fixateRef
Definition ThreatManager.h:223

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:228
std::unordered_map< ObjectGuid, ThreatReference * > _myThreatListEntries
Definition ThreatManager.h:214

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:704
std::vector< std::pair< ObjectGuid, uint32 > > _redirectInfo
Definition ThreatManager.h:233
void PutThreatListRef(ObjectGuid const &guid, ThreatReference *ref)
== MY THREAT LIST ==
Definition ThreatManager.cpp:897
void PutThreatenedByMeRef(ObjectGuid const &guid, ThreatReference *ref)
== OTHERS' THREAT LISTS ==
Definition ThreatManager.cpp:921
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:683
friend class ThreatReferenceImpl
Definition ThreatManager.h:261
void UpdateVictim()
Definition ThreatManager.cpp:613
Definition ThreatManager.h:267
void UpdateOffline()
Definition ThreatManager.cpp:75
void HeapNotifyIncreased()
Definition ThreatManager.cpp:179
@ ONLINE_STATE_ONLINE
Definition ThreatManager.h:270
@ ONLINE_STATE_SUPPRESSED
Definition ThreatManager.h:270
bool ShouldBeSuppressed() const
Definition ThreatManager.cpp:123
OnlineState GetOnlineState() const
Definition ThreatManager.h:275
bool IsOnline() const
Definition ThreatManager.h:276
OnlineState _online
Definition ThreatManager.h:313
void AddThreat(float amount)
Definition ThreatManager.cpp:51
Definition Unit.h:664
Unit * GetVehicleBase() const
Definition Unit.cpp:14996
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::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
705{
706 // modifiers by spell
707 if (spell)
708 {
709 if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(spell->Id))
710 if (threatEntry->pctMod != 1.0f) // flat/AP modifiers handled in Spell::HandleThreatSpells
711 threat *= threatEntry->pctMod;
712
713 if (Player* modOwner = victim->GetSpellModOwner())
714 modOwner->ApplySpellMod(spell->Id, SPELLMOD_THREAT, threat);
715 }
716
717 // modifiers by effect school
718 ThreatManager const& victimMgr = victim->GetThreatMgr();
719 SpellSchoolMask const mask = spell ? spell->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL;
720 switch (mask)
721 {
723 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_NORMAL];
724 break;
726 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_HOLY];
727 break;
729 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_FIRE];
730 break;
732 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_NATURE];
733 break;
735 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_FROST];
736 break;
738 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_SHADOW];
739 break;
741 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_ARCANE];
742 break;
743 default:
744 {
745 auto it = victimMgr._multiSchoolModifiers.find(mask);
746 if (it != victimMgr._multiSchoolModifiers.end())
747 {
748 threat *= it->second;
749 break;
750 }
751 float mod = victim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, mask);
752 victimMgr._multiSchoolModifiers[mask] = mod;
753 threat *= mod;
754 break;
755 }
756 }
757 return threat;
758}
@ 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:836
Definition Player.h:1084
Definition ThreatManager.h:90
std::unordered_map< std::underlying_type< SpellSchoolMask >::type, float > _multiSchoolModifiers
Definition ThreatManager.h:230
Player * GetSpellModOwner() const
Definition Unit.cpp:12951
Definition SpellMgr.h:375

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 ( )
581{
582 if (!_myThreatListEntries.empty())
583 {
585 do
586 _myThreatListEntries.begin()->second->UnregisterAndFree();
587 while (!_myThreatListEntries.empty());
588 }
589}
void SendClearAllThreatToClients() const
Definition ThreatManager.cpp:861

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_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(), CombatManager::EndAllPvECombat(), npc_tirion_fordring_tft::npc_tirion_fordringAI::EnterEvadeMode(), GuardAI::EnterEvadeMode(), boss_doomrel::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_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_unkor_the_ruthless::npc_unkor_the_ruthlessAI::Submit(), 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:591

Referenced by npc_pet_hunter_snake_trap::UpdateAI().

◆ ClearThreat() [1/2]

void ThreatManager::ClearThreat ( ThreatReference ref)
573{
575 ref->UnregisterAndFree();
577 UpdateVictim();
578}
void SendRemoveToClients(Unit const *victim) const
Definition ThreatManager.cpp:868
void UnregisterAndFree()
Definition ThreatManager.cpp:160
Unit *const _victim
Definition ThreatManager.h:312

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

◆ ClearThreat() [2/2]

void ThreatManager::ClearThreat ( Unit target)
566{
567 auto it = _myThreatListEntries.find(target->GetGUID());
568 if (it != _myThreatListEntries.end())
569 ClearThreat(it->second);
570}
void ClearThreat(Unit *target)
Definition ThreatManager.cpp:565

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

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

◆ CompareReferencesLT()

bool ThreatManager::CompareReferencesLT ( ThreatReference const *  a,
ThreatReference const *  b,
float  aWeight 
)
staticprivate
696{
697 if (a->_online != b->_online) // online state precedence (ONLINE > SUPPRESSED > OFFLINE)
698 return a->_online < b->_online;
699 if (a->_taunted != b->_taunted) // taunt state precedence (TAUNT > NONE > DETAUNT)
700 return a->_taunted < b->_taunted;
701 return (a->GetThreat() * aWeight < b->GetThreat());
702}
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)
592{
593 if (target)
594 {
595 auto it = _myThreatListEntries.find(target->GetGUID());
596 if (it != _myThreatListEntries.end())
597 {
598 _fixateRef = it->second;
599 return;
600 }
601 }
602 _fixateRef = nullptr;
603}

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

Referenced by npc_pet_hunter_snake_trap::UpdateAI().

◆ ForwardThreatForAssistingMe()

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

== AFFECT OTHERS' THREAT LISTS ==

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

Referenced by Creature::CallForHelp().

◆ GetCurrentVictim()

◆ GetFixateTarget()

Unit * ThreatManager::GetFixateTarget ( ) const
606{
607 if (_fixateRef)
608 return _fixateRef->GetVictim();
609 else
610 return nullptr;
611}

References _fixateRef, and ThreatReference::GetVictim().

Referenced by debug_commandscript::HandleDebugThreatListCommand(), and npc_pet_hunter_snake_trap::UpdateAI().

◆ 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(), and UnitAI::SelectTargetList().

◆ 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(), 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(), boss_kelthuzad::boss_kelthuzadAI::UpdateAI(), boss_sapphiron::boss_sapphironAI::UpdateAI(), and boss_the_lurker_below::UpdateAI().

◆ HasRedirects()

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

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()

bool ThreatManager::IsThreatListEmpty ( bool  includeOffline = false) const

◆ 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:281
float GetThreat() const
Definition ThreatManager.h:274

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
684{
686 std::vector<ObjectGuid> v(std::move(_needsAIUpdate)); // _needsAIUpdate is now empty in case this triggers a recursive call
687 if (!ai)
688 return;
689 for (ObjectGuid const& guid : v)
690 if (ThreatReference const* ref = Acore::Containers::MapGetValuePtr(_myThreatListEntries, guid))
691 ai->JustStartedThreateningMe(ref->GetVictim());
692}
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:85
Definition CreatureAI.h:69
Definition ObjectGuid.h:118
std::vector< ObjectGuid > _needsAIUpdate
Definition ThreatManager.h:218
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
929{
930 auto it = _threatenedByMe.find(guid);
931 if (it != _threatenedByMe.end())
932 _threatenedByMe.erase(it);
933}

References _threatenedByMe.

Referenced by ThreatReference::UnregisterAndFree().

◆ PurgeThreatListRef()

void ThreatManager::PurgeThreatListRef ( ObjectGuid const &  guid)
private
907{
908 auto it = _myThreatListEntries.find(guid);
909 if (it == _myThreatListEntries.end())
910 return;
911 ThreatReference* ref = it->second;
912 _myThreatListEntries.erase(it);
913 _sortedThreatList->erase(static_cast<ThreatReferenceImpl*>(ref)->_handle);
914
915 if (_fixateRef == ref)
916 _fixateRef = nullptr;
917 if (_currentVictimRef == ref)
918 _currentVictimRef = nullptr;
919}
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 ==

922{
923 auto& inMap = _threatenedByMe[guid];
924 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());
925 inMap = ref;
926}

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 ==

898{
899 _needClientUpdate = true;
900 auto& inMap = _myThreatListEntries[guid];
901 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());
902 inMap = ref;
903 static_cast<ThreatReferenceImpl*>(ref)->_handle = _sortedThreatList->push(ref);
904}

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

Referenced by AddThreat().

◆ RegisterForAIUpdate()

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

Referenced by ThreatReference::UpdateOffline().

◆ RegisterRedirectThreat()

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

== REDIRECT SYSTEM ==

832{
833 _redirectRegistry[spellId][victim] = pct;
835}
void UpdateRedirectInfo()
Definition ThreatManager.cpp:935

References _redirectRegistry, and UpdateRedirectInfo().

Referenced by Spell::EffectRedirectThreat().

◆ RemoveMeFromThreatLists()

void ThreatManager::RemoveMeFromThreatLists ( )

◆ ReselectVictim()

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

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 ( )
789{
790 for (auto const& pair : _threatenedByMe)
791 pair.second->ScaleThreat(0.0f);
792}

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
862{
864 data << _owner->GetPackGUID();
865 _owner->SendMessageToSet(&data, false);
866}
PackedGuid const & GetPackGUID() const
Definition Object.h:116
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:2112
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
869{
871 data << _owner->GetPackGUID();
872 data << victim->GetPackGUID();
873 _owner->SendMessageToSet(&data, false);
874}
@ 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
877{
878 WorldPacket data(newHighest ? SMSG_HIGHEST_THREAT_UPDATE : SMSG_THREAT_UPDATE, (_sortedThreatList->size() + 2) * 8); // guess
879 data << _owner->GetPackGUID();
880 if (newHighest)
882 size_t countPos = data.wpos();
883 data << uint32(0); // placeholder
884 uint32 count = 0;
885 for (ThreatReference const* ref : *_sortedThreatList)
886 {
887 if (!ref->IsAvailable())
888 continue;
889 data << ref->GetVictim()->GetPackGUID();
890 data << uint32(ref->GetThreat() * 100);
891 ++count;
892 }
893 data.put<uint32>(countPos, count);
894 _owner->SendMessageToSet(&data, false);
895}
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 
)
552{
553 auto it = _myThreatListEntries.find(target->GetGUID());
554 if (it != _myThreatListEntries.end())
555 it->second->UpdateTauntState(
556 static_cast<ThreatReference::TauntState>(state));
557}
TauntState
Definition ThreatManager.h:269

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
544 // immediately reselect victim so taunt takes effect without waiting
545 // for the next THREAT_UPDATE_INTERVAL (1 s) timer tick
546 UpdateVictim();
548}
@ SPELL_AURA_MOD_TAUNT
Definition SpellAuraDefines.h:74
void EvaluateSuppressed(bool canExpire=false)
Definition ThreatManager.cpp:370
@ TAUNT_STATE_TAUNT
Definition ThreatManager.h:269
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1428
std::vector< AuraEffect * > AuraEffectList
Definition Unit.h:680

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

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

◆ UnregisterRedirectThreat() [1/2]

◆ UnregisterRedirectThreat() [2/2]

void ThreatManager::UnregisterRedirectThreat ( uint32  spellId,
ObjectGuid const &  victim 
)
847{
848 auto it = _redirectRegistry.find(spellId);
849 if (it == _redirectRegistry.end())
850 return;
851 auto& victimMap = it->second;
852 auto it2 = victimMap.find(victim);
853 if (it2 == victimMap.end())
854 return;
855 victimMap.erase(it2);
856 if (victimMap.empty())
857 _redirectRegistry.erase(it);
859}

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 ( )
825{
826 for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
828 _multiSchoolModifiers.clear();
829}
std::uint8_t uint8
Definition Define.h:109
float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
Definition Unit.cpp:6315

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

Referenced by AuraEffect::HandleModThreat().

◆ UpdateMyTempModifiers()

void ThreatManager::UpdateMyTempModifiers ( )
804{
805 int32 mod = 0;
806 for (AuraEffect const* eff : _owner->GetAuraEffectsByType(SPELL_AURA_MOD_TOTAL_THREAT))
807 mod += eff->GetAmount();
808
809 if (_threatenedByMe.empty())
810 return;
811
812 auto it = _threatenedByMe.begin();
813 bool const isIncrease = (it->second->_tempModifier < mod);
814 do
815 {
816 it->second->_tempModifier = mod;
817 if (isIncrease)
818 it->second->HeapNotifyIncreased();
819 else
820 it->second->HeapNotifyDecreased();
821 } while ((++it) != _threatenedByMe.end());
822}
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
936{
937 _redirectInfo.clear();
938 uint32 totalPct = 0;
939 for (auto const& pair : _redirectRegistry) // (spellid, victim -> pct)
940 for (auto const& victimPair : pair.second) // (victim,pct)
941 {
942 uint32 thisPct = std::min<uint32>(100 - totalPct, victimPair.second);
943 if (thisPct > 0)
944 {
945 _redirectInfo.push_back({ victimPair.first, thisPct });
946 totalPct += thisPct;
947 ASSERT(totalPct <= 100);
948 if (totalPct == 100)
949 return;
950 }
951 }
952}

References _redirectInfo, _redirectRegistry, and ASSERT.

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

◆ UpdateVictim()

void ThreatManager::UpdateVictim ( )
private
614{
615 ThreatReference const* const newVictim = ReselectVictim();
616 bool const newHighest = newVictim && (newVictim != _currentVictimRef);
617
618 _currentVictimRef = newVictim;
619 if (newHighest || _needClientUpdate)
620 {
621 SendThreatListToClients(newHighest);
622 _needClientUpdate = false;
623 }
624
626}
void SendThreatListToClients(bool newHighest) const
Definition ThreatManager.cpp:876
ThreatReference const * ReselectVictim()
Definition ThreatManager.cpp:628

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

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

◆ UpdateVictimForTesting()

void ThreatManager::UpdateVictimForTesting ( )
inline
186{ UpdateVictim(); }

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 TauntUpdate(), and Update().

◆ CompareThreat

const CompareThreatLessThan ThreatManager::CompareThreat
staticprivate

◆ THREAT_UPDATE_INTERVAL

const uint32 ThreatManager::THREAT_UPDATE_INTERVAL = 1000u
static

Referenced by TauntUpdate(), and Update().


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