Combat/Threat rewrite - prep & refactor

Port From (https://github.com/TrinityCore/TrinityCore/commit/8be23fcbbdf26e8169defd761e61765f301bebe0)
This commit is contained in:
hondacrx
2020-08-22 11:58:19 -04:00
parent 67bacbb731
commit 193ad3a48d
42 changed files with 533 additions and 421 deletions
+8 -21
View File
@@ -475,7 +475,7 @@ namespace Game.Entities
}
// periodic check to see if the creature has passed an evade boundary
if (IsAIEnabled && !IsInEvadeMode() && IsInCombat())
if (IsAIEnabled && !IsInEvadeMode() && IsEngaged())
{
if (diff >= m_boundaryCheckTime)
{
@@ -487,7 +487,7 @@ namespace Game.Entities
}
// if periodic combat pulse is enabled and we are both in combat and in a dungeon, do this now
if (m_combatPulseDelay > 0 && IsInCombat() && GetMap().IsDungeon())
if (m_combatPulseDelay > 0 && IsEngaged() && GetMap().IsDungeon())
{
if (diff > m_combatPulseTime)
m_combatPulseTime = 0;
@@ -503,12 +503,7 @@ namespace Game.Entities
continue;
if (player.IsAlive() && IsHostileTo(player))
{
if (CanHaveThreatList())
AddThreat(player, 0.0f);
SetInCombatWith(player);
player.SetInCombatWith(this);
}
EngageWithTarget(player);
}
m_combatPulseTime = m_combatPulseDelay * Time.InMilliseconds;
}
@@ -1484,7 +1479,7 @@ namespace Game.Entities
if (!_IsTargetAcceptable(who))
return false;
if (who.IsInCombat() && IsWithinDist(who, SharedConst.AttackDistance))
if (who.IsEngaged() && IsWithinDist(who, SharedConst.AttackDistance))
{
Unit victim = who.GetAttackerForHelper();
if (victim != null)
@@ -2022,7 +2017,7 @@ namespace Game.Entities
return false;
// skip fighting creature
if (IsInCombat())
if (IsEngaged())
return false;
// only free creature
@@ -2067,7 +2062,7 @@ namespace Game.Entities
Unit targetVictim = target.GetAttackerForHelper();
// if I'm already fighting target, or I'm hostile towards the target, the target is acceptable
if (IsInCombatWith(target) || IsHostileTo(target))
if (IsEngagedBy(target) || IsHostileTo(target))
return true;
// if the target's victim is friendly, and the target is neutral, the target is acceptable
@@ -2256,7 +2251,6 @@ namespace Game.Entities
}
var PlList = map.GetPlayers();
if (PlList.Empty())
return;
@@ -2266,12 +2260,7 @@ namespace Game.Entities
continue;
if (player.IsAlive())
{
SetInCombatWith(player);
player.SetInCombatWith(this);
AddThreat(player, 0.0f);
}
EngageWithTarget(player);
}
}
@@ -3270,9 +3259,7 @@ namespace Game.Entities
if (assistant != null && assistant.CanAssistTo(m_owner, victim))
{
assistant.SetNoCallAssistance(true);
assistant.CombatStart(victim);
if (assistant.IsAIEnabled)
assistant.GetAI().AttackStart(victim);
assistant.EngageWithTarget(victim);
}
}
}
@@ -170,7 +170,7 @@ namespace Game.Entities
member.SetFormation(null);
}
public void MemberAttackStart(Creature member, Unit target)
public void MemberEngagingTarget(Creature member, Unit target)
{
GroupAIFlags groupAI = (GroupAIFlags)FormationMgr.CreatureGroupMap[member.GetSpawnId()].groupAI;
if (groupAI == 0)
@@ -186,9 +186,6 @@ namespace Game.Entities
foreach (var pair in m_members)
{
if (m_leader) // avoid crash if leader was killed and reset.
Log.outDebug(LogFilter.Unit, "GROUP ATTACK: group instance id {0} calls member instid {1}", m_leader.GetInstanceId(), member.GetInstanceId());
Creature other = pair.Key;
// Skip self
@@ -198,11 +195,8 @@ namespace Game.Entities
if (!other.IsAlive())
continue;
if (other.GetVictim())
continue;
if (((other != m_leader && groupAI.HasAnyFlag(GroupAIFlags.MembersAssistLeader)) || (other == m_leader && groupAI.HasAnyFlag(GroupAIFlags.LeaderAssistsMember))) && other.IsValidAttackTarget(target))
other.GetAI().AttackStart(target);
other.EngageWithTarget(target);
}
}
+1 -4
View File
@@ -1738,9 +1738,7 @@ namespace Game.Entities
public void AddToNotify(NotifyFlags f) { m_notifyflags |= f; }
public bool IsNeedNotify(NotifyFlags f) { return Convert.ToBoolean(m_notifyflags & f); }
NotifyFlags GetNotifyFlags() { return m_notifyflags; }
bool NotifyExecuted(NotifyFlags f) { return Convert.ToBoolean(m_executed_notifies & f); }
void SetNotified(NotifyFlags f) { m_executed_notifies |= f; }
public void ResetAllNotifies() { m_notifyflags = 0; m_executed_notifies = 0; }
public void ResetAllNotifies() { m_notifyflags = 0; }
public bool IsActiveObject() { return m_isActive; }
public bool IsPermanentWorldObject() { return m_isWorldObject; }
@@ -2363,7 +2361,6 @@ namespace Game.Entities
public bool IsInWorld { get; set; }
NotifyFlags m_notifyflags;
NotifyFlags m_executed_notifies;
public FlaggedArray<StealthType> m_stealth = new FlaggedArray<StealthType>(2);
public FlaggedArray<StealthType> m_stealthDetect = new FlaggedArray<StealthType>(2);
+26 -2
View File
@@ -22,6 +22,7 @@ using Game.Networking.Packets;
using Game.Spells;
using System;
using System.Collections.Generic;
using Game.Maps;
namespace Game.Entities
{
@@ -485,15 +486,38 @@ namespace Game.Entities
}
}
public void SetContestedPvP(Player attackedPlayer = null)
{
if (attackedPlayer != null && (attackedPlayer == this || (duel != null && duel.opponent == attackedPlayer)))
return;
SetContestedPvPTimer(30000);
if (!HasUnitState(UnitState.AttackPlayer))
{
AddUnitState(UnitState.AttackPlayer);
AddPlayerFlag(PlayerFlags.ContestedPVP);
// call MoveInLineOfSight for nearby contested guards
AIRelocationNotifier notifier = new AIRelocationNotifier(this);
Cell.VisitWorldObjects(this, notifier, GetVisibilityRange());
}
foreach (Unit unit in m_Controlled)
{
if (!unit.HasUnitState(UnitState.AttackPlayer))
{
unit.AddUnitState(UnitState.AttackPlayer);
AIRelocationNotifier notifier = new AIRelocationNotifier(unit);
Cell.VisitWorldObjects(this, notifier, GetVisibilityRange());
}
}
}
public void UpdateContestedPvP(uint diff)
{
if (m_contestedPvPTimer == 0 || IsInCombat())
return;
if (m_contestedPvPTimer <= diff)
{
ResetContestedPvP();
}
else
m_contestedPvPTimer -= diff;
}
+24 -45
View File
@@ -125,7 +125,7 @@ namespace Game.Entities
public virtual void SetCanDualWield(bool value) { m_canDualWield = value; }
void SendClearThreatList()
public void SendClearThreatList()
{
ThreatClear packet = new ThreatClear();
packet.UnitGUID = GetGUID();
@@ -158,13 +158,6 @@ namespace Game.Entities
}
}
public void DeleteThreatList()
{
if (CanHaveThreatList(true) && !threatManager.IsThreatListEmpty())
SendClearThreatList();
threatManager.ClearReferences();
}
public void TauntApply(Unit taunter)
{
Cypher.Assert(IsTypeId(TypeId.Unit));
@@ -325,12 +318,6 @@ namespace Game.Entities
}
public void RemoveHatedBy(HostileReference pHostileReference) { } //nothing to do yet
public void AddThreat(Unit victim, float fThreat, SpellSchoolMask schoolMask = SpellSchoolMask.Normal, SpellInfo threatSpell = null)
{
// Only mobs can manage threat lists
if (CanHaveThreatList() && !HasUnitState(UnitState.Evade))
threatManager.AddThreat(victim, fThreat, schoolMask, threatSpell);
}
public float ApplyTotalThreatModifier(float fThreat, SpellSchoolMask schoolMask = SpellSchoolMask.Normal)
{
if (!HasAuraType(AuraType.ModThreat) || fThreat < 0)
@@ -360,6 +347,17 @@ namespace Game.Entities
return m_deathState;
}
public bool IsEngaged() { return IsInCombat(); }
public bool IsEngagedBy(Unit who) { return IsInCombatWith(who); }
public void EngageWithTarget(Unit who)
{
SetInCombatWith(who);
who.SetInCombatWith(this);
GetThreatManager().AddThreat(who, 0.0f);
}
public bool IsThreatened() { return CanHaveThreatList() && !GetThreatManager().IsThreatListEmpty(); }
public bool IsThreatenedBy(Unit who) { return who != null && CanHaveThreatList() && GetThreatManager().IsThreatenedBy(who); }
public bool IsInCombat() { return HasUnitFlag(UnitFlags.InCombat); }
public bool IsPetInCombat() { return HasUnitFlag(UnitFlags.PetInCombat); }
@@ -444,7 +442,7 @@ namespace Game.Entities
if (creature != null && !IsPet())
{
// should not let player enter combat by right clicking target - doesn't helps
AddThreat(victim, 0.0f);
GetThreatManager().AddThreat(victim, 0.0f);
SetInCombatWith(victim);
if (victim.IsTypeId(TypeId.Player))
@@ -453,7 +451,7 @@ namespace Game.Entities
Unit owner = victim.GetOwner();
if (owner != null)
{
AddThreat(owner, 0.0f);
GetThreatManager().AddThreat(owner, 0.0f);
SetInCombatWith(owner);
if (owner.GetTypeId() == TypeId.Player)
owner.SetInCombatWith(this);
@@ -553,6 +551,9 @@ namespace Game.Entities
}
public Unit GetAttackerForHelper()
{
if (!IsEngaged())
return null;
Unit victim = GetVictim();
if (victim != null)
if ((!IsPet() && GetPlayerMovingMe() == null) || IsInCombatWith(victim) || victim.IsInCombatWith(this))
@@ -1143,7 +1144,7 @@ namespace Game.Entities
if (damagetype != DamageEffectType.DOT && damage > 0 && !victim.GetOwnerGUID().IsPlayer() && (spellProto == null || !spellProto.HasAura(AuraType.DamageShield)))
victim.ToCreature().SetLastDamagedTime(GameTime.GetGameTime() + SharedConst.MaxAggroResetTime);
victim.AddThreat(this, damage, damageSchoolMask, spellProto);
victim.GetThreatManager().AddThreat(this, damage, spellProto);
}
else // victim is a player
{
@@ -1338,11 +1339,12 @@ namespace Game.Entities
SetInCombatWith(target);
target.SetInCombatWith(this);
}
Unit who = target.GetCharmerOrOwnerOrSelf();
if (who.IsTypeId(TypeId.Player))
SetContestedPvP(who.ToPlayer());
Player me = GetCharmerOrOwnerPlayerOrPlayerItself();
Unit who = target.GetCharmerOrOwnerOrSelf();
if (me != null && who.IsTypeId(TypeId.Player))
me.SetContestedPvP(who.ToPlayer());
if (me != null && who.IsPvP() && (!who.IsTypeId(TypeId.Player) || me.duel == null || me.duel.opponent != who))
{
me.UpdatePvP(true);
@@ -1403,7 +1405,7 @@ namespace Game.Entities
creature.GetAI().EnterCombat(enemy);
if (creature.GetFormation() != null)
creature.GetFormation().MemberAttackStart(creature, enemy);
creature.GetFormation().MemberEngagingTarget(creature, enemy);
}
if (IsPet())
@@ -1595,7 +1597,7 @@ namespace Game.Entities
if (!creature.IsPet())
{
creature.DeleteThreatList();
creature.GetThreatManager().ClearAllThreat();
// must be after setDeathState which resets dynamic flags
if (!creature.loot.IsLooted())
@@ -1709,29 +1711,6 @@ namespace Game.Entities
public virtual uint GetBlockPercent() { return 30; }
public void SetContestedPvP(Player attackedPlayer = null)
{
Player player = GetCharmerOrOwnerPlayerOrPlayerItself();
if (player == null || (attackedPlayer != null && (attackedPlayer == player || (player.duel != null && player.duel.opponent == attackedPlayer))))
return;
player.SetContestedPvPTimer(30000);
if (!player.HasUnitState(UnitState.AttackPlayer))
{
player.AddUnitState(UnitState.AttackPlayer);
player.AddPlayerFlag(PlayerFlags.ContestedPVP);
// call MoveInLineOfSight for nearby contested guards
UpdateObjectVisibility();
}
if (!HasUnitState(UnitState.AttackPlayer))
{
AddUnitState(UnitState.AttackPlayer);
// call MoveInLineOfSight for nearby contested guards
UpdateObjectVisibility();
}
}
void UpdateReactives(uint p_time)
{
for (ReactiveType reactive = 0; reactive < ReactiveType.Max; ++reactive)
+2 -2
View File
@@ -313,7 +313,7 @@ namespace Game.Entities
CastStop();
CombatStop(); // @todo CombatStop(true) may cause crash (interrupt spells)
DeleteThreatList();
GetThreatManager().ClearAllThreat();
Player playerCharmer = charmer.ToPlayer();
@@ -456,7 +456,7 @@ namespace Game.Entities
CastStop();
CombatStop(); // @todo CombatStop(true) may cause crash (interrupt spells)
GetHostileRefManager().DeleteReferences();
DeleteThreatList();
GetThreatManager().ClearAllThreat();
if (_oldFactionId != 0)
{
+9 -4
View File
@@ -1508,14 +1508,19 @@ namespace Game.Entities
}
public void EnergizeBySpell(Unit victim, uint spellId, int damage, PowerType powerType)
{
SpellInfo info = Global.SpellMgr.GetSpellInfo(spellId, GetMap().GetDifficultyID());
if (info != null)
EnergizeBySpell(victim, info, damage, powerType);
}
void EnergizeBySpell(Unit victim, SpellInfo spellInfo, int damage, PowerType powerType)
{
int gain = victim.ModifyPower(powerType, damage);
int overEnergize = damage - gain;
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(spellId, GetMap().GetDifficultyID());
victim.GetHostileRefManager().ThreatAssist(this, damage * 0.5f, spellInfo);
SendEnergizeSpellLog(victim, spellId, damage, overEnergize, powerType);
victim.GetThreatManager().ForwardThreatForAssistingMe(this, damage / 2, spellInfo, true);
SendEnergizeSpellLog(victim, spellInfo.Id, damage, overEnergize, powerType);
}
public void ApplySpellImmune(uint spellId, SpellImmunity op, SpellSchoolMask type, bool apply)
+2 -2
View File
@@ -491,7 +491,7 @@ namespace Game.Entities
m_Events.KillAllEvents(false); // non-delatable (currently casted spells) will not deleted now but it will deleted at call in Map.RemoveAllObjectsInRemoveList
CombatStop();
DeleteThreatList();
GetThreatManager().ClearAllThreat();
GetHostileRefManager().DeleteReferences();
}
public override void CleanupsBeforeDelete(bool finalCleanup = true)
@@ -1609,7 +1609,7 @@ namespace Game.Entities
if (s != DeathState.Alive && s != DeathState.JustRespawned)
{
CombatStop();
DeleteThreatList();
GetThreatManager().ClearAllThreat();
GetHostileRefManager().DeleteReferences();
if (IsNonMeleeSpellCast(false))