Core/Auras: Defined and implemented many new interrupt flags

Port From (https://github.com/TrinityCore/TrinityCore/commit/9b5a46ca2bb3a4632cb9914e0899df611a47d935)
This commit is contained in:
hondacrx
2021-03-28 15:49:12 -04:00
parent d93c4fc3cb
commit 0501481fcd
23 changed files with 257 additions and 169 deletions
+4 -1
View File
@@ -1787,7 +1787,7 @@ namespace Game.Entities
InterruptNonMeleeSpells(true);
//remove auras before removing from map...
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.ChangeMap | SpellAuraInterruptFlags.Move | SpellAuraInterruptFlags.Turning);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Moving | SpellAuraInterruptFlags.Turning);
if (!GetSession().PlayerLogout() && !options.HasAnyFlag(TeleportToOptions.Seamless))
{
@@ -2123,6 +2123,7 @@ namespace Game.Entities
m_summon_expire = 0;
UpdateCriteria(CriteriaTypes.AcceptedSummonings, 1);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Summon);
m_summon_location.SetOrientation(GetOrientation());
TeleportTo(m_summon_location);
@@ -4047,6 +4048,8 @@ namespace Game.Entities
CastSpell(this, 20584, true);
CastSpell(this, 8326, true);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Release);
// there must be SMSG.FORCE_RUN_SPEED_CHANGE, SMSG.FORCE_SWIM_SPEED_CHANGE, SMSG.MOVE_WATER_WALK
// there must be SMSG.STOP_MIRROR_TIMER
+12 -9
View File
@@ -288,7 +288,7 @@ namespace Game.Entities
else
ToPlayer().OnCombatExit();
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.LeaveCombat);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.LeavingCombat);
}
public void ClearInPetCombat()
@@ -630,7 +630,7 @@ namespace Game.Entities
return;
CombatStart(victim);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.MeleeAttack);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Attacking);
// ignore ranged case
if (attType != WeaponAttackType.BaseAttack && attType != WeaponAttackType.OffAttack)
@@ -712,7 +712,7 @@ namespace Game.Entities
return;
CombatStart(victim);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.MeleeAttack);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Attacking);
if (attType != WeaponAttackType.BaseAttack && attType != WeaponAttackType.OffAttack)
return; // ignore ranged case
@@ -993,14 +993,14 @@ namespace Game.Entities
if (damagetype != DamageEffectType.NoDamage)
{
// interrupting auras with AURA_INTERRUPT_FLAG_DAMAGE before checking !damage (absorbed damage breaks that type of auras)
// interrupting auras with SpellAuraInterruptFlags.Damage before checking !damage (absorbed damage breaks that type of auras)
if (spellProto != null)
{
if (!spellProto.HasAttribute(SpellAttr4.DamageDoesntBreakAuras))
victim.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.TakeDamage, spellProto.Id);
victim.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Damage, spellProto.Id);
}
else
victim.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.TakeDamage, 0);
victim.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Damage, 0);
// interrupt spells with SPELL_INTERRUPT_FLAG_ABORT_ON_DMG on absorbed damage (no dots)
if (damage == 0 && damagetype != DamageEffectType.DOT && cleanDamage != null && cleanDamage.absorbed_damage != 0)
@@ -1140,7 +1140,7 @@ namespace Game.Entities
victim.ModifyHealth(-(int)damage);
if (damagetype == DamageEffectType.Direct || damagetype == DamageEffectType.SpellDirect)
victim.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.DirectDamage, spellProto != null ? spellProto.Id : 0);
victim.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.NonPeriodicDamage, spellProto != null ? spellProto.Id : 0);
if (!victim.IsTypeId(TypeId.Player))
{
@@ -1179,6 +1179,7 @@ namespace Game.Entities
{
Spell spell = victim.GetCurrentSpell(CurrentSpellTypes.Generic);
if (spell != null)
{
if (spell.GetState() == SpellState.Preparing)
{
var interruptFlags = spell.m_spellInfo.InterruptFlags;
@@ -1187,10 +1188,11 @@ namespace Game.Entities
else if (interruptFlags.HasAnyFlag(SpellInterruptFlags.PushBack))
spell.Delayed();
}
}
}
Spell spell1 = victim.GetCurrentSpell(CurrentSpellTypes.Channeled);
if (spell1 != null)
if (spell1.GetState() == SpellState.Casting && spell1.m_spellInfo.HasChannelInterruptFlag(SpellChannelInterruptFlags.Delay) && damagetype != DamageEffectType.DOT)
if (spell1.GetState() == SpellState.Casting && spell1.m_spellInfo.HasChannelInterruptFlag(SpellAuraInterruptFlags.DamageChannelDuration) && damagetype != DamageEffectType.DOT)
spell1.DelayedChannel();
}
}
@@ -1352,7 +1354,7 @@ namespace Game.Entities
if (me != null && who.IsPvP() && (!who.IsTypeId(TypeId.Player) || me.duel == null || me.duel.opponent != who))
{
me.UpdatePvP(true);
me.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.EnterPvpCombat);
me.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.PvPActive);
}
}
public void SetInCombatWith(Unit enemy)
@@ -1426,6 +1428,7 @@ namespace Game.Entities
foreach (var unit in m_Controlled)
unit.SetInCombatState(PvP, enemy);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.EnteringCombat);
ProcSkillsAndAuras(enemy, ProcFlags.EnterCombat, ProcFlags.None, ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, null, null, null);
}
+2 -1
View File
@@ -86,7 +86,8 @@ namespace Game.Entities
protected Dictionary<CurrentSpellTypes, Spell> m_currentSpells = new((int)CurrentSpellTypes.Max);
Dictionary<SpellValueMod, int> CustomSpellValueMod = new();
MultiMap<uint, uint>[] m_spellImmune = new MultiMap<uint, uint>[(int)SpellImmunity.Max];
uint[] m_interruptMask = new uint[2];
SpellAuraInterruptFlags m_interruptMask;
SpellAuraInterruptFlags2 m_interruptMask2;
protected int m_procDeep;
bool m_AutoRepeatFirstCast;
SpellHistory _spellHistory;
+4 -4
View File
@@ -582,7 +582,7 @@ namespace Game.Entities
if (relocated)
{
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Move);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Moving);
// move and update visible state if need
if (IsTypeId(TypeId.Player))
@@ -787,9 +787,9 @@ namespace Game.Entities
{
// remove appropriate auras if we are swimming/not swimming respectively
if (inWater)
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.NotAbovewater);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.UnderWater);
else
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.NotUnderwater);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.AboveWater);
}
public virtual void ProcessTerrainStatusUpdate(ZLiquidStatus status, Optional<LiquidData> liquidData)
@@ -1348,7 +1348,7 @@ namespace Game.Entities
RemoveVehicleKit();
}
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.NotMounted);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Dismount);
// only resummon old pet if the player is already added to a map
// this prevents adding a pet to a not created map which would otherwise cause a crash
+72 -34
View File
@@ -1476,7 +1476,7 @@ namespace Game.Entities
var auras = GetAuraEffectsByType(type);
foreach (var eff in auras)
if ((excludeAura == 0 || excludeAura != eff.GetSpellInfo().Id) && //Avoid self interrupt of channeled Crowd Control spells like Seduction
eff.GetSpellInfo().HasAuraInterruptFlag(SpellAuraInterruptFlags.TakeDamage))
eff.GetSpellInfo().HasAuraInterruptFlag(SpellAuraInterruptFlags.Damage))
return true;
return false;
}
@@ -2913,11 +2913,12 @@ namespace Game.Entities
}
public void UpdateInterruptMask()
{
m_interruptMask.Clear();
m_interruptMask = SpellAuraInterruptFlags.None;
m_interruptMask2 = SpellAuraInterruptFlags2.None;
foreach (AuraApplication aurApp in m_interruptableAuras)
{
for (var i = 0; i < m_interruptMask.Length; ++i)
m_interruptMask[i] |= aurApp.GetBase().GetSpellInfo().AuraInterruptFlags[i];
m_interruptMask |= aurApp.GetBase().GetSpellInfo().AuraInterruptFlags;
m_interruptMask2 |= aurApp.GetBase().GetSpellInfo().AuraInterruptFlags2;
}
Spell spell = GetCurrentSpell(CurrentSpellTypes.Channeled);
@@ -2925,8 +2926,8 @@ namespace Game.Entities
{
if (spell.GetState() == SpellState.Casting)
{
for (var i = 0; i < m_interruptMask.Length; ++i)
m_interruptMask[i] |= spell.m_spellInfo.ChannelInterruptFlags[i];
m_interruptMask |= spell.m_spellInfo.ChannelInterruptFlags;
m_interruptMask2 |= spell.m_spellInfo.ChannelInterruptFlags2;
}
}
}
@@ -3161,27 +3162,32 @@ namespace Game.Entities
public bool HasNegativeAuraWithInterruptFlag(SpellAuraInterruptFlags flag, ObjectGuid guid = default)
{
return HasNegativeAuraWithInterruptFlag((uint)flag, 0, guid);
}
public bool HasNegativeAuraWithInterruptFlag(SpellAuraInterruptFlags2 flag, ObjectGuid guid = default)
{
return HasNegativeAuraWithInterruptFlag((uint)flag, 1, guid);
}
public bool HasNegativeAuraWithInterruptFlag(uint flag, int index, ObjectGuid guid = default)
{
if (!Convert.ToBoolean(m_interruptMask[index] & flag))
if (!HasInterruptFlag(flag))
return false;
foreach (var aura in m_interruptableAuras)
{
if (!aura.IsPositive() && Convert.ToBoolean(aura.GetBase().GetSpellInfo().AuraInterruptFlags[index] & flag)
if (!aura.IsPositive() && aura.GetBase().GetSpellInfo().HasAuraInterruptFlag(flag)
&& (guid.IsEmpty() || aura.GetBase().GetCasterGUID() == guid))
return true;
}
return false;
}
public bool HasNegativeAuraWithInterruptFlag(SpellAuraInterruptFlags2 flag, ObjectGuid guid = default)
{
if (!HasInterruptFlag(flag))
return false;
foreach (var aura in m_interruptableAuras)
{
if (!aura.IsPositive() && aura.GetBase().GetSpellInfo().HasAuraInterruptFlag(flag)
&& (guid.IsEmpty() || aura.GetBase().GetCasterGUID() == guid))
return true;
}
return false;
}
bool HasNegativeAuraWithAttribute(SpellAttr0 flag, ObjectGuid guid = default)
{
foreach (var list in GetAppliedAuras())
@@ -3267,19 +3273,18 @@ namespace Game.Entities
return dispelList;
}
bool IsInterruptFlagIgnoredForSpell(SpellAuraInterruptFlags2 flag, Unit unit, SpellInfo spellInfo)
{
return false;
}
bool IsInterruptFlagIgnoredForSpell(SpellAuraInterruptFlags flag, Unit unit, SpellInfo spellInfo)
{
return flag == SpellAuraInterruptFlags.Moving && unit.HasAuraTypeWithAffectMask(AuraType.CastWhileWalking, spellInfo);
}
public void RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags flag, uint except = 0)
{
RemoveAurasWithInterruptFlags((uint)flag, 0, except);
}
public void RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2 flag, uint except = 0)
{
RemoveAurasWithInterruptFlags((uint)flag, 1, except);
}
void RemoveAurasWithInterruptFlags(uint flag, int index, uint except = 0)
{
if (!Convert.ToBoolean(m_interruptMask[index] & flag))
if (!HasInterruptFlag(flag))
return;
// interrupt auras
@@ -3287,8 +3292,7 @@ namespace Game.Entities
{
Aura aura = m_interruptableAuras[i].GetBase();
if (Convert.ToBoolean(aura.GetSpellInfo().AuraInterruptFlags[index] & flag) && (except == 0 || aura.GetId() != except)
&& !(Convert.ToBoolean(flag & (uint)SpellAuraInterruptFlags.Move) && HasAuraTypeWithAffectMask(AuraType.CastWhileWalking, aura.GetSpellInfo())))
if (aura.GetSpellInfo().HasAuraInterruptFlag(flag) && (except == 0 || aura.GetId() != except) && !IsInterruptFlagIgnoredForSpell(flag, this, aura.GetSpellInfo()))
{
uint removedAuras = m_removedAurasCount;
RemoveAura(aura, AuraRemoveMode.Interrupt);
@@ -3302,9 +3306,43 @@ namespace Game.Entities
if (spell != null)
{
if (spell.GetState() == SpellState.Casting
&& Convert.ToBoolean(spell.GetSpellInfo().ChannelInterruptFlags[index] & flag)
&& spell.GetSpellInfo().HasChannelInterruptFlag(flag)
&& spell.GetSpellInfo().Id != except
&& !(Convert.ToBoolean(flag & (uint)SpellAuraInterruptFlags.Move) && HasAuraTypeWithAffectMask(AuraType.CastWhileWalking, spell.GetSpellInfo())))
&& !IsInterruptFlagIgnoredForSpell(flag, this, spell.GetSpellInfo()))
InterruptNonMeleeSpells(false);
}
UpdateInterruptMask();
}
public void RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags2 flag, uint except = 0)
{
if (!HasInterruptFlag(flag))
return;
// interrupt auras
for (var i = 0; i < m_interruptableAuras.Count; i++)
{
Aura aura = m_interruptableAuras[i].GetBase();
if (aura.GetSpellInfo().HasAuraInterruptFlag(flag) && (except == 0 || aura.GetId() != except) && !IsInterruptFlagIgnoredForSpell(flag, this, aura.GetSpellInfo()))
{
uint removedAuras = m_removedAurasCount;
RemoveAura(aura, AuraRemoveMode.Interrupt);
if (m_removedAurasCount > removedAuras + 1)
i = 0;
}
}
// interrupt channeled spell
Spell spell = GetCurrentSpell(CurrentSpellTypes.Channeled);
if (spell != null)
{
if (spell.GetState() == SpellState.Casting
&& spell.GetSpellInfo().HasChannelInterruptFlag(flag)
&& spell.GetSpellInfo().Id != except
&& !IsInterruptFlagIgnoredForSpell(flag, this, spell.GetSpellInfo()))
InterruptNonMeleeSpells(false);
}
@@ -4173,7 +4211,7 @@ namespace Game.Entities
return;
// Sitdown on apply aura req seated
if (aura.GetSpellInfo().HasAuraInterruptFlag(SpellAuraInterruptFlags.NotSeated) && !IsSitState())
if (aura.GetSpellInfo().HasAuraInterruptFlag(SpellAuraInterruptFlags.Standing) && !IsSitState())
SetStandState(UnitStandStateType.Sit);
Unit caster = aura.GetCaster();
+24 -6
View File
@@ -434,6 +434,13 @@ namespace Game.Entities
}
}
public override void AddToWorld()
{
base.AddToWorld();
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.EnterWorld);
}
public override void RemoveFromWorld()
{
// cleanup
@@ -447,6 +454,7 @@ namespace Game.Entities
RemoveCharmAuras();
RemoveAurasByType(AuraType.BindSight);
RemoveNotOwnSingleTargetAuras();
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.LeaveWorld);
RemoveAllGameObjects();
RemoveAllDynObjects();
@@ -1552,7 +1560,7 @@ namespace Game.Entities
if (aurSpellInfo.HasAnyAuraInterruptFlag())
{
m_interruptableAuras.Add(aurApp);
AddInterruptMask(aurSpellInfo.AuraInterruptFlags);
AddInterruptMask(aurSpellInfo.AuraInterruptFlags, aurSpellInfo.AuraInterruptFlags2);
}
AuraStateType aState = aura.GetSpellInfo().GetAuraState();
@@ -1562,10 +1570,14 @@ namespace Game.Entities
aura._ApplyForTarget(this, caster, aurApp);
return aurApp;
}
public void AddInterruptMask(uint[] mask)
bool HasInterruptFlag(SpellAuraInterruptFlags flags) { return m_interruptMask.HasFlag(flags); }
bool HasInterruptFlag(SpellAuraInterruptFlags2 flags) { return m_interruptMask2.HasFlag(flags); }
public void AddInterruptMask(SpellAuraInterruptFlags flags, SpellAuraInterruptFlags2 flags2)
{
for (int i = 0; i < m_interruptMask.Length; ++i)
m_interruptMask[i] |= mask[i];
m_interruptMask |= flags;
m_interruptMask2 |= flags2;
}
void _UpdateAutoRepeatSpell()
@@ -1673,6 +1685,13 @@ namespace Game.Entities
SetPowerType(displayPower);
}
public void SetSheath(SheathState sheathed)
{
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.SheatheState), (byte)sheathed);
if (sheathed == SheathState.Unarmed)
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Sheathing);
}
public FactionTemplateRecord GetFactionTemplateEntry()
{
FactionTemplateRecord entry = CliDB.FactionTemplateStorage.LookupByKey(GetFaction());
@@ -2030,7 +2049,6 @@ namespace Game.Entities
public void SetEmoteState(Emote emote) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.EmoteState), (int)emote); }
public SheathState GetSheath() { return (SheathState)(byte)m_unitData.SheatheState; }
public void SetSheath(SheathState sheathed) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.SheatheState), (byte)sheathed); }
public uint GetCombatTimer() { return combatTimer; }
public UnitPVPStateFlags GetPvpFlags() { return (UnitPVPStateFlags)(byte)m_unitData.PvpFlags; }
@@ -2364,7 +2382,7 @@ namespace Game.Entities
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StandState), (byte)state);
if (IsStandState())
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.NotSeated);
RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Standing);
if (IsTypeId(TypeId.Player))
{