Combat/Threat rewrite - prep & refactor
Port From (https://github.com/TrinityCore/TrinityCore/commit/8be23fcbbdf26e8169defd761e61765f301bebe0)
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user