Core/Entities: Kick engagement logic upstairs to Unit (from ThreatManager), since all Units with AI need it (not just those with threat list).

Port From (https://github.com/TrinityCore/TrinityCore/commit/35e55f10899712435102764671241b94a2026599)
This commit is contained in:
hondacrx
2021-12-23 20:00:45 -05:00
parent ff48f2cab9
commit 8694a2ae24
6 changed files with 49 additions and 42 deletions
+5 -3
View File
@@ -934,7 +934,7 @@ namespace Game.Chat
{ {
if (!mgr.IsThreatListEmpty(true)) if (!mgr.IsThreatListEmpty(true))
{ {
if (mgr.IsEngaged()) if (target.IsEngaged())
handler.SendSysMessage($"Threat list of {target.GetName()} ({target.GetGUID()}, SpawnID {(target.IsCreature() ? target.ToCreature().GetSpawnId() : 0)}):"); handler.SendSysMessage($"Threat list of {target.GetName()} ({target.GetGUID()}, SpawnID {(target.IsCreature() ? target.ToCreature().GetSpawnId() : 0)}):");
else else
handler.SendSysMessage($"{target.GetName()} ({target.GetGUID()}, SpawnID {(target.IsCreature() ? target.ToCreature().GetSpawnId() : 0)}) is not engaged, but still has a threat list? Well, here it is:"); handler.SendSysMessage($"{target.GetName()} ({target.GetGUID()}, SpawnID {(target.IsCreature() ? target.ToCreature().GetSpawnId() : 0)}) is not engaged, but still has a threat list? Well, here it is:");
@@ -948,13 +948,15 @@ namespace Game.Chat
} }
handler.SendSysMessage("End of threat list."); handler.SendSysMessage("End of threat list.");
} }
else if (!mgr.IsEngaged()) else if (!target.IsEngaged())
handler.SendSysMessage($"{target.GetName()} ({target.GetGUID()}, SpawnID {(target.IsCreature() ? target.ToCreature().GetSpawnId() : 0)}) is not currently engaged."); handler.SendSysMessage($"{target.GetName()} ({target.GetGUID()}, SpawnID {(target.IsCreature() ? target.ToCreature().GetSpawnId() : 0)}) is not currently engaged.");
else else
handler.SendSysMessage($"{target.GetName()} ({target.GetGUID()}, SpawnID {(target.IsCreature() ? target.ToCreature().GetSpawnId() : 0)}) seems to be engaged, but does not have a threat list??"); handler.SendSysMessage($"{target.GetName()} ({target.GetGUID()}, SpawnID {(target.IsCreature() ? target.ToCreature().GetSpawnId() : 0)}) seems to be engaged, but does not have a threat list??");
} }
else if (target.IsEngaged())
handler.SendSysMessage($"{target.GetName()} ({target.GetGUID()}) is currently engaged. (This unit cannot have a threat list.)");
else else
handler.SendSysMessage($"{target.GetName()} ({target.GetGUID()}) cannot have a threat list."); handler.SendSysMessage($"{target.GetName()} ({target.GetGUID()}) is not currently engaged. (This unit cannot have a threat list.)");
return true; return true;
} }
+4
View File
@@ -277,11 +277,15 @@ namespace Game.Combat
{ {
_owner.AddUnitFlag(UnitFlags.InCombat); _owner.AddUnitFlag(UnitFlags.InCombat);
_owner.AtEnterCombat(); _owner.AtEnterCombat();
if (!_owner.CanHaveThreatList() && !_owner.IsEngaged())
_owner.AtEngage(GetAnyTarget());
} }
else else
{ {
_owner.RemoveUnitFlag(UnitFlags.InCombat); _owner.RemoveUnitFlag(UnitFlags.InCombat);
_owner.AtExitCombat(); _owner.AtExitCombat();
if (_owner.IsEngaged() && !(_owner.IsCreature() && _owner.ToCreature().IsAIEnabled()))
_owner.AtDisengage();
} }
Unit master = _owner.GetCharmerOrOwner(); Unit master = _owner.GetCharmerOrOwner();
+14 -31
View File
@@ -32,7 +32,6 @@ namespace Game.Combat
public Unit _owner; public Unit _owner;
bool _ownerCanHaveThreatList; bool _ownerCanHaveThreatList;
bool _ownerEngaged;
public bool NeedClientUpdate; public bool NeedClientUpdate;
uint _updateTimer; uint _updateTimer;
@@ -82,7 +81,7 @@ namespace Game.Combat
public void Update(uint tdiff) public void Update(uint tdiff)
{ {
if (!CanHaveThreatList() || !IsEngaged()) if (!CanHaveThreatList() || IsThreatListEmpty())
return; return;
if (_updateTimer <= tdiff) if (_updateTimer <= tdiff)
@@ -192,13 +191,6 @@ namespace Game.Combat
} }
} }
static void SaveCreatureHomePositionIfNeed(Creature c)
{
MovementGeneratorType movetype = c.GetMotionMaster().GetCurrentMovementGeneratorType();
if (movetype == MovementGeneratorType.Waypoint || movetype == MovementGeneratorType.Point || (c.IsAIEnabled() && c.GetAI().IsEscorted()))
c.SetHomePosition(c.GetPosition());
}
public void AddThreat(Unit target, float amount, SpellInfo spell = null, bool ignoreModifiers = false, bool ignoreRedirects = false) public void AddThreat(Unit target, float amount, SpellInfo spell = null, bool ignoreModifiers = false, bool ignoreRedirects = false)
{ {
// step 1: we can shortcut if the spell has one of the NO_THREAT attrs set - nothing will happen // step 1: we can shortcut if the spell has one of the NO_THREAT attrs set - nothing will happen
@@ -317,20 +309,10 @@ namespace Game.Combat
if (newRefe.IsOnline()) // ...and if the ref is online it also gets the threat it should have if (newRefe.IsOnline()) // ...and if the ref is online it also gets the threat it should have
newRefe.AddThreat(amount); newRefe.AddThreat(amount);
if (!_ownerEngaged) if (!_owner.IsEngaged())
{ {
Creature cOwner = _owner.ToCreature(); // if we got here the owner can have a threat list, and must be a creature! _owner.AtEngage(target);
_ownerEngaged = true;
UpdateVictim(); UpdateVictim();
SaveCreatureHomePositionIfNeed(cOwner);
CreatureAI ownerAI = cOwner.GetAI();
if (ownerAI != null)
ownerAI.JustEngagedWith(target);
CreatureGroup formation = cOwner.GetFormation();
if (formation != null)
formation.MemberEngagingTarget(cOwner, target);
} }
} }
@@ -407,14 +389,17 @@ namespace Game.Combat
public void ClearAllThreat() public void ClearAllThreat()
{ {
_ownerEngaged = false; if (!_myThreatListEntries.Empty())
if (_myThreatListEntries.Empty()) {
return; SendClearAllThreatToClients();
do
SendClearAllThreatToClients(); _myThreatListEntries.FirstOrDefault().Value.UnregisterAndFree();
do while (!_myThreatListEntries.Empty());
_myThreatListEntries.First().Value.UnregisterAndFree(); }
while (!_myThreatListEntries.Empty()); // note: i don't really like having this here
// (maybe engage flag should be in creature ai? it's inherently an AI property...)
if (_owner.IsEngaged())
_owner.AtDisengage();
} }
public void FixateTarget(Unit target) public void FixateTarget(Unit target)
@@ -783,8 +768,6 @@ namespace Game.Combat
// identical to ThreatManager::CanHaveThreatList(GetOwner()) // identical to ThreatManager::CanHaveThreatList(GetOwner())
public bool CanHaveThreatList() { return _ownerCanHaveThreatList; } public bool CanHaveThreatList() { return _ownerCanHaveThreatList; }
public bool IsEngaged() { return _ownerEngaged; }
public int GetThreatListSize() { return _sortedThreatList.Count; } public int GetThreatListSize() { return _sortedThreatList.Count; }
// fastest of the three threat list getters - gets the threat list in "arbitrary" order // fastest of the three threat list getters - gets the threat list in "arbitrary" order
+16 -4
View File
@@ -1042,9 +1042,9 @@ namespace Game.Entities
&& !GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.NoXpAtKill); && !GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.NoXpAtKill);
} }
public override void AtEnterCombat() public override void AtEngage(Unit target)
{ {
base.AtEnterCombat(); base.AtEngage(target);
if (!GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.MountedCombatAllowed)) if (!GetCreatureTemplate().TypeFlags.HasAnyFlag(CreatureTypeFlags.MountedCombatAllowed))
Dismount(); Dismount();
@@ -1055,11 +1055,23 @@ namespace Game.Entities
UpdateSpeed(UnitMoveType.Swim); UpdateSpeed(UnitMoveType.Swim);
UpdateSpeed(UnitMoveType.Flight); UpdateSpeed(UnitMoveType.Flight);
} }
MovementGeneratorType movetype = GetMotionMaster().GetCurrentMovementGeneratorType();
if (movetype == MovementGeneratorType.Waypoint || movetype == MovementGeneratorType.Point || (IsAIEnabled() && GetAI().IsEscorted()))
SetHomePosition(GetPosition());
CreatureAI ai = GetAI();
if (ai != null)
ai.JustEngagedWith(target);
CreatureGroup formation = GetFormation();
if (formation != null)
formation.MemberEngagingTarget(this, target);
} }
public override void AtExitCombat() public override void AtDisengage()
{ {
base.AtExitCombat(); base.AtDisengage();
ClearUnitState(UnitState.AttackPlayer); ClearUnitState(UnitState.AttackPlayer);
if (HasDynamicFlag(UnitDynFlags.Tapped)) if (HasDynamicFlag(UnitDynFlags.Tapped))
+7 -4
View File
@@ -57,6 +57,9 @@ namespace Game.Entities
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.LeavingCombat); RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.LeavingCombat);
} }
public virtual void AtEngage(Unit target) { m_isEngaged = true; }
public virtual void AtDisengage() { m_isEngaged = false; }
public void CombatStop(bool includingCast = false, bool mutualPvP = true) public void CombatStop(bool includingCast = false, bool mutualPvP = true)
{ {
if (includingCast && IsNonMeleeSpellCast(false)) if (includingCast && IsNonMeleeSpellCast(false))
@@ -144,10 +147,10 @@ namespace Game.Entities
public bool CanHaveThreatList() { return m_threatManager.CanHaveThreatList(); } public bool CanHaveThreatList() { return m_threatManager.CanHaveThreatList(); }
// For NPCs with threat list: Whether there are any enemies on our threat list // This value can be different from IsInCombat:
// For other units: Whether we're in combat // - when a projectile spell is midair against a creature (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) // - when the creature has no targets left, but the AI has not yet ceased engaged logic
public bool IsEngaged() { return CanHaveThreatList() ? m_threatManager.IsEngaged() : IsInCombat(); } public bool IsEngaged() { return m_isEngaged; }
public bool IsEngagedBy(Unit who) { return CanHaveThreatList() ? IsThreatenedBy(who) : IsInCombatWith(who); } public bool IsEngagedBy(Unit who) { return CanHaveThreatList() ? IsThreatenedBy(who) : IsInCombatWith(who); }
+3
View File
@@ -54,6 +54,9 @@ namespace Game.Entities
internal float[] m_modAttackSpeedPct = new float[(int)WeaponAttackType.Max]; internal float[] m_modAttackSpeedPct = new float[(int)WeaponAttackType.Max];
protected uint[] m_attackTimer = new uint[(int)WeaponAttackType.Max]; protected uint[] m_attackTimer = new uint[(int)WeaponAttackType.Max];
// Threat+combat management
bool m_isEngaged;
CombatManager m_combatManager; CombatManager m_combatManager;
ThreatManager m_threatManager; ThreatManager m_threatManager;