Core/Threat: Threat system adjustments

Port From (https://github.com/TrinityCore/TrinityCore/commit/392a644dc8562ea54b9c185a2776fceb1006e2cd)
This commit is contained in:
hondacrx
2021-11-01 12:04:49 -04:00
parent 9b99019d44
commit 3f684eadf9
6 changed files with 176 additions and 158 deletions
+163 -124
View File
@@ -28,13 +28,13 @@ namespace Game.Combat
{ {
public class ThreatManager public class ThreatManager
{ {
public static uint CLIENT_THREAT_UPDATE_INTERVAL = 1000u; public static uint THREAT_UPDATE_INTERVAL = 1000u;
public Unit _owner; public Unit _owner;
bool _ownerCanHaveThreatList; bool _ownerCanHaveThreatList;
bool _ownerEngaged; bool _ownerEngaged;
uint _updateClientTimer; uint _updateTimer;
List<ThreatReference> _sortedThreatList = new(); List<ThreatReference> _sortedThreatList = new();
Dictionary<ObjectGuid, ThreatReference> _myThreatListEntries = new(); Dictionary<ObjectGuid, ThreatReference> _myThreatListEntries = new();
ThreatReference _currentVictimRef; ThreatReference _currentVictimRef;
@@ -68,7 +68,7 @@ namespace Game.Combat
public ThreatManager(Unit owner) public ThreatManager(Unit owner)
{ {
_owner = owner; _owner = owner;
_updateClientTimer = CLIENT_THREAT_UPDATE_INTERVAL; _updateTimer = THREAT_UPDATE_INTERVAL;
for (var i = 0; i < (int)SpellSchools.Max; ++i) for (var i = 0; i < (int)SpellSchools.Max; ++i)
_singleSchoolModifiers[i] = 1.0f; _singleSchoolModifiers[i] = 1.0f;
@@ -84,18 +84,21 @@ namespace Game.Combat
if (!CanHaveThreatList() || !IsEngaged()) if (!CanHaveThreatList() || !IsEngaged())
return; return;
if (_updateClientTimer <= tdiff) if (_updateTimer <= tdiff)
{ {
_updateClientTimer = CLIENT_THREAT_UPDATE_INTERVAL; UpdateVictim();
SendThreatListToClients(); _updateTimer = THREAT_UPDATE_INTERVAL;
} }
else else
_updateClientTimer -= tdiff; _updateTimer -= tdiff;
} }
public Unit GetCurrentVictim() public Unit GetCurrentVictim()
{ {
if (_currentVictimRef != null) if (_currentVictimRef != null || _currentVictimRef.ShouldBeOffline())
UpdateVictim();
if (_currentVictimRef != null && !_currentVictimRef.ShouldBeOffline())
return _currentVictimRef.GetVictim(); return _currentVictimRef.GetVictim();
return null; return null;
@@ -110,22 +113,6 @@ namespace Game.Combat
return null; return null;
} }
public Unit SelectVictim()
{
if (_sortedThreatList.Empty())
return null;
ThreatReference newVictimRef = ReselectVictim();
if (newVictimRef != _currentVictimRef)
{
if (newVictimRef != null)
SendNewVictimToClients(newVictimRef);
_currentVictimRef = newVictimRef;
}
return newVictimRef != null ? newVictimRef.GetVictim() : null;
}
public bool IsThreatListEmpty(bool includeOffline = false) public bool IsThreatListEmpty(bool includeOffline = false)
{ {
if (includeOffline) if (includeOffline)
@@ -186,14 +173,11 @@ namespace Game.Combat
public bool IsThreateningTo(Unit who, bool includeOffline = false) { return IsThreateningTo(who.GetGUID(), includeOffline); } public bool IsThreateningTo(Unit who, bool includeOffline = false) { return IsThreateningTo(who.GetGUID(), includeOffline); }
public void UpdateOnlineStates(bool meThreateningOthers, bool othersThreateningMe) public void EvaluateSuppressed()
{ {
if (othersThreateningMe) foreach (var pair in _threatenedByMe)
foreach (var pair in _myThreatListEntries) if (pair.Value.IsOnline() && pair.Value.ShouldBeSuppressed())
pair.Value.UpdateOnlineState(); pair.Value.Online = OnlineState.Suppressed;
if (meThreateningOthers)
foreach (var pair in _threatenedByMe)
pair.Value.UpdateOnlineState();
} }
static void SaveCreatureHomePositionIfNeed(Creature c) static void SaveCreatureHomePositionIfNeed(Creature c)
@@ -296,7 +280,13 @@ namespace Game.Combat
var targetRefe = _myThreatListEntries.LookupByKey(target.GetGUID()); var targetRefe = _myThreatListEntries.LookupByKey(target.GetGUID());
if (targetRefe != null) if (targetRefe != null)
{ {
targetRefe.AddThreat(amount); // causing threat causes SUPPRESSED threat states to stop being suppressed
if (targetRefe.GetOnlineState() == OnlineState.Suppressed)
if (!targetRefe.ShouldBeSuppressed())
targetRefe.Online = OnlineState.Online;
if (targetRefe.IsOnline())
targetRefe.AddThreat(amount);
return; return;
} }
@@ -307,10 +297,10 @@ namespace Game.Combat
if (!_ownerEngaged) if (!_ownerEngaged)
{ {
Creature cOwner = _owner.ToCreature(); // if we got here the owner can have a threat list, and must be a creature!
_ownerEngaged = true; _ownerEngaged = true;
Creature cOwner = _owner.ToCreature(); UpdateVictim();
Cypher.Assert(cOwner != null); // if we got here the owner can have a threat list, and must be a creature!
SaveCreatureHomePositionIfNeed(cOwner); SaveCreatureHomePositionIfNeed(cOwner);
CreatureAI ownerAI = cOwner.GetAI(); CreatureAI ownerAI = cOwner.GetAI();
if (ownerAI != null) if (ownerAI != null)
@@ -368,14 +358,22 @@ namespace Game.Combat
public void ResetAllThreat() public void ResetAllThreat()
{ {
foreach (var pair in _myThreatListEntries) foreach (var pair in _myThreatListEntries)
pair.Value.SetThreat(0.0f); pair.Value.ScaleThreat(0.0f);
} }
public void ClearThreat(Unit target) public void ClearThreat(Unit target)
{ {
var refe = _myThreatListEntries.LookupByKey(target.GetGUID()); var refe = _myThreatListEntries.LookupByKey(target.GetGUID());
if (refe != null) if (refe != null)
refe.ClearThreat(); ClearThreat(refe);
}
public void ClearThreat(ThreatReference refe)
{
SendRemoveToClients(refe.GetVictim());
refe.UnregisterAndFree();
if (_currentVictimRef == null)
UpdateVictim();
} }
public void ClearAllThreat() public void ClearAllThreat()
@@ -386,7 +384,7 @@ namespace Game.Combat
SendClearAllThreatToClients(); SendClearAllThreatToClients();
do do
_myThreatListEntries.First().Value.ClearThreat(false); _myThreatListEntries.First().Value.UnregisterAndFree();
while (!_myThreatListEntries.Empty()); while (!_myThreatListEntries.Empty());
} }
@@ -414,8 +412,24 @@ namespace Game.Combat
public void ClearFixate() { FixateTarget(null); } public void ClearFixate() { FixateTarget(null); }
void UpdateVictim()
{
ThreatReference newVictim = ReselectVictim();
bool newHighest = (newVictim != _currentVictimRef);
_currentVictimRef = newVictim;
SendThreatListToClients(newVictim != null && newHighest);
}
ThreatReference ReselectVictim() ThreatReference ReselectVictim()
{ {
if (_sortedThreatList.Empty())
return null;
foreach (var pair in _myThreatListEntries)
pair.Value.UpdateOffline();
// fixated target is always preferred // fixated target is always preferred
if (_fixateRef != null && _fixateRef.IsAvailable()) if (_fixateRef != null && _fixateRef.IsAvailable())
return _fixateRef; return _fixateRef;
@@ -538,30 +552,6 @@ namespace Game.Combat
return threat; return threat;
} }
void SendClearAllThreatToClients()
{
ThreatClear threatClear = new();
threatClear.UnitGUID = _owner.GetGUID();
_owner.SendMessageToSet(threatClear, false);
}
public void SendThreatListToClients()
{
ThreatUpdate threatUpdate = new();
threatUpdate.UnitGUID = _owner.GetGUID();
foreach (ThreatReference refe in _sortedThreatList)
{
if (!refe.IsAvailable()) // @todo check if suppressed threat should get sent for bubble/iceblock/hop etc
continue;
ThreatInfo threatInfo = new();
threatInfo.UnitGUID = refe.GetVictim().GetGUID();
threatInfo.Threat = (long)(refe.GetThreat() * 100);
threatUpdate.ThreatList.Add(threatInfo);
}
_owner.SendMessageToSet(threatUpdate, false);
}
public void ForwardThreatForAssistingMe(Unit assistant, float baseAmount, SpellInfo spell = null, bool ignoreModifiers = false) public void ForwardThreatForAssistingMe(Unit assistant, float baseAmount, SpellInfo spell = null, bool ignoreModifiers = false)
{ {
if (spell != null && spell.HasAttribute(SpellAttr1.NoThreat)) // shortcut, none of the calls would do anything if (spell != null && spell.HasAttribute(SpellAttr1.NoThreat)) // shortcut, none of the calls would do anything
@@ -570,16 +560,35 @@ namespace Game.Combat
if (_threatenedByMe.Empty()) if (_threatenedByMe.Empty())
return; return;
float perTarget = baseAmount / _threatenedByMe.Count; // Threat is divided evenly among all targets (LibThreat sourced) List<Creature> canBeThreatened = new();
List<Creature> cannotBeThreatened = new();
foreach (var pair in _threatenedByMe) foreach (var pair in _threatenedByMe)
pair.Value.GetOwner().GetThreatManager().AddThreat(assistant, perTarget, spell, ignoreModifiers); {
Creature owner = pair.Value.GetOwner();
if (!owner.HasBreakableByDamageCrowdControlAura())
canBeThreatened.Add(owner);
else
cannotBeThreatened.Add(owner);
}
if (!canBeThreatened.Empty()) // targets under CC cannot gain assist threat - split evenly among the rest
{
float perTarget = baseAmount / canBeThreatened.Count;
foreach (Creature threatened in canBeThreatened)
threatened.GetThreatManager().AddThreat(assistant, perTarget, spell, ignoreModifiers);
}
foreach (Creature threatened in cannotBeThreatened)
threatened.GetThreatManager().AddThreat(assistant, 0.0f, spell, true);
} }
public void RemoveMeFromThreatLists() public void RemoveMeFromThreatLists()
{ {
while (!_threatenedByMe.Empty()) while (!_threatenedByMe.Empty())
_threatenedByMe.First().Value.ClearThreat(); {
var refe = _threatenedByMe.FirstOrDefault().Value;
refe._mgr.ClearThreat(_owner);
}
} }
public void UpdateMyTempModifiers() public void UpdateMyTempModifiers()
@@ -588,9 +597,12 @@ namespace Game.Combat
foreach (AuraEffect eff in _owner.GetAuraEffectsByType(AuraType.ModTotalThreat)) foreach (AuraEffect eff in _owner.GetAuraEffectsByType(AuraType.ModTotalThreat))
mod += eff.GetAmount(); mod += eff.GetAmount();
if (_threatenedByMe.Empty())
return;
foreach (var pair in _threatenedByMe) foreach (var pair in _threatenedByMe)
{ {
pair.Value._tempModifier = mod; pair.Value.TempModifier = mod;
pair.Value.ListNotifyChanged(); pair.Value.ListNotifyChanged();
} }
} }
@@ -627,6 +639,13 @@ namespace Game.Combat
UpdateRedirectInfo(); UpdateRedirectInfo();
} }
void SendClearAllThreatToClients()
{
ThreatClear threatClear = new();
threatClear.UnitGUID = _owner.GetGUID();
_owner.SendMessageToSet(threatClear, false);
}
public void SendRemoveToClients(Unit victim) public void SendRemoveToClients(Unit victim)
{ {
ThreatRemove threatRemove = new(); ThreatRemove threatRemove = new();
@@ -635,22 +654,37 @@ namespace Game.Combat
_owner.SendMessageToSet(threatRemove, false); _owner.SendMessageToSet(threatRemove, false);
} }
void SendNewVictimToClients(ThreatReference victimRef) void SendThreatListToClients(bool newHighest)
{ {
HighestThreatUpdate highestThreatUpdate = new(); void fillSharedPacketDataAndSend(dynamic packet)
highestThreatUpdate.UnitGUID = _owner.GetGUID();
highestThreatUpdate.HighestThreatGUID = victimRef.GetVictim().GetGUID();
foreach (ThreatReference refe in _sortedThreatList)
{ {
if (!refe.IsAvailable()) packet.UnitGUID = _owner.GetGUID();
continue; packet.ThreatList.reserve(_sortedThreatList.Count);
ThreatInfo threatInfo = new(); foreach (ThreatReference refe in _sortedThreatList)
threatInfo.UnitGUID = refe.GetVictim().GetGUID(); {
threatInfo.Threat = (long)(refe.GetThreat() * 100); if (!refe.IsAvailable())
highestThreatUpdate.ThreatList.Add(threatInfo); continue;
ThreatInfo threatInfo = new();
threatInfo.UnitGUID = refe.GetVictim().GetGUID();
threatInfo.Threat = (long)(refe.GetThreat() * 100);
packet.ThreatList.Add(threatInfo);
}
_owner.SendMessageToSet(packet, false);
}
if (newHighest)
{
HighestThreatUpdate highestThreatUpdate = new();
highestThreatUpdate.HighestThreatGUID = _currentVictimRef.GetVictim().GetGUID();
fillSharedPacketDataAndSend(highestThreatUpdate);
}
else
{
ThreatUpdate threatUpdate = new();
fillSharedPacketDataAndSend(threatUpdate);
} }
_owner.SendMessageToSet(highestThreatUpdate, false);
} }
void PutThreatListRef(ObjectGuid guid, ThreatReference refe) void PutThreatListRef(ObjectGuid guid, ThreatReference refe)
@@ -661,23 +695,20 @@ namespace Game.Combat
_sortedThreatList.Sort(); _sortedThreatList.Sort();
} }
public void PurgeThreatListRef(ObjectGuid guid, bool sendRemove) public void PurgeThreatListRef(ObjectGuid guid)
{ {
var refe = _myThreatListEntries.LookupByKey(guid); var refe = _myThreatListEntries.LookupByKey(guid);
if (refe == null) if (refe == null)
return; return;
_myThreatListEntries.Remove(guid); _myThreatListEntries.Remove(guid);
_sortedThreatList.Remove(refe);
if (_currentVictimRef == refe)
_currentVictimRef = null;
if (_fixateRef == refe) if (_fixateRef == refe)
_fixateRef = null; _fixateRef = null;
_sortedThreatList.Remove(refe); if (_currentVictimRef == refe)
_sortedThreatList.Sort(); _currentVictimRef = null;
if (sendRemove && refe.IsAvailable())
SendRemoveToClients(refe.GetVictim());
} }
void PutThreatenedByMeRef(ObjectGuid guid, ThreatReference refe) void PutThreatenedByMeRef(ObjectGuid guid, ThreatReference refe)
@@ -759,21 +790,21 @@ namespace Game.Combat
public class ThreatReference : IComparable<ThreatReference> public class ThreatReference : IComparable<ThreatReference>
{ {
Unit _owner; Creature _owner;
ThreatManager _mgr; public ThreatManager _mgr;
Unit _victim; Unit _victim;
public OnlineState Online;
float _baseAmount; float _baseAmount;
public int _tempModifier; // Temporary effects (auras with SPELL_AURA_MOD_TOTAL_THREAT) - set from victim's threatmanager in ThreatManager::UpdateMyTempModifiers public int TempModifier; // Temporary effects (auras with SPELL_AURA_MOD_TOTAL_THREAT) - set from victim's threatmanager in ThreatManager::UpdateMyTempModifiers
OnlineState _online;
TauntState _taunted; TauntState _taunted;
public ThreatReference(ThreatManager mgr, Unit victim, float amount) public ThreatReference(ThreatManager mgr, Unit victim, float amount)
{ {
_owner = mgr._owner; _owner = mgr._owner as Creature;
_mgr = mgr; _mgr = mgr;
_victim = victim; _victim = victim;
_baseAmount = amount; Online = ShouldBeOffline() ? OnlineState.Offline : ShouldBeSuppressed() ? OnlineState.Suppressed : OnlineState.Online;
_online = SelectOnlineState(); _baseAmount = IsOnline() ? amount : 0.0f;
} }
public void AddThreat(float amount) public void AddThreat(float amount)
@@ -794,17 +825,23 @@ namespace Game.Combat
ListNotifyChanged(); ListNotifyChanged();
} }
public void UpdateOnlineState() public void UpdateOffline()
{ {
OnlineState onlineState = SelectOnlineState(); bool shouldBeOffline = ShouldBeOffline();
if (onlineState == _online) if (shouldBeOffline == IsOffline())
return; return;
_online = onlineState; if (shouldBeOffline)
ListNotifyChanged(); {
Online = OnlineState.Offline;
if (!IsAvailable()) ListNotifyChanged();
_owner.GetThreatManager().SendRemoveToClients(_victim); _mgr.SendRemoveToClients(_victim);
}
else
{
Online = ShouldBeSuppressed() ? OnlineState.Suppressed : OnlineState.Online;
ListNotifyChanged();
}
} }
public static bool FlagsAllowFighting(Unit a, Unit b) public static bool FlagsAllowFighting(Unit a, Unit b)
@@ -825,31 +862,28 @@ namespace Game.Combat
return true; return true;
} }
OnlineState SelectOnlineState() public bool ShouldBeOffline()
{ {
// first, check all offline conditions if (!_owner.CanSeeOrDetect(_victim))
if (!_owner.CanSeeOrDetect(_victim)) // not in map/phase, or stealth/invis return true;
return OnlineState.Offline;
if (_victim.HasUnitState(UnitState.Died)) // feign death if (!_owner._IsTargetAcceptable(_victim) || !_owner.CanCreatureAttack(_victim))
return OnlineState.Offline; return true;
if (!FlagsAllowFighting(_owner, _victim) || !FlagsAllowFighting(_victim, _owner)) if (!FlagsAllowFighting(_owner, _victim) || !FlagsAllowFighting(_victim, _owner))
return OnlineState.Offline; return true;
if (_owner.IsAIEnabled() && !_owner.GetAI().CanAIAttack(_victim)) return false;
return OnlineState.Offline; }
// next, check suppression (immunity to chosen melee attack school) public bool ShouldBeSuppressed()
{
if (_victim.IsImmunedToDamage(_owner.GetMeleeDamageSchoolMask())) if (_victim.IsImmunedToDamage(_owner.GetMeleeDamageSchoolMask()))
return OnlineState.Suppressed; return true;
// or any form of CC that will break on damage - disorient, polymorph, blind etc
if (_victim.HasBreakableByDamageCrowdControlAura()) if (_victim.HasBreakableByDamageCrowdControlAura())
return OnlineState.Suppressed; return true;
// no suppression - we're online return false;
return OnlineState.Online;
} }
public void UpdateTauntState(TauntState state = TauntState.None) public void UpdateTauntState(TauntState state = TauntState.None)
@@ -866,19 +900,24 @@ namespace Game.Combat
ListNotifyChanged(); ListNotifyChanged();
} }
public void ClearThreat(bool sendRemove = true) public void ClearThreat()
{ {
_owner.GetThreatManager().PurgeThreatListRef(_victim.GetGUID(), sendRemove); _mgr.ClearThreat(this);
}
public void UnregisterAndFree()
{
_owner.GetThreatManager().PurgeThreatListRef(_victim.GetGUID());
_victim.GetThreatManager().PurgeThreatenedByMeRef(_owner.GetGUID()); _victim.GetThreatManager().PurgeThreatenedByMeRef(_owner.GetGUID());
} }
public Unit GetOwner() { return _owner; } public Creature GetOwner() { return _owner; }
public Unit GetVictim() { return _victim; } public Unit GetVictim() { return _victim; }
public float GetThreat() { return Math.Max(_baseAmount + (float)_tempModifier, 0.0f); } public float GetThreat() { return Math.Max(_baseAmount + (float)TempModifier, 0.0f); }
public OnlineState GetOnlineState() { return _online; } public OnlineState GetOnlineState() { return Online; }
public bool IsOnline() { return (_online >= OnlineState.Online); } public bool IsOnline() { return Online >= OnlineState.Online; }
public bool IsAvailable() { return (_online > OnlineState.Offline); } public bool IsAvailable() { return Online > OnlineState.Offline; }
public bool IsOffline() { return (_online <= OnlineState.Offline); } public bool IsOffline() { return Online <= OnlineState.Offline; }
public TauntState GetTauntState() { return IsTaunting() ? TauntState.Taunt : _taunted; } public TauntState GetTauntState() { return IsTaunting() ? TauntState.Taunt : _taunted; }
public bool IsTaunting() { return _taunted >= TauntState.Taunt; } public bool IsTaunting() { return _taunted >= TauntState.Taunt; }
public bool IsDetaunted() { return _taunted == TauntState.Detaunt; } public bool IsDetaunted() { return _taunted == TauntState.Detaunt; }
+2 -3
View File
@@ -417,7 +417,7 @@ namespace Game.Entities
LoadCreaturesAddon(); LoadCreaturesAddon();
LoadTemplateImmunities(); LoadTemplateImmunities();
GetThreatManager().UpdateOnlineStates(true, true); GetThreatManager().EvaluateSuppressed();
return true; return true;
} }
@@ -541,7 +541,6 @@ namespace Game.Entities
if (diff >= m_boundaryCheckTime) if (diff >= m_boundaryCheckTime)
{ {
GetAI().CheckInRoom(); GetAI().CheckInRoom();
GetThreatManager().UpdateOnlineStates(false, true);
m_boundaryCheckTime = 2500; m_boundaryCheckTime = 2500;
} }
else else
@@ -898,7 +897,7 @@ namespace Game.Entities
Unit target; Unit target;
if (CanHaveThreatList()) if (CanHaveThreatList())
target = GetThreatManager().SelectVictim(); target = GetThreatManager().GetCurrentVictim();
else if (!HasReactState(ReactStates.Passive)) else if (!HasReactState(ReactStates.Passive))
{ {
// We're a player pet, probably // We're a player pet, probably
-2
View File
@@ -152,8 +152,6 @@ namespace Game.Entities
public bool CanHaveThreatList() { return m_threatManager.CanHaveThreatList(); } public bool CanHaveThreatList() { return m_threatManager.CanHaveThreatList(); }
void SendThreatListUpdate() { m_threatManager.SendThreatListToClients(); }
// For NPCs with threat list: Whether there are any enemies on our threat list // For NPCs with threat list: Whether there are any enemies on our threat list
// For other units: Whether we're in combat // For other units: Whether we're in combat
// This value is different from IsInCombat when a projectile spell is midair (combat on launch - threat+aggro on impact) // This value is different from IsInCombat when a projectile spell is midair (combat on launch - threat+aggro on impact)
+3 -19
View File
@@ -419,7 +419,6 @@ namespace Game.Entities
AddToNotify(NotifyFlags.VisibilityChanged); AddToNotify(NotifyFlags.VisibilityChanged);
else else
{ {
m_threatManager.UpdateOnlineStates(true, true);
base.UpdateObjectVisibility(true); base.UpdateObjectVisibility(true);
// call MoveInLineOfSight for nearby creatures // call MoveInLineOfSight for nearby creatures
AIRelocationNotifier notifier = new(this); AIRelocationNotifier notifier = new(this);
@@ -2882,16 +2881,11 @@ namespace Game.Entities
{ {
AddUnitFlag(UnitFlags.ImmuneToPc | UnitFlags.ImmuneToNpc); AddUnitFlag(UnitFlags.ImmuneToPc | UnitFlags.ImmuneToNpc);
ValidateAttackersAndOwnTarget(); ValidateAttackersAndOwnTarget();
if (keepCombat) if (!keepCombat)
m_threatManager.UpdateOnlineStates(true, true);
else
m_combatManager.EndAllCombat(); m_combatManager.EndAllCombat();
} }
else else
{
RemoveUnitFlag(UnitFlags.ImmuneToPc | UnitFlags.ImmuneToNpc); RemoveUnitFlag(UnitFlags.ImmuneToPc | UnitFlags.ImmuneToNpc);
m_threatManager.UpdateOnlineStates(true, true);
}
} }
public virtual void SetImmuneToAll(bool apply) { SetImmuneToAll(apply, false); } public virtual void SetImmuneToAll(bool apply) { SetImmuneToAll(apply, false); }
@@ -2904,9 +2898,7 @@ namespace Game.Entities
{ {
AddUnitFlag(UnitFlags.ImmuneToPc); AddUnitFlag(UnitFlags.ImmuneToPc);
ValidateAttackersAndOwnTarget(); ValidateAttackersAndOwnTarget();
if (keepCombat) if (!keepCombat)
m_threatManager.UpdateOnlineStates(true, true);
else
{ {
List<CombatReference> toEnd = new(); List<CombatReference> toEnd = new();
foreach (var pair in m_combatManager.GetPvECombatRefs()) foreach (var pair in m_combatManager.GetPvECombatRefs())
@@ -2922,10 +2914,7 @@ namespace Game.Entities
} }
} }
else else
{
RemoveUnitFlag(UnitFlags.ImmuneToPc); RemoveUnitFlag(UnitFlags.ImmuneToPc);
m_threatManager.UpdateOnlineStates(true, true);
}
} }
public virtual void SetImmuneToPC(bool apply) { SetImmuneToPC(apply, false); } public virtual void SetImmuneToPC(bool apply) { SetImmuneToPC(apply, false); }
@@ -2938,9 +2927,7 @@ namespace Game.Entities
{ {
AddUnitFlag(UnitFlags.ImmuneToNpc); AddUnitFlag(UnitFlags.ImmuneToNpc);
ValidateAttackersAndOwnTarget(); ValidateAttackersAndOwnTarget();
if (keepCombat) if (!keepCombat)
m_threatManager.UpdateOnlineStates(true, true);
else
{ {
List<CombatReference> toEnd = new(); List<CombatReference> toEnd = new();
foreach (var pair in m_combatManager.GetPvECombatRefs()) foreach (var pair in m_combatManager.GetPvECombatRefs())
@@ -2956,10 +2943,7 @@ namespace Game.Entities
} }
} }
else else
{
RemoveUnitFlag(UnitFlags.ImmuneToNpc); RemoveUnitFlag(UnitFlags.ImmuneToNpc);
m_threatManager.UpdateOnlineStates(true, true);
}
} }
public virtual void SetImmuneToNPC(bool apply) { SetImmuneToNPC(apply, false); } public virtual void SetImmuneToNPC(bool apply) { SetImmuneToNPC(apply, false); }
+7 -9
View File
@@ -1581,7 +1581,7 @@ namespace Game.Spells
} }
} }
target.GetThreatManager().UpdateOnlineStates(true, false); target.GetThreatManager().EvaluateSuppressed();
} }
[AuraEffectHandler(AuraType.ModScale)] [AuraEffectHandler(AuraType.ModScale)]
@@ -1696,8 +1696,6 @@ namespace Game.Spells
if (creature != null) if (creature != null)
creature.InitializeReactState(); creature.InitializeReactState();
} }
target.GetThreatManager().UpdateOnlineStates(true, false);
} }
[AuraEffectHandler(AuraType.ModUnattackable)] [AuraEffectHandler(AuraType.ModUnattackable)]
@@ -2383,7 +2381,7 @@ namespace Game.Spells
Unit target = aurApp.GetTarget(); Unit target = aurApp.GetTarget();
target.SetControlled(apply, UnitState.Confused); target.SetControlled(apply, UnitState.Confused);
target.GetThreatManager().UpdateOnlineStates(true, false); target.GetThreatManager().EvaluateSuppressed();
} }
[AuraEffectHandler(AuraType.ModFear)] [AuraEffectHandler(AuraType.ModFear)]
@@ -2395,7 +2393,7 @@ namespace Game.Spells
Unit target = aurApp.GetTarget(); Unit target = aurApp.GetTarget();
target.SetControlled(apply, UnitState.Fleeing); target.SetControlled(apply, UnitState.Fleeing);
target.GetThreatManager().UpdateOnlineStates(true, false); target.GetThreatManager().EvaluateSuppressed();
} }
[AuraEffectHandler(AuraType.ModStun)] [AuraEffectHandler(AuraType.ModStun)]
@@ -2407,7 +2405,7 @@ namespace Game.Spells
Unit target = aurApp.GetTarget(); Unit target = aurApp.GetTarget();
target.SetControlled(apply, UnitState.Stunned); target.SetControlled(apply, UnitState.Stunned);
target.GetThreatManager().UpdateOnlineStates(true, false); target.GetThreatManager().EvaluateSuppressed();
} }
[AuraEffectHandler(AuraType.ModRoot)] [AuraEffectHandler(AuraType.ModRoot)]
@@ -2420,7 +2418,7 @@ namespace Game.Spells
Unit target = aurApp.GetTarget(); Unit target = aurApp.GetTarget();
target.SetControlled(apply, UnitState.Root); target.SetControlled(apply, UnitState.Root);
target.GetThreatManager().UpdateOnlineStates(true, false); target.GetThreatManager().EvaluateSuppressed();
} }
[AuraEffectHandler(AuraType.PreventsFleeing)] [AuraEffectHandler(AuraType.PreventsFleeing)]
@@ -2817,7 +2815,7 @@ namespace Game.Spells
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.StealthOrInvis); target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.StealthOrInvis);
} }
target.GetThreatManager().UpdateOnlineStates(true, false); target.GetThreatManager().EvaluateSuppressed();
} }
[AuraEffectHandler(AuraType.DamageImmunity)] [AuraEffectHandler(AuraType.DamageImmunity)]
@@ -2829,7 +2827,7 @@ namespace Game.Spells
Unit target = aurApp.GetTarget(); Unit target = aurApp.GetTarget();
m_spellInfo.ApplyAllSpellImmunitiesTo(target, GetSpellEffectInfo(), apply); m_spellInfo.ApplyAllSpellImmunitiesTo(target, GetSpellEffectInfo(), apply);
target.GetThreatManager().UpdateOnlineStates(true, false); target.GetThreatManager().EvaluateSuppressed();
} }
[AuraEffectHandler(AuraType.DispelImmunity)] [AuraEffectHandler(AuraType.DispelImmunity)]
+1 -1
View File
@@ -3217,7 +3217,7 @@ namespace Game.Spells
{ {
// in dungeons (or for nonplayers), reset this unit on all enemies' threat lists // in dungeons (or for nonplayers), reset this unit on all enemies' threat lists
foreach (var pair in unitTarget.GetThreatManager().GetThreatenedByMeList()) foreach (var pair in unitTarget.GetThreatManager().GetThreatenedByMeList())
pair.Value.SetThreat(0.0f); pair.Value.ScaleThreat(0.0f);
} }
// makes spells cast before this time fizzle // makes spells cast before this time fizzle