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)
235 _sortedThreatList(std::make_unique<Heap>()), _currentVictimRef(nullptr), _fixateRef(nullptr)
236{
237 for (int8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
238 _singleSchoolModifiers[i] = 1.0f;
239}
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 ( )
242{
243 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());
244 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());
245 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());
246}
#define ASSERT
Definition Errors.h:68
std::string ToString() const
Definition ObjectGuid.cpp:49
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 ==

411{
412 // step 1: we can shortcut if the spell has one of the NO_THREAT attrs set - nothing will happen
413 if (spell)
414 {
415 if (spell->HasAttribute(SPELL_ATTR1_NO_THREAT))
416 return;
417 if (!_owner->IsEngaged() && spell->HasAttribute(SPELL_ATTR3_SUPPRESS_TARGET_PROCS))
418 return;
419 }
420
421 // while riding a vehicle, all threat goes to the vehicle, not the pilot
422 if (Unit* vehicle = target->GetVehicleBase())
423 {
424 AddThreat(vehicle, amount, spell, ignoreModifiers, ignoreRedirects);
425 if (target->HasUnitTypeMask(UNIT_MASK_ACCESSORY)) // accessories are fully treated as components of the parent and cannot have threat
426 return;
427 amount = 0.0f;
428 }
429
430 // if we cannot actually have a threat list, we instead just set combat state and avoid creating threat refs altogether
431 if (!CanHaveThreatList())
432 {
433 CombatManager& combatMgr = _owner->GetCombatManager();
434 if (!combatMgr.SetInCombatWith(target))
435 return;
436 // traverse redirects and put them in combat, too
437 for (auto const& pair : target->GetThreatMgr()._redirectInfo)
438 if (!combatMgr.IsInCombatWith(pair.first))
439 if (Unit* redirTarget = ObjectAccessor::GetUnit(*_owner, pair.first))
440 combatMgr.SetInCombatWith(redirTarget);
441 return;
442 }
443
444 // apply threat modifiers to the amount
445 if (!ignoreModifiers)
446 amount = CalculateModifiedThreat(amount, target, spell);
447
448 // the owner's AI sees the threat once, before any of it is redirected; the redirected shares are not reported again
449 if (!ignoreRedirects)
450 {
451 if (Creature* creatureOwner = _owner->ToCreature())
452 if (creatureOwner->IsAIEnabled)
453 creatureOwner->AI()->CalculateThreat(target, amount, spell);
454 }
455
456 // if we're increasing threat, send some/all of it to redirection targets instead if applicable
457 if (!ignoreRedirects && amount > 0.0f)
458 {
459 auto const& redirInfo = target->GetThreatMgr()._redirectInfo;
460 if (!redirInfo.empty())
461 {
462 float const origAmount = amount;
463 // intentional iteration by index - there's a nested AddThreat call further down that might cause AI calls which might modify redirect info through spells
464 for (size_t i = 0; i < redirInfo.size(); ++i)
465 {
466 auto const pair = redirInfo[i]; // (victim,pct)
467 Unit* redirTarget = nullptr;
468 auto it = _myThreatListEntries.find(pair.first); // try to look it up in our threat list first (faster)
469 if (it != _myThreatListEntries.end())
470 redirTarget = it->second->_victim;
471 else
472 redirTarget = ObjectAccessor::GetUnit(*_owner, pair.first);
473
474 if (redirTarget)
475 {
476 float amountRedirected = CalculatePct(origAmount, pair.second);
477 AddThreat(redirTarget, amountRedirected, spell, true, true);
478 amount -= amountRedirected;
479 }
480 }
481 }
482 }
483
484 // ensure we're in combat (threat implies combat!)
485 if (!_owner->GetCombatManager().SetInCombatWith(target)) // if this returns false, we're not actually in combat, and thus cannot have threat!
486 return; // typical causes: bad scripts trying to add threat to GMs, dead targets etc
487
488 // ok, now we actually apply threat
489 // check if we already have an entry - if we do, just increase threat for that entry and we're done
490 auto it = _myThreatListEntries.find(target->GetGUID());
491 if (it != _myThreatListEntries.end())
492 {
493 ThreatReference* const ref = it->second;
494
495 // SUPPRESSED threat states don't go back to ONLINE until threat is caused by them (retail behavior)
497 if (!ref->ShouldBeSuppressed())
498 {
500 ref->HeapNotifyIncreased();
501 }
502
503 if (ref->IsOnline())
504 ref->AddThreat(amount);
505
506 return;
507 }
508
509 // ok, we're now in combat - create the threat list reference and push it to the respective managers
510 ThreatReference* ref = new ThreatReferenceImpl(this, target);
511 PutThreatListRef(target->GetGUID(), ref);
513
514 ref->UpdateOffline();
515 if (ref->IsOnline()) // we only add the threat if the ref is currently available
516 ref->AddThreat(amount);
517 // Note: AI update registration is handled inside UpdateOffline() when transitioning from OFFLINE
518
520 UpdateVictim();
521 else
523}
@ 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:110
bool SetInCombatWith(Unit *who, bool addSecondUnitSuppressed=false)
Definition CombatManager.cpp:214
Definition Creature.h:47
Creature * ToCreature()
Definition Object.h:212
bool CanHaveThreatList() const
Definition ThreatManager.h:109
static float CalculateModifiedThreat(float threat, Unit const *victim, SpellInfo const *spell)
Definition ThreatManager.cpp:741
std::vector< std::pair< ObjectGuid, uint32 > > _redirectInfo
Definition ThreatManager.h:233
void PutThreatListRef(ObjectGuid const &guid, ThreatReference *ref)
== MY THREAT LIST ==
Definition ThreatManager.cpp:934
void PutThreatenedByMeRef(ObjectGuid const &guid, ThreatReference *ref)
== OTHERS' THREAT LISTS ==
Definition ThreatManager.cpp:958
void AddThreat(Unit *target, float amount, SpellInfo const *spell=nullptr, bool ignoreModifiers=false, bool ignoreRedirects=false)
== AFFECT MY THREAT LIST ==
Definition ThreatManager.cpp:410
void ProcessAIUpdates()
Definition ThreatManager.cpp:720
friend class ThreatReferenceImpl
Definition ThreatManager.h:261
void UpdateVictim()
Definition ThreatManager.cpp:650
Definition ThreatManager.h:267
void UpdateOffline()
Definition ThreatManager.cpp:75
void HeapNotifyIncreased()
Definition ThreatManager.cpp:197
@ 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:670
Unit * GetVehicleBase() const
Definition Unit.cpp:14704
ThreatManager & GetThreatMgr()
Definition Unit.h:965
uint32 HasUnitTypeMask(uint32 mask) const
Definition Unit.h:747
CombatManager & GetCombatManager()
Definition Unit.h:967
virtual bool IsEngaged() const
Definition Unit.h:945
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, Object::ToCreature(), 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
742{
743 // modifiers by spell
744 if (spell)
745 {
746 if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(spell->Id))
747 if (threatEntry->pctMod != 1.0f) // flat/AP modifiers handled in Spell::HandleThreatSpells
748 threat *= threatEntry->pctMod;
749
750 if (Player* modOwner = victim->GetSpellModOwner())
751 modOwner->ApplySpellMod(spell->Id, SPELLMOD_THREAT, threat);
752 }
753
754 // modifiers by effect school
755 ThreatManager const& victimMgr = victim->GetThreatMgr();
756 SpellSchoolMask const mask = spell ? spell->GetSchoolMask() : SPELL_SCHOOL_MASK_NORMAL;
757 switch (mask)
758 {
760 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_NORMAL];
761 break;
763 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_HOLY];
764 break;
766 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_FIRE];
767 break;
769 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_NATURE];
770 break;
772 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_FROST];
773 break;
775 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_SHADOW];
776 break;
778 threat *= victimMgr._singleSchoolModifiers[SPELL_SCHOOL_ARCANE];
779 break;
780 default:
781 {
782 auto it = victimMgr._multiSchoolModifiers.find(mask);
783 if (it != victimMgr._multiSchoolModifiers.end())
784 {
785 threat *= it->second;
786 break;
787 }
788 float mod = victim->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_THREAT, mask);
789 victimMgr._multiSchoolModifiers[mask] = mod;
790 threat *= mod;
791 break;
792 }
793 }
794 return threat;
795}
@ 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:851
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:12637
Definition SpellMgr.h:377

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
208{
209 if (!who)
210 return false;
211
212 Creature const* cWho = who->ToCreature();
213 // only creatures can have threat list
214 if (!cWho)
215 return false;
216
217 // pets, totems and triggers cannot have threat list
218 if (cWho->IsPet() || cWho->IsTotem() || cWho->IsTrigger())
219 return false;
220
221 // summons cannot have a threat list if they were summoned by a player
223 if (TempSummon const* tWho = cWho->ToTempSummon())
224 if (tWho->GetSummonerGUID().IsPlayer())
225 return false;
226
227 // accessories are fully treated as components of the parent and cannot have threat
229 return false;
230
231 return true;
232}
@ UNIT_MASK_GUARDIAN
Definition UnitDefines.h:161
@ UNIT_MASK_MINION
Definition UnitDefines.h:160
bool IsTrigger() const
Definition Creature.h:79
Definition TemporarySummon.h:50
bool IsPet() const
Definition Unit.h:803
TempSummon * ToTempSummon()
Definition Unit.h:737
bool IsTotem() const
Definition Unit.h:805

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 ( )
618{
619 if (!_myThreatListEntries.empty())
620 {
622 do
623 _myThreatListEntries.begin()->second->UnregisterAndFree();
624 while (!_myThreatListEntries.empty());
625 }
626}
void SendClearAllThreatToClients() const
Definition ThreatManager.cpp:898

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(), npc_snobold_vassal::npc_snobold_vassalAI::LoseCarrier(), 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(), boss_malygos::UpdateAI(), and npc_aeranas::npc_aeranasAI::UpdateAI().

◆ ClearFixate()

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

Referenced by npc_pet_hunter_snake_trap::UpdateAI().

◆ ClearThreat() [1/2]

void ThreatManager::ClearThreat ( ThreatReference *  ref)
610{
612 ref->UnregisterAndFree();
614 UpdateVictim();
615}
void SendRemoveToClients(Unit const *victim) const
Definition ThreatManager.cpp:905
void UnregisterAndFree()
Definition ThreatManager.cpp:178
Unit *const _victim
Definition ThreatManager.h:312

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

◆ ClearThreat() [2/2]

void ThreatManager::ClearThreat ( Unit *  target)
603{
604 auto it = _myThreatListEntries.find(target->GetGUID());
605 if (it != _myThreatListEntries.end())
606 ClearThreat(it->second);
607}
void ClearThreat(Unit *target)
Definition ThreatManager.cpp:602

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
733{
734 if (a->_online != b->_online) // online state precedence (ONLINE > SUPPRESSED > OFFLINE)
735 return a->_online < b->_online;
736 if (a->_taunted != b->_taunted) // taunt state precedence (TAUNT > NONE > DETAUNT)
737 return a->_taunted < b->_taunted;
738 return (a->GetThreat() * aWeight < b->GetThreat());
739}
float GetThreat(Unit const *who, bool includeOffline=false) const
Definition ThreatManager.cpp:308

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

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

◆ EvaluateSuppressed()

void ThreatManager::EvaluateSuppressed ( bool  canExpire = false)
393{
394 for (auto const& pair : _threatenedByMe)
395 {
396 bool const shouldBeSuppressed = pair.second->ShouldBeSuppressed();
397 if (pair.second->IsOnline() && shouldBeSuppressed)
398 {
399 pair.second->_online = ThreatReference::ONLINE_STATE_SUPPRESSED;
400 pair.second->HeapNotifyDecreased();
401 }
402 else if (canExpire && pair.second->IsSuppressed() && !shouldBeSuppressed)
403 {
404 pair.second->_online = ThreatReference::ONLINE_STATE_ONLINE;
405 pair.second->HeapNotifyIncreased();
406 }
407 }
408}

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)
629{
630 if (target)
631 {
632 auto it = _myThreatListEntries.find(target->GetGUID());
633 if (it != _myThreatListEntries.end())
634 {
635 _fixateRef = it->second;
636 return;
637 }
638 }
639 _fixateRef = nullptr;
640}

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

798{
799 if (spell && spell->HasAttribute(SPELL_ATTR1_NO_THREAT)) // shortcut, none of the calls would do anything
800 return;
801 if (_threatenedByMe.empty())
802 return;
803
804 std::vector<Creature*> canBeThreatened, cannotBeThreatened;
805 for (auto const& pair : _threatenedByMe)
806 {
807 Creature* owner = pair.second->GetOwner();
809 canBeThreatened.push_back(owner);
810 else
811 cannotBeThreatened.push_back(owner);
812 }
813
814 if (!canBeThreatened.empty()) // targets under CC cannot gain assist threat - split evenly among the rest
815 {
816 float const perTarget = baseAmount / canBeThreatened.size();
817 for (Creature* threatened : canBeThreatened)
818 threatened->GetThreatMgr().AddThreat(assistant, perTarget, spell, ignoreModifiers);
819 }
820
821 for (Creature* threatened : cannotBeThreatened)
822 threatened->GetThreatMgr().AddThreat(assistant, 0.0f, spell, true);
823}
@ UNIT_STATE_CONTROLLED
Definition UnitDefines.h:218
Unit * GetOwner() const
Definition Unit.cpp:7517
bool HasUnitState(const uint32 f) const
Definition Unit.h:742

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
282{
283 for (ThreatReference const* ref : *_sortedThreatList)
284 if (!ref->IsOffline())
285 return ref->GetVictim();
286 return nullptr;
287}

References _sortedThreatList, and Unit::GetVictim().

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

◆ GetCurrentVictim()

◆ GetFixateTarget()

Unit * ThreatManager::GetFixateTarget ( ) const
643{
644 if (_fixateRef)
645 return _fixateRef->GetVictim();
646 else
647 return nullptr;
648}

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 ( )
365{
366 std::vector<ThreatReference*> list;
367 list.reserve(_myThreatListEntries.size());
368 for (auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end(); it != end; ++it)
369 list.push_back(const_cast<ThreatReference*>(*it));
370 return list;
371}

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
350{
351 auto itr = _sortedThreatList->ordered_begin();
352 auto end = _sortedThreatList->ordered_end();
353 std::function<ThreatReference const* ()> generator = [itr, end]() mutable -> ThreatReference const*
354 {
355 if (itr == end)
356 return nullptr;
357
358 return *(itr++);
359 };
360 std::function<ThreatReference const* ()> endGenerator = []() -> ThreatReference const* { return nullptr; };
361 return { ThreatListIterator{ std::move(generator) }, ThreatListIterator{ std::move(endGenerator) } };
362}

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
322{
323 uint32 returnValue = 0;
324 for (ThreatReference const* ref : *_sortedThreatList)
325 {
326 if (!includeOffline && !ref->IsAvailable())
327 continue;
328 if (ref->GetVictim()->IsPlayer())
329 ++returnValue;
330 }
331 return returnValue;
332}
std::uint32_t uint32
Definition Define.h:107

References _sortedThreatList.

◆ GetThreatListSize()

◆ GetUnsortedThreatList()

Acore::IteratorPair< ThreatManager::ThreatListIterator > ThreatManager::GetUnsortedThreatList ( ) const
335{
336 auto itr = _myThreatListEntries.begin();
337 auto end = _myThreatListEntries.end();
338 std::function<ThreatReference const* ()> generator = [itr, end]() mutable -> ThreatReference const*
339 {
340 if (itr == end)
341 return nullptr;
342
343 return (itr++)->second;
344 };
345 std::function<ThreatReference const* ()> endGenerator = []() -> ThreatReference const* { return nullptr; };
346 return { ThreatListIterator{ std::move(generator) }, ThreatListIterator{ std::move(endGenerator) } };
347}

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

Referenced by boss_ouro::CastBoulderIfReady(), 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(), HasTargetableThreat(), 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
300{
301 auto it = _myThreatListEntries.find(who);
302 if (it == _myThreatListEntries.end())
303 return false;
304 return (includeOffline || it->second->IsAvailable());
305}

References _myThreatListEntries.

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

◆ IsThreatenedBy() [2/2]

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

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

◆ IsThreateningAnyone()

bool ThreatManager::IsThreateningAnyone ( bool  includeOffline = false) const
374{
375 if (includeOffline)
376 return !_threatenedByMe.empty();
377 for (auto const& pair : _threatenedByMe)
378 if (pair.second->IsAvailable())
379 return true;
380 return false;
381}

References _threatenedByMe.

Referenced by WorldSession::HandleMoveWorldportAck().

◆ IsThreateningTo() [1/2]

bool ThreatManager::IsThreateningTo ( ObjectGuid const &  who,
bool  includeOffline = false 
) const
384{
385 auto it = _threatenedByMe.find(who);
386 if (it == _threatenedByMe.end())
387 return false;
388 return (includeOffline || it->second->IsAvailable());
389}

References _threatenedByMe.

Referenced by IsThreateningTo().

◆ IsThreateningTo() [2/2]

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

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

◆ IsThreatListEmpty()

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

◆ MatchUnitThreatToHighestThreat()

void ThreatManager::MatchUnitThreatToHighestThreat ( Unit *  target)
533{
534 if (_sortedThreatList->empty())
535 return;
536
537 auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end();
538 ThreatReference const* highest = *it;
539 if (!highest->IsAvailable())
540 return;
541
542 if (highest->IsTaunting() && ((++it) != end)) // might need to skip this - max threat could be the preceding element (there is only one taunt element)
543 {
544 ThreatReference const* a = *it;
545 if (a->IsAvailable() && a->GetThreat() > highest->GetThreat())
546 highest = a;
547 }
548
549 float const threatDiff = highest->GetThreat() - GetThreat(target, true);
550 AddThreat(target, threatDiff, nullptr, true, true);
551
552 // a suppressed reference ignores AddThreat, but a taunt still matches the highest threat
553 if (threatDiff > 0.0f && !target->GetVehicleBase())
555 if (ref->IsSuppressed())
556 ref->AddThreat(threatDiff);
557}
bool IsTaunting() const
Definition ThreatManager.h:281
float GetThreat() const
Definition ThreatManager.h:274
auto MapGetValuePtr(M &map, typename M::key_type const &key) -> decltype(AddressOrSelf(map.find(key) ->second))
Definition Containers.h:216

References _myThreatListEntries, _sortedThreatList, AddThreat(), Object::GetGUID(), ThreatReference::GetThreat(), GetThreat(), Unit::GetVehicleBase(), ThreatReference::IsAvailable(), ThreatReference::IsTaunting(), and Acore::Containers::MapGetValuePtr().

Referenced by Spell::EffectTaunt().

◆ ModifyThreatByPercent()

◆ operator=()

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

◆ ProcessAIUpdates()

void ThreatManager::ProcessAIUpdates ( )
private
721{
723 std::vector<ObjectGuid> v(std::move(_needsAIUpdate)); // _needsAIUpdate is now empty in case this triggers a recursive call
724 if (!ai)
725 return;
726 for (ObjectGuid const& guid : v)
727 if (ThreatReference const* ref = Acore::Containers::MapGetValuePtr(_myThreatListEntries, guid))
728 ai->JustStartedThreateningMe(ref->GetVictim());
729}
#define ASSERT_NOTNULL(pointer)
Definition Errors.h:85
Definition CreatureAI.h:69
Definition ObjectGuid.h:121
std::vector< ObjectGuid > _needsAIUpdate
Definition ThreatManager.h:218
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
966{
967 auto it = _threatenedByMe.find(guid);
968 if (it != _threatenedByMe.end())
969 _threatenedByMe.erase(it);
970}

References _threatenedByMe.

Referenced by ThreatReference::UnregisterAndFree().

◆ PurgeThreatListRef()

void ThreatManager::PurgeThreatListRef ( ObjectGuid const &  guid)
private
944{
945 auto it = _myThreatListEntries.find(guid);
946 if (it == _myThreatListEntries.end())
947 return;
948 ThreatReference* ref = it->second;
949 _myThreatListEntries.erase(it);
950 _sortedThreatList->erase(static_cast<ThreatReferenceImpl*>(ref)->_handle);
951
952 if (_fixateRef == ref)
953 _fixateRef = nullptr;
954 if (_currentVictimRef == ref)
955 _currentVictimRef = nullptr;
956}
Definition ThreatManager.cpp:186

References _currentVictimRef, _fixateRef, _myThreatListEntries, and _sortedThreatList.

Referenced by ThreatReference::UnregisterAndFree().

◆ PutThreatenedByMeRef()

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

== OTHERS' THREAT LISTS ==

959{
960 auto& inMap = _threatenedByMe[guid];
961 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());
962 inMap = ref;
963}

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

935{
936 _needClientUpdate = true;
937 auto& inMap = _myThreatListEntries[guid];
938 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());
939 inMap = ref;
940 static_cast<ThreatReferenceImpl*>(ref)->_handle = _sortedThreatList->push(ref);
941}

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

869{
870 _redirectRegistry[spellId][victim] = pct;
872}
void UpdateRedirectInfo()
Definition ThreatManager.cpp:972

References _redirectRegistry, and UpdateRedirectInfo().

Referenced by Spell::EffectRedirectThreat().

◆ RemoveMeFromThreatLists()

void ThreatManager::RemoveMeFromThreatLists ( )

◆ ReselectVictim()

ThreatReference const * ThreatManager::ReselectVictim ( )
private
666{
667 if (_sortedThreatList->empty())
668 return nullptr;
669
670 for (auto const& pair : _myThreatListEntries)
671 pair.second->UpdateOffline(); // AI notifies are processed in ::UpdateVictim caller
672
673 // fixated target is always preferred
675 return _fixateRef;
676
677 ThreatReference const* oldVictimRef = _currentVictimRef;
678 if (oldVictimRef && oldVictimRef->IsOffline())
679 oldVictimRef = nullptr;
680 // in 99% of cases - we won't need to actually look at anything beyond the first element
681 ThreatReference const* highest = _sortedThreatList->top();
682
683 // if the highest reference is offline, the entire list is offline, and we indicate this
684 if (!highest->IsAvailable())
685 return nullptr;
686 // if we have no old victim, or old victim is still highest, then highest is our target and we're done
687 if (!oldVictimRef || highest == oldVictimRef)
688 return highest;
689 // 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
690 if (!ThreatManager::CompareReferencesLT(oldVictimRef, highest, 1.1f))
691 return oldVictimRef;
692 // if highest threat breaks 130%, it's our new target regardless of range (and we're done)
693 if (ThreatManager::CompareReferencesLT(oldVictimRef, highest, 1.3f))
694 return highest;
695 // 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
696 if (_owner->IsWithinMeleeRange(highest->_victim))
697 return highest;
698 // If we get here, highest threat is ranged, but below 130% of current - there might be a melee that breaks 110% below us somewhere
699 auto it = _sortedThreatList->ordered_begin(), end = _sortedThreatList->ordered_end();
700 while (it != end)
701 {
702 ThreatReference const* next = *it;
703 // if we've found current victim, we're done (nothing above is higher, and nothing below can be higher)
704 if (next == oldVictimRef)
705 return next;
706 // if next isn't above 110% threat, then nothing below it can be either - we're done, old victim stays
707 if (!ThreatManager::CompareReferencesLT(oldVictimRef, next, 1.1f))
708 return oldVictimRef;
709 // if next is melee, he's above 110% and our new victim
711 return next;
712 // otherwise the next highest target may still be a melee above 110% and we need to look further
713 ++it;
714 }
715 // we should have found the old victim at some point in the loop above
716 ASSERT(false && "Current victim not found in sorted threat list even though it has a reference - manager desync!");
717 return nullptr;
718}
static bool CompareReferencesLT(ThreatReference const *a, ThreatReference const *b, float aWeight)
Definition ThreatManager.cpp:732
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 ( )
826{
827 for (auto const& pair : _threatenedByMe)
828 pair.second->ScaleThreat(0.0f);
829}

References _threatenedByMe.

◆ ResetAllRedirects()

void ThreatManager::ResetAllRedirects ( )
inline

◆ ResetAllThreat()

◆ ResetThreat()

◆ ScaleThreat()

void ThreatManager::ScaleThreat ( Unit *  target,
float  factor 
)
526{
527 auto it = _myThreatListEntries.find(target->GetGUID());
528 if (it != _myThreatListEntries.end())
529 it->second->ScaleThreat(std::max<float>(factor, 0.0f));
530}

References _myThreatListEntries, and Object::GetGUID().

◆ SendClearAllThreatToClients()

void ThreatManager::SendClearAllThreatToClients ( ) const
private
899{
901 data << _owner->GetPackGUID();
902 _owner->SendMessageToSet(&data, false);
903}
PackedGuid const & GetPackGUID() const
Definition Object.h:122
virtual void SendMessageToSet(WorldPacket const *data, bool self) const
Definition Object.cpp:2178
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
906{
908 data << _owner->GetPackGUID();
909 data << victim->GetPackGUID();
910 _owner->SendMessageToSet(&data, false);
911}
@ 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
914{
915 WorldPacket data(newHighest ? SMSG_HIGHEST_THREAT_UPDATE : SMSG_THREAT_UPDATE, (_sortedThreatList->size() + 2) * 8); // guess
916 data << _owner->GetPackGUID();
917 if (newHighest)
919 size_t countPos = data.wpos();
920 data << uint32(0); // placeholder
921 uint32 count = 0;
922 for (ThreatReference const* ref : *_sortedThreatList)
923 {
924 if (!ref->IsAvailable())
925 continue;
926 data << ref->GetVictim()->GetPackGUID();
927 data << uint32(ref->GetThreat() * 100);
928 ++count;
929 }
930 data.put<uint32>(countPos, count);
931 _owner->SendMessageToSet(&data, false);
932}
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 
)
589{
590 auto it = _myThreatListEntries.find(target->GetGUID());
591 if (it != _myThreatListEntries.end())
592 it->second->UpdateTauntState(
593 static_cast<ThreatReference::TauntState>(state));
594}
TauntState
Definition ThreatManager.h:269

References _myThreatListEntries, and Object::GetGUID().

◆ TauntUpdate()

void ThreatManager::TauntUpdate ( )
560{
562
564 std::unordered_map<ObjectGuid, ThreatReference::TauntState> tauntStates;
565 // Only the last taunt effect applied by something still on our threat list is considered
566 for (auto it = tauntEffects.begin(), end = tauntEffects.end(); it != end; ++it)
567 tauntStates[(*it)->GetCasterGUID()] = ThreatReference::TauntState(state++);
568
569 for (auto const& pair : _myThreatListEntries)
570 {
571 auto it = tauntStates.find(pair.first);
572 if (it != tauntStates.end())
573 pair.second->UpdateTauntState(it->second);
574 else
575 pair.second->UpdateTauntState();
576 }
577
578 // taunt aura update also re-evaluates all suppressed states (retail behavior)
579 EvaluateSuppressed(true);
580
581 // immediately reselect victim so taunt takes effect without waiting
582 // for the next THREAT_UPDATE_INTERVAL (1 s) timer tick
583 UpdateVictim();
585}
@ SPELL_AURA_MOD_TAUNT
Definition SpellAuraDefines.h:74
void EvaluateSuppressed(bool canExpire=false)
Definition ThreatManager.cpp:392
@ TAUNT_STATE_TAUNT
Definition ThreatManager.h:269
AuraEffectList const & GetAuraEffectsByType(AuraType type) const
Definition Unit.h:1445
std::vector< AuraEffect * > AuraEffectList
Definition Unit.h:686

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 
)
884{
885 auto it = _redirectRegistry.find(spellId);
886 if (it == _redirectRegistry.end())
887 return;
888 auto& victimMap = it->second;
889 auto it2 = victimMap.find(victim);
890 if (it2 == victimMap.end())
891 return;
892 victimMap.erase(it2);
893 if (victimMap.empty())
894 _redirectRegistry.erase(it);
896}

References _redirectRegistry, and UpdateRedirectInfo().

◆ Update()

void ThreatManager::Update ( uint32  tdiff)
254{
255 if (!CanHaveThreatList() || IsThreatListEmpty(true))
256 return;
257 if (_updateTimer <= tdiff)
258 {
259 UpdateVictim();
261 }
262 else
263 _updateTimer -= tdiff;
264}
bool IsThreatListEmpty(bool includeOffline=false) const
Definition ThreatManager.cpp:289

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

Referenced by Creature::Update().

◆ UpdateMySpellSchoolModifiers()

void ThreatManager::UpdateMySpellSchoolModifiers ( )
862{
863 for (uint8 i = 0; i < MAX_SPELL_SCHOOL; ++i)
865 _multiSchoolModifiers.clear();
866}
std::uint8_t uint8
Definition Define.h:109
float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
Definition Unit.cpp:6116

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

Referenced by AuraEffect::HandleModThreat().

◆ UpdateMyTempModifiers()

void ThreatManager::UpdateMyTempModifiers ( )
841{
842 int32 mod = 0;
843 for (AuraEffect const* eff : _owner->GetAuraEffectsByType(SPELL_AURA_MOD_TOTAL_THREAT))
844 mod += eff->GetAmount();
845
846 if (_threatenedByMe.empty())
847 return;
848
849 auto it = _threatenedByMe.begin();
850 bool const isIncrease = (it->second->_tempModifier < mod);
851 do
852 {
853 it->second->_tempModifier = mod;
854 if (isIncrease)
855 it->second->HeapNotifyIncreased();
856 else
857 it->second->HeapNotifyDecreased();
858 } while ((++it) != _threatenedByMe.end());
859}
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
973{
974 _redirectInfo.clear();
975 uint32 totalPct = 0;
976 for (auto const& pair : _redirectRegistry) // (spellid, victim -> pct)
977 for (auto const& victimPair : pair.second) // (victim,pct)
978 {
979 uint32 thisPct = std::min<uint32>(100 - totalPct, victimPair.second);
980 if (thisPct > 0)
981 {
982 _redirectInfo.push_back({ victimPair.first, thisPct });
983 totalPct += thisPct;
984 ASSERT(totalPct <= 100);
985 if (totalPct == 100)
986 return;
987 }
988 }
989}

References _redirectInfo, _redirectRegistry, and ASSERT.

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

◆ UpdateVictim()

void ThreatManager::UpdateVictim ( )
private
651{
652 ThreatReference const* const newVictim = ReselectVictim();
653 bool const newHighest = newVictim && (newVictim != _currentVictimRef);
654
655 _currentVictimRef = newVictim;
656 if (newHighest || _needClientUpdate)
657 {
658 SendThreatListToClients(newHighest);
659 _needClientUpdate = false;
660 }
661
663}
void SendThreatListToClients(bool newHighest) const
Definition ThreatManager.cpp:913
ThreatReference const * ReselectVictim()
Definition ThreatManager.cpp:665

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: