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)
 
Unit * GetOwner () const
 
bool CanHaveThreatList () const
 
Unit * GetCurrentVictim ()
 
Unit * GetLastVictim () const
 
Unit * GetAnyTarget () 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< ThreatListIterator > GetUnsortedThreatList () const
 
Acore::IteratorPair< ThreatListIterator > GetSortedThreatList () 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 ()
 
Unit * GetFixateTarget () 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
 
ThreatManager & operator= (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)
217 _sortedThreatList(std::make_unique<Heap>()), _currentVictimRef(nullptr), _fixateRef(nullptr)
218{
219 for (int8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
220 _singleSchoolModifiers[i] = 1.0f;
221}
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 ( )
224{
225 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());
226 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());
227 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());
228}
#define ASSERT
Definition Errors.h:68
std::string ToString() const
Definition ObjectGuid.cpp:48
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:120
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 ==

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

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
709{
710 // modifiers by spell
711 if (spell)
712 {
713 if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(spell->Id))
714 if (threatEntry->pctMod != 1.0f) // flat/AP modifiers handled in Spell::HandleThreatSpells
715 threat *= threatEntry->pctMod;
716
717 if (Player* modOwner = victim->GetSpellModOwner())
718 modOwner->ApplySpellMod(spell->Id, SPELLMOD_THREAT, threat);
719 }
720
721 // modifiers by effect school
722 ThreatManager const& victimMgr = victim->GetThreatMgr();
723 SpellSchoolMask const mask = spell ? spell->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL;
724 switch (mask)
725 {
727 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_NORMAL];
728 break;
730 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_HOLY];
731 break;
733 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_FIRE];
734 break;
736 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_NATURE];
737 break;
739 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_FROST];
740 break;
742 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_SHADOW];
743 break;
745 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_ARCANE];
746 break;
747 default:
748 {
749 auto it = victimMgr._multiSchoolModifiers.find(mask);
750 if (it != victimMgr._multiSchoolModifiers.end())
751 {
752 threat *= it->second;
753 break;
754 }
755 float mod = victim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, mask);
756 victimMgr._multiSchoolModifiers[mask] = mod;
757 threat *= mod;
758 break;
759 }
760 }
761 return threat;
762}
@ 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:86
#define sSpellMgr
Definition SpellMgr.h:847
Definition Player.h:1086
Definition ThreatManager.h:90
std::unordered_map< std::underlying_type< SpellSchoolMask >::type, float > _multiSchoolModifiers
Definition ThreatManager.h:230
Player * GetSpellModOwner() const override
Definition Unit.cpp:12567
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 // accessories are fully treated as components of the parent and cannot have threat
211 return false;
212
213 return true;
214}
@ 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:212
Definition TemporarySummon.h:50
bool IsPet() const
Definition Unit.h:798
TempSummon * ToTempSummon()
Definition Unit.h:732
bool IsTotem() const
Definition Unit.h:800

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

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

◆ ClearAllThreat()

void ThreatManager::ClearAllThreat ( )
585{
586 if (!_myThreatListEntries.empty())
587 {
589 do
590 _myThreatListEntries.begin()->second->UnregisterAndFree();
591 while (!_myThreatListEntries.empty());
592 }
593}
void SendClearAllThreatToClients() const
Definition ThreatManager.cpp:865

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(), boss_kiljaeden::DamageTaken(), npc_weegli_blastfuse::npc_weegli_blastfuseAI::DoAction(), 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(), boss_thorim_start_npcs::SetGUID(), spell_putricide_ooze_channel::StartAttack(), npc_unkor_the_ruthless::npc_unkor_the_ruthlessAI::Submit(), npc_highlord_darion_mograine::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:595

Referenced by npc_pet_hunter_snake_trap::UpdateAI().

◆ ClearThreat() [1/2]

void ThreatManager::ClearThreat ( ThreatReference *  ref)
577{
579 ref->UnregisterAndFree();
581 UpdateVictim();
582}
void SendRemoveToClients(Unit const *victim) const
Definition ThreatManager.cpp:872
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)
570{
571 auto it = _myThreatListEntries.find(target->GetGUID());
572 if (it != _myThreatListEntries.end())
573 ClearThreat(it->second);
574}
void ClearThreat(Unit *target)
Definition ThreatManager.cpp:569

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
700{
701 if (a->_online != b->_online) // online state precedence (ONLINE > SUPPRESSED > OFFLINE)
702 return a->_online < b->_online;
703 if (a->_taunted != b->_taunted) // taunt state precedence (TAUNT > NONE > DETAUNT)
704 return a->_taunted < b->_taunted;
705 return (a->GetThreat() * aWeight < b->GetThreat());
706}
float GetThreat(Unit const *who, bool includeOffline=false) const
Definition ThreatManager.cpp:290

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

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

◆ EvaluateSuppressed()

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

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)
596{
597 if (target)
598 {
599 auto it = _myThreatListEntries.find(target->GetGUID());
600 if (it != _myThreatListEntries.end())
601 {
602 _fixateRef = it->second;
603 return;
604 }
605 }
606 _fixateRef = nullptr;
607}

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

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

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
264{
265 for (ThreatReference const* ref : *_sortedThreatList)
266 if (!ref->IsOffline())
267 return ref->GetVictim();
268 return nullptr;
269}

References _sortedThreatList, and Unit::GetVictim().

Referenced by Creature::CallForHelp(), and npc_icc_orb_controller::SetGUID().

◆ GetCurrentVictim()

◆ GetFixateTarget()

Unit * ThreatManager::GetFixateTarget ( ) const
610{
611 if (_fixateRef)
612 return _fixateRef->GetVictim();
613 else
614 return nullptr;
615}

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 ( )
347{
348 std::vector<ThreatReference*> list;
349 list.reserve(_myThreatListEntries.size());
350 for (auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end(); it != end; ++it)
351 list.push_back(const_cast<ThreatReference*>(*it));
352 return list;
353}

References _myThreatListEntries, and _sortedThreatList.

Referenced by SmartScript::ProcessAction().

◆ GetOwner()

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

◆ GetSortedThreatList()

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

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
304{
305 uint32 returnValue = 0;
306 for (ThreatReference const* ref : *_sortedThreatList)
307 {
308 if (!includeOffline && !ref->IsAvailable())
309 continue;
310 if (ref->GetVictim()->IsPlayer())
311 ++returnValue;
312 }
313 return returnValue;
314}
std::uint32_t uint32
Definition Define.h:107

References _sortedThreatList.

◆ GetThreatListSize()

◆ GetUnsortedThreatList()

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

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
282{
283 auto it = _myThreatListEntries.find(who);
284 if (it == _myThreatListEntries.end())
285 return false;
286 return (includeOffline || it->second->IsAvailable());
287}

References _myThreatListEntries.

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

◆ IsThreatenedBy() [2/2]

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

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

◆ IsThreateningAnyone()

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

References _threatenedByMe.

Referenced by WorldSession::HandleMoveWorldportAck().

◆ IsThreateningTo() [1/2]

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

References _threatenedByMe.

Referenced by IsThreateningTo().

◆ IsThreateningTo() [2/2]

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

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

◆ IsThreatListEmpty()

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

◆ MatchUnitThreatToHighestThreat()

void ThreatManager::MatchUnitThreatToHighestThreat ( Unit *  target)
507{
508 if (_sortedThreatList->empty())
509 return;
510
511 auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end();
512 ThreatReference const* highest = *it;
513 if (!highest->IsAvailable())
514 return;
515
516 if (highest->IsTaunting() && ((++it) != end)) // might need to skip this - max threat could be the preceding element (there is only one taunt element)
517 {
518 ThreatReference const* a = *it;
519 if (a->IsAvailable() && a->GetThreat() > highest->GetThreat())
520 highest = a;
521 }
522
523 AddThreat(target, highest->GetThreat() - GetThreat(target, true), nullptr, true, true);
524}
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
688{
690 std::vector<ObjectGuid> v(std::move(_needsAIUpdate)); // _needsAIUpdate is now empty in case this triggers a recursive call
691 if (!ai)
692 return;
693 for (ObjectGuid const& guid : v)
694 if (ThreatReference const* ref = Acore::Containers::MapGetValuePtr(_myThreatListEntries, guid))
695 ai->JustStartedThreateningMe(ref->GetVictim());
696}
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:85
Definition CreatureAI.h:69
Definition ObjectGuid.h:121
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
933{
934 auto it = _threatenedByMe.find(guid);
935 if (it != _threatenedByMe.end())
936 _threatenedByMe.erase(it);
937}

References _threatenedByMe.

Referenced by ThreatReference::UnregisterAndFree().

◆ PurgeThreatListRef()

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

926{
927 auto& inMap = _threatenedByMe[guid];
928 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());
929 inMap = ref;
930}

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

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

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

836{
837 _redirectRegistry[spellId][victim] = pct;
839}
void UpdateRedirectInfo()
Definition ThreatManager.cpp:939

References _redirectRegistry, and UpdateRedirectInfo().

Referenced by Spell::EffectRedirectThreat().

◆ RemoveMeFromThreatLists()

void ThreatManager::RemoveMeFromThreatLists ( )

◆ ReselectVictim()

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

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 ( )
793{
794 for (auto const& pair : _threatenedByMe)
795 pair.second->ScaleThreat(0.0f);
796}

References _threatenedByMe.

◆ ResetAllRedirects()

void ThreatManager::ResetAllRedirects ( )
inline

◆ ResetAllThreat()

◆ ResetThreat()

◆ ScaleThreat()

void ThreatManager::ScaleThreat ( Unit *  target,
float  factor 
)
500{
501 auto it = _myThreatListEntries.find(target->GetGUID());
502 if (it != _myThreatListEntries.end())
503 it->second->ScaleThreat(std::max<float>(factor, 0.0f));
504}

References _myThreatListEntries, and Object::GetGUID().

◆ SendClearAllThreatToClients()

void ThreatManager::SendClearAllThreatToClients ( ) const
private
866{
868 data << _owner->GetPackGUID();
869 _owner->SendMessageToSet(&data, false);
870}
PackedGuid const & GetPackGUID() const
Definition Object.h:122
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:2171
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
873{
875 data << _owner->GetPackGUID();
876 data << victim->GetPackGUID();
877 _owner->SendMessageToSet(&data, false);
878}
@ 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
881{
882 WorldPacket data(newHighest ? SMSG_HIGHEST_THREAT_UPDATE : SMSG_THREAT_UPDATE, (_sortedThreatList->size() + 2) * 8); // guess
883 data << _owner->GetPackGUID();
884 if (newHighest)
886 size_t countPos = data.wpos();
887 data << uint32(0); // placeholder
888 uint32 count = 0;
889 for (ThreatReference const* ref : *_sortedThreatList)
890 {
891 if (!ref->IsAvailable())
892 continue;
893 data << ref->GetVictim()->GetPackGUID();
894 data << uint32(ref->GetThreat() * 100);
895 ++count;
896 }
897 data.put<uint32>(countPos, count);
898 _owner->SendMessageToSet(&data, false);
899}
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 
)
556{
557 auto it = _myThreatListEntries.find(target->GetGUID());
558 if (it != _myThreatListEntries.end())
559 it->second->UpdateTauntState(
560 static_cast<ThreatReference::TauntState>(state));
561}
TauntState
Definition ThreatManager.h:269

References _myThreatListEntries, and Object::GetGUID().

◆ TauntUpdate()

void ThreatManager::TauntUpdate ( )
527{
529
531 std::unordered_map<ObjectGuid, ThreatReference::TauntState> tauntStates;
532 // Only the last taunt effect applied by something still on our threat list is considered
533 for (auto it = tauntEffects.begin(), end = tauntEffects.end(); it != end; ++it)
534 tauntStates[(*it)->GetCasterGUID()] = ThreatReference::TauntState(state++);
535
536 for (auto const& pair : _myThreatListEntries)
537 {
538 auto it = tauntStates.find(pair.first);
539 if (it != tauntStates.end())
540 pair.second->UpdateTauntState(it->second);
541 else
542 pair.second->UpdateTauntState();
543 }
544
545 // taunt aura update also re-evaluates all suppressed states (retail behavior)
546 EvaluateSuppressed(true);
547
548 // immediately reselect victim so taunt takes effect without waiting
549 // for the next THREAT_UPDATE_INTERVAL (1 s) timer tick
550 UpdateVictim();
552}
@ SPELL_AURA_MOD_TAUNT
Definition SpellAuraDefines.h:74
void EvaluateSuppressed(bool canExpire=false)
Definition ThreatManager.cpp:374
@ TAUNT_STATE_TAUNT
Definition ThreatManager.h:269
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1433
std::vector< AuraEffect * > AuraEffectList
Definition Unit.h:681

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 
)
851{
852 auto it = _redirectRegistry.find(spellId);
853 if (it == _redirectRegistry.end())
854 return;
855 auto& victimMap = it->second;
856 auto it2 = victimMap.find(victim);
857 if (it2 == victimMap.end())
858 return;
859 victimMap.erase(it2);
860 if (victimMap.empty())
861 _redirectRegistry.erase(it);
863}

References _redirectRegistry, and UpdateRedirectInfo().

◆ Update()

void ThreatManager::Update ( uint32  tdiff)
236{
237 if (!CanHaveThreatList() || IsThreatListEmpty(true))
238 return;
239 if (_updateTimer <= tdiff)
240 {
241 UpdateVictim();
243 }
244 else
245 _updateTimer -= tdiff;
246}
bool IsThreatListEmpty(bool includeOffline=false) const
Definition ThreatManager.cpp:271

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

Referenced by Creature::Update().

◆ UpdateMySpellSchoolModifiers()

void ThreatManager::UpdateMySpellSchoolModifiers ( )
829{
830 for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
832 _multiSchoolModifiers.clear();
833}
std::uint8_t uint8
Definition Define.h:109
float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
Definition Unit.cpp:6080

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

Referenced by AuraEffect::HandleModThreat().

◆ UpdateMyTempModifiers()

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

References _redirectInfo, _redirectRegistry, and ASSERT.

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

◆ UpdateVictim()

void ThreatManager::UpdateVictim ( )
private
618{
619 ThreatReference const* const newVictim = ReselectVictim();
620 bool const newHighest = newVictim && (newVictim != _currentVictimRef);
621
622 _currentVictimRef = newVictim;
623 if (newHighest || _needClientUpdate)
624 {
625 SendThreatListToClients(newHighest);
626 _needClientUpdate = false;
627 }
628
630}
void SendThreatListToClients(bool newHighest) const
Definition ThreatManager.cpp:880
ThreatReference const * ReselectVictim()
Definition ThreatManager.cpp:632

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: