refactor(Core/Combat): Port TrinityCore heap-based threat system (#24715)
Co-authored-by: blinkysc <blinkysc@users.noreply.github.com> Co-authored-by: Treeston <treeston.mmoc@gmail.com> Co-authored-by: killerwife <killerwife@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -235,9 +235,10 @@ struct boss_hadronox : public BossAI
|
||||
|
||||
bool IsInCombatWithPlayer() const
|
||||
{
|
||||
return std::ranges::any_of(me->GetThreatMgr().GetThreatList(), [](auto const& ref) {
|
||||
return ref->getTarget()->IsControlledByPlayer();
|
||||
});
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
if (ref->GetVictim()->IsControlledByPlayer())
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void DamageTaken(Unit* who, uint32& damage, DamageEffectType /*damageType*/, SpellSchoolMask /*damageSchoolMask*/) override
|
||||
|
||||
@@ -1080,7 +1080,7 @@ class spell_halion_twilight_phasing_aura : public AuraScript
|
||||
GetTarget()->SetUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
GetTarget()->ToCreature()->SetReactState(REACT_DEFENSIVE);
|
||||
GetTarget()->GetMotionMaster()->Clear();
|
||||
GetTarget()->GetThreatMgr().clearReferences();
|
||||
GetTarget()->GetThreatMgr().ClearAllThreat();
|
||||
GetTarget()->RemoveAllAttackers();
|
||||
GetTarget()->AttackStop();
|
||||
}
|
||||
@@ -1090,7 +1090,7 @@ class spell_halion_twilight_phasing_aura : public AuraScript
|
||||
GetTarget()->RemoveUnitFlag(UNIT_FLAG_NOT_SELECTABLE);
|
||||
GetTarget()->ToCreature()->SetReactState(REACT_DEFENSIVE);
|
||||
GetTarget()->GetMotionMaster()->Clear();
|
||||
GetTarget()->GetThreatMgr().clearReferences();
|
||||
GetTarget()->GetThreatMgr().ClearAllThreat();
|
||||
GetTarget()->RemoveAllAttackers();
|
||||
GetTarget()->AttackStop();
|
||||
}
|
||||
|
||||
+2
-2
@@ -138,7 +138,7 @@ public:
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
events.Reset();
|
||||
Talk(SAY_EADRIC_DEFEATED);
|
||||
me->GetThreatMgr().clearReferences();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
me->SetRegeneratingHealth(false);
|
||||
_EnterEvadeMode();
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
@@ -281,7 +281,7 @@ public:
|
||||
me->SetFaction(FACTION_FRIENDLY);
|
||||
events.Reset();
|
||||
Talk(SAY_PALETRESS_DEFEATED);
|
||||
me->GetThreatMgr().clearReferences();
|
||||
me->GetThreatMgr().ClearAllThreat();
|
||||
me->SetRegeneratingHealth(false);
|
||||
_EnterEvadeMode();
|
||||
me->SetUnitFlag(UNIT_FLAG_NON_ATTACKABLE);
|
||||
|
||||
-1
@@ -143,7 +143,6 @@ public:
|
||||
void Reset() override
|
||||
{
|
||||
me->SetReactState(REACT_PASSIVE);
|
||||
me->getHostileRefMgr().setOnlineOfflineState(false);
|
||||
}
|
||||
|
||||
void OnCharmed(bool apply) override
|
||||
|
||||
+12
-19
@@ -103,17 +103,14 @@ struct boss_faction_championsAI : public ScriptedAI
|
||||
|
||||
void RecalculateThreat()
|
||||
{
|
||||
ThreatContainer::StorageType const& tList = me->GetThreatMgr().GetThreatList();
|
||||
for( ThreatContainer::StorageType::const_iterator itr = tList.begin(); itr != tList.end(); ++itr )
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
Unit* pUnit = ObjectAccessor::GetUnit(*me, (*itr)->getUnitGuid());
|
||||
Unit* pUnit = ref->GetVictim();
|
||||
if (pUnit && pUnit->IsPlayer() && me->GetThreatMgr().GetThreat(pUnit))
|
||||
{
|
||||
float threatMod = GetThreatMod(me->GetDistance2d(pUnit), (float)pUnit->GetArmor(), pUnit->GetHealth(), pUnit->GetMaxHealth(), pUnit);
|
||||
me->GetThreatMgr().ModifyThreatByPercent(pUnit, -100);
|
||||
//me->getThreatMgr().DoAddThreat(pUnit, 10000000.0f * threatMod);
|
||||
if (HostileReference* ref = me->GetThreatMgr().GetOnlineContainer().getReferenceByTarget(pUnit))
|
||||
ref->AddThreat(10000000.0f * threatMod);
|
||||
me->GetThreatMgr().ResetThreat(pUnit);
|
||||
me->GetThreatMgr().AddThreat(pUnit, 10000000.0f * threatMod, nullptr, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -179,27 +176,23 @@ struct boss_faction_championsAI : public ScriptedAI
|
||||
|
||||
uint32 EnemiesInRange(float distance)
|
||||
{
|
||||
ThreatContainer::StorageType const& tList = me->GetThreatMgr().GetThreatList();
|
||||
uint32 count = 0;
|
||||
Unit* target;
|
||||
for( ThreatContainer::StorageType::const_iterator iter = tList.begin(); iter != tList.end(); ++iter )
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
target = ObjectAccessor::GetUnit((*me), (*iter)->getUnitGuid());
|
||||
if (target && me->GetDistance2d(target) < distance )
|
||||
++count;
|
||||
if (Unit* target = ref->GetVictim())
|
||||
if (me->GetDistance2d(target) < distance)
|
||||
++count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
Unit* SelectEnemyCaster(bool casting, float range)
|
||||
{
|
||||
ThreatContainer::StorageType const& tList = me->GetThreatMgr().GetThreatList();
|
||||
Unit* target;
|
||||
for( ThreatContainer::StorageType::const_iterator iter = tList.begin(); iter != tList.end(); ++iter )
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
target = ObjectAccessor::GetUnit((*me), (*iter)->getUnitGuid());
|
||||
if (target && target->getPowerType() == POWER_MANA && (!casting || target->HasUnitState(UNIT_STATE_CASTING)) && me->GetExactDist(target) <= range )
|
||||
return target;
|
||||
if (Unit* target = ref->GetVictim())
|
||||
if (target->getPowerType() == POWER_MANA && (!casting || target->HasUnitState(UNIT_STATE_CASTING)) && me->GetExactDist(target) <= range)
|
||||
return target;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -980,7 +980,7 @@ public:
|
||||
for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
|
||||
if (Player* p = itr->GetSource())
|
||||
if (!p->IsGameMaster())
|
||||
p->SetInCombatState(true);
|
||||
p->SetInCombatWith(me);
|
||||
_events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, 4s);
|
||||
}
|
||||
break;
|
||||
@@ -1319,7 +1319,7 @@ public:
|
||||
for (Map::PlayerList::const_iterator itr = pl.begin(); itr != pl.end(); ++itr)
|
||||
if (Player* p = itr->GetSource())
|
||||
if (!p->IsGameMaster())
|
||||
p->SetInCombatState(true);
|
||||
p->SetInCombatWith(me);
|
||||
_events.ScheduleEvent(EVENT_KEEP_PLAYER_IN_COMBAT, 4s);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -301,13 +301,13 @@ public:
|
||||
if (events.GetPhaseMask() & PHASE_ONE_MASK && damage >= me->GetPower(POWER_MANA))
|
||||
{
|
||||
// reset threat
|
||||
ThreatContainer::StorageType const& threatlist = me->GetThreatMgr().GetThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatlist.begin(); itr != threatlist.end(); ++itr)
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
Unit* unit = ObjectAccessor::GetUnit((*me), (*itr)->getUnitGuid());
|
||||
|
||||
if (unit && DoGetThreat(unit))
|
||||
DoModifyThreatByPercent(unit, -100);
|
||||
if (Unit* unit = ref->GetVictim())
|
||||
{
|
||||
if (DoGetThreat(unit))
|
||||
DoModifyThreatByPercent(unit, -100);
|
||||
}
|
||||
}
|
||||
|
||||
Talk(SAY_PHASE_2);
|
||||
|
||||
@@ -209,7 +209,7 @@ public:
|
||||
|
||||
bool operator()(Unit const* target) const
|
||||
{
|
||||
if (!me || !target || !target->IsPlayer() || target == me->GetThreatMgr().GetCurrentVictim())
|
||||
if (!me || !target || !target->IsPlayer() || target == me->GetThreatMgr().GetLastVictim())
|
||||
return false;
|
||||
|
||||
if (me->IsWithinCombatRange(target, 7.0f))
|
||||
|
||||
@@ -498,7 +498,7 @@ public:
|
||||
bool Execute(uint64 /*time*/, uint32 /*diff*/) override
|
||||
{
|
||||
_owner->SetReactState(REACT_AGGRESSIVE);
|
||||
if (!_owner->GetThreatMgr().isThreatListEmpty())
|
||||
if (!_owner->GetThreatMgr().IsThreatListEmpty())
|
||||
if (Unit* target = _owner->SelectVictim())
|
||||
_owner->AI()->AttackStart(target);
|
||||
if (!_owner->GetVictim())
|
||||
@@ -1180,7 +1180,7 @@ public:
|
||||
{
|
||||
if (summon->GetEntry() == NPC_VILE_SPIRIT)
|
||||
{
|
||||
summon->m_Events.KillAllEvents(true);
|
||||
summon->m_Events.KillAllEvents(false);
|
||||
summon->m_Events.AddEventAtOffset(new VileSpiritActivateEvent(summon), 55s);
|
||||
summon->GetMotionMaster()->Clear(true);
|
||||
summon->StopMoving();
|
||||
@@ -2273,7 +2273,7 @@ public:
|
||||
{
|
||||
me->SetControlled(false, UNIT_STATE_ROOT);
|
||||
|
||||
if (!me->GetThreatMgr().isThreatListEmpty())
|
||||
if (!me->GetThreatMgr().IsThreatListEmpty())
|
||||
if (Unit* target = me->SelectVictim())
|
||||
AttackStart(target);
|
||||
if (!me->GetVictim())
|
||||
|
||||
@@ -593,12 +593,12 @@ public:
|
||||
{
|
||||
checkTimer = 3000;
|
||||
me->SetInCombatWithZone();
|
||||
ThreatContainer::StorageType const& threatList = me->GetThreatMgr().GetThreatList();
|
||||
if (!threatList.empty())
|
||||
for (ThreatContainer::StorageType::const_iterator itr = threatList.begin(); itr != threatList.end(); ++itr)
|
||||
if (Unit* target = (*itr)->getTarget())
|
||||
if (target->IsAlive() && target->IsPlayer() && me->GetExactDist(target) < 200.0f && !target->IsImmunedToDamageOrSchool(SPELL_SCHOOL_MASK_ALL))
|
||||
return;
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
if (Unit* target = ref->GetVictim())
|
||||
if (target->IsAlive() && target->IsPlayer() && me->GetExactDist(target) < 200.0f && !target->IsImmunedToDamageOrSchool(SPELL_SCHOOL_MASK_ALL))
|
||||
return;
|
||||
}
|
||||
EnterEvadeMode();
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1762,15 +1762,26 @@ public:
|
||||
Position myPos = me->GetPosition();
|
||||
me->NearTeleportTo(c->GetPositionX(), c->GetPositionY(), c->GetPositionZ(), c->GetOrientation());
|
||||
c->NearTeleportTo(myPos.GetPositionX(), myPos.GetPositionY(), myPos.GetPositionZ(), myPos.GetOrientation());
|
||||
const ThreatContainer::StorageType me_tl = me->GetThreatMgr().GetThreatList();
|
||||
const ThreatContainer::StorageType target_tl = c->GetThreatMgr().GetThreatList();
|
||||
|
||||
// Store threat values before reset
|
||||
std::vector<std::pair<Unit*, float>> myThreats;
|
||||
std::vector<std::pair<Unit*, float>> targetThreats;
|
||||
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
if (Unit* victim = ref->GetVictim())
|
||||
myThreats.push_back({victim, ref->GetThreat()});
|
||||
|
||||
for (ThreatReference const* ref : c->GetThreatMgr().GetUnsortedThreatList())
|
||||
if (Unit* victim = ref->GetVictim())
|
||||
targetThreats.push_back({victim, ref->GetThreat()});
|
||||
|
||||
DoResetThreatList();
|
||||
for (ThreatContainer::StorageType::const_iterator iter = target_tl.begin(); iter != target_tl.end(); ++iter)
|
||||
me->GetThreatMgr().AddThreat((*iter)->getTarget(), (*iter)->GetThreat());
|
||||
for (auto const& pair : targetThreats)
|
||||
me->GetThreatMgr().AddThreat(pair.first, pair.second);
|
||||
|
||||
c->GetThreatMgr().ResetAllThreat();
|
||||
for (ThreatContainer::StorageType::const_iterator iter = me_tl.begin(); iter != me_tl.end(); ++iter)
|
||||
c->GetThreatMgr().AddThreat((*iter)->getTarget(), (*iter)->GetThreat());
|
||||
for (auto const& pair : myThreats)
|
||||
c->GetThreatMgr().AddThreat(pair.first, pair.second);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -406,16 +406,19 @@ public:
|
||||
events.Repeat(15s);
|
||||
break;
|
||||
case EVENT_TELEPORT:
|
||||
{
|
||||
me->AttackStop();
|
||||
if (IN_LIVE_SIDE(me))
|
||||
{
|
||||
me->CastSpell(me, SPELL_TELEPORT_DEAD, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
me->CastSpell(me, SPELL_TELEPORT_LIVE, false);
|
||||
}
|
||||
me->GetThreatMgr().resetAggro(NotOnSameSide(me));
|
||||
|
||||
// Clear threat from targets not on the same side as Gothik
|
||||
NotOnSameSide notOnSameSide(me);
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
if (notOnSameSide(ref->GetVictim()))
|
||||
me->GetThreatMgr().ClearThreat(ref->GetVictim());
|
||||
|
||||
if (Unit* pTarget = SelectTarget(SelectTargetMethod::MaxDistance, 0))
|
||||
{
|
||||
me->GetThreatMgr().AddThreat(pTarget, 100.0f);
|
||||
@@ -423,6 +426,7 @@ public:
|
||||
}
|
||||
events.Repeat(20s);
|
||||
break;
|
||||
}
|
||||
case EVENT_CHECK_HEALTH:
|
||||
if (me->HealthBelowPct(30))
|
||||
{
|
||||
|
||||
@@ -401,15 +401,17 @@ public:
|
||||
case EVENT_DETONATE_MANA:
|
||||
{
|
||||
std::vector<Unit*> unitList;
|
||||
ThreatContainer::StorageType const& threatList = me->GetThreatMgr().GetThreatList();
|
||||
for (auto itr : threatList)
|
||||
for (ThreatReference const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
{
|
||||
if (itr->getTarget()->IsPlayer()
|
||||
&& itr->getTarget()->getPowerType() == POWER_MANA
|
||||
&& itr->getTarget()->GetPower(POWER_MANA))
|
||||
{
|
||||
unitList.push_back(itr->getTarget());
|
||||
}
|
||||
if (Unit* target = ref->GetVictim())
|
||||
{
|
||||
if (target->IsPlayer()
|
||||
&& target->getPowerType() == POWER_MANA
|
||||
&& target->GetPower(POWER_MANA))
|
||||
{
|
||||
unitList.push_back(target);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!unitList.empty())
|
||||
{
|
||||
|
||||
@@ -117,11 +117,11 @@ public:
|
||||
std::list<Unit*> meleeRangeTargets;
|
||||
Unit* finalTarget = nullptr;
|
||||
uint8 counter = 0;
|
||||
auto i = me->GetThreatMgr().GetThreatList().begin();
|
||||
for (; i != me->GetThreatMgr().GetThreatList().end(); ++i, ++counter)
|
||||
auto threatList = me->GetThreatMgr().GetSortedThreatList();
|
||||
for (auto i = threatList.begin(); i != threatList.end(); ++i, ++counter)
|
||||
{
|
||||
// Gather all units with melee range
|
||||
Unit* target = (*i)->getTarget();
|
||||
Unit* target = (*i)->GetVictim();
|
||||
if (me->IsWithinMeleeRange(target))
|
||||
{
|
||||
meleeRangeTargets.push_back(target);
|
||||
|
||||
@@ -315,17 +315,17 @@ public:
|
||||
}
|
||||
|
||||
std::vector<Unit*> targets;
|
||||
auto i = me->GetThreatMgr().GetThreatList().begin();
|
||||
for (; i != me->GetThreatMgr().GetThreatList().end(); ++i)
|
||||
auto i = me->GetThreatMgr().GetUnsortedThreatList().begin();
|
||||
for (; i != me->GetThreatMgr().GetUnsortedThreatList().end(); ++i)
|
||||
{
|
||||
if ((*i)->getTarget()->IsPlayer())
|
||||
if ((*i)->GetVictim()->IsPlayer())
|
||||
{
|
||||
bool inList = false;
|
||||
if (!blockList.empty())
|
||||
{
|
||||
for (GuidList::const_iterator itr = blockList.begin(); itr != blockList.end(); ++itr)
|
||||
{
|
||||
if ((*i)->getTarget()->GetGUID() == *itr)
|
||||
if ((*i)->GetVictim()->GetGUID() == *itr)
|
||||
{
|
||||
inList = true;
|
||||
break;
|
||||
@@ -334,7 +334,7 @@ public:
|
||||
}
|
||||
if (!inList)
|
||||
{
|
||||
targets.push_back((*i)->getTarget());
|
||||
targets.push_back((*i)->GetVictim());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,8 +128,8 @@ public:
|
||||
|
||||
bool IsAnyPlayerInMeleeRange() const
|
||||
{
|
||||
for (auto const& ref : me->GetThreatMgr().GetThreatList())
|
||||
if (Unit* target = ref->getTarget())
|
||||
for (auto const* ref : me->GetThreatMgr().GetUnsortedThreatList())
|
||||
if (Unit* target = ref->GetVictim())
|
||||
if (target->IsPlayer() && me->IsWithinMeleeRange(target))
|
||||
return true;
|
||||
return false;
|
||||
|
||||
@@ -1419,7 +1419,7 @@ public:
|
||||
{
|
||||
me->CastSpell(me, SPELL_SAC_GHOUL_EXPLODE, true);
|
||||
me->KillSelf();
|
||||
me->m_Events.KillAllEvents(true);
|
||||
me->m_Events.KillAllEvents(false);
|
||||
Deactivate();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user