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