Core/Spells: Named and implemented most of SpellAttr7
Port From (https://github.com/TrinityCore/TrinityCore/commit/4e87bd7942d932225436940f62e26d48719a42dd)
This commit is contained in:
@@ -1892,38 +1892,38 @@ namespace Framework.Constants
|
||||
}
|
||||
public enum SpellAttr7 : uint
|
||||
{
|
||||
Unk0 = 0x01, // 0 Shaman'S New Spells (Call Of The ...), Feign Death.
|
||||
IgnoreDurationMods = 0x02, // 1 Duration is not affected by duration modifiers
|
||||
DisableAuraWhileDead = 0x04, // 2 Disable Aura While Dead
|
||||
IsCheatSpell = 0x08, // 3 Cannot Cast If Caster Doesn'T Have Unitflag2 & UnitFlag2AllowCheatSpells
|
||||
Unk4 = 0x10, // 4 Only 47883 (Soulstone Resurrection) And Test Spell.
|
||||
SummonTotem = 0x20, // 5 Only Shaman Player Totems.
|
||||
NoPushbackOnDamage = 0x40, // 6 Does not cause spell pushback on damage
|
||||
Unk7 = 0x80, // 7 66218 (Launch) Spell.
|
||||
HordeOnly = 0x100, // 8 Teleports, Mounts And Other Spells.
|
||||
AllianceOnly = 0x200, // 9 Teleports, Mounts And Other Spells.
|
||||
DispelCharges = 0x400, // 10 Dispel And Spellsteal Individual Charges Instead Of Whole Aura.
|
||||
InterruptOnlyNonplayer = 0x800, // 11 Only Non-Player Casts Interrupt, Though Feral Charge - Bear Has It.
|
||||
SilenceOnlyNonplayer = 0x1000, // 12 Not Set In 3.2.2a.
|
||||
CanAlwaysBeInterrupted = 0x2000, // 13 Can always be interrupted, even if caster is immune
|
||||
Unk14 = 0x4000, // 14 Only 52150 (Raise Dead - Pet) Spell.
|
||||
Unk15 = 0x8000, // 15 Exorcism. Usable On Players? 100% Crit Chance On Undead And Demons?
|
||||
HiddenInSpellbookWhenLearned = 0x10000, // 16 After learning these spells become hidden in spellbook (but are visible when not learned for low level characters)
|
||||
Unk17 = 0x20000, // 17 Only 27965 (Suicide) Spell.
|
||||
HasChargeEffect = 0x40000, // 18 Only Spells That Have Charge Among Effects.
|
||||
ZoneTeleport = 0x80000, // 19 Teleports To Specific Zones.
|
||||
Unk20 = 0x100000, // 20 Blink, Divine Shield, Ice Block
|
||||
Unk21 = 0x200000, // 21 Not Set
|
||||
Unk22 = 0x400000, // 22
|
||||
NoAttackDodge = 0x800000, // 23 No Attack Dodge
|
||||
NoAttackParry = 0x1000000, // 24 No Attack Parry
|
||||
AllowSpellReflection = 0x01, // Allow Spell Reflection
|
||||
NoTargetDurationMod = 0x02, // No Target Duration Mod
|
||||
DisableAuraWhileDead = 0x04, // Disable Aura While Dead
|
||||
DebugSpell = 0x08, // Debug Spell Description Cannot Cast If Caster Doesn'T Have Unitflag2 & UnitFlag2AllowCheatSpells
|
||||
TreatAsRaidBuff = 0x10, /*Nyi*/ // Treat As Raid Buff
|
||||
CanBeMultiCast = 0x20, // Can Be Multi Cast
|
||||
DontCauseSpellPushback = 0x40, // Don'T Cause Spell Pushback Description Damage Dealt By This Does Not Cause Spell Pushback
|
||||
PrepareForVehicleControlEnd = 0x80, /*Nyi*/ // Prepare For Vehicle Control End
|
||||
HordeSpecificSpell = 0x100, /*Nyi*/ // Horde Specific Spell
|
||||
AllianceSpecificSpell = 0x200, /*Nyi*/ // Alliance Specific Spell
|
||||
DispelRemovesCharges = 0x400, // Dispel Removes Charges Description Dispel/Spellsteal Remove Individual Charges
|
||||
CanCauseInterrupt = 0x800, // Can Cause Interrupt Description Only Interrupt Non-Player Casting
|
||||
CanCauseSilence = 0x1000, /*Nyi*/ // Can Cause Silence
|
||||
NoUiNotInterruptible = 0x2000, // No Ui Not Interruptible Description Can Always Be Interrupted, Even If Caster Is Immune
|
||||
RecastOnResummon = 0x4000, /*Nyi - Deprecated Attribute, There Is No SpellGo Sent Anymore On Pet Resummon*/ // Recast On Resummon
|
||||
ResetSwingTimerAtSpellStart = 0x8000, // Reset Swing Timer At Spell Start
|
||||
OnlyInSpellbookUntilLearned = 0x10000, // Only In Spellbook Until Learned Description After Learning These Spells Become Hidden In Spellbook (But Are Visible When Not Learned For Low Level Characters)
|
||||
DoNotLogPvpKill = 0x20000, /*Nyi, Only Used By 1 Spell That Is Already Filtered Out In Pvp Credits Because Its Self Targeting*/ // Do Not Log Pvp Kill
|
||||
AttackOnChargeToUnit = 0x40000, // Attack On Charge To Unit
|
||||
ReportSpellFailureToUnitTarget = 0x80000, // Report Spell Failure To Unit Target
|
||||
NoClientFailWhileStunnedFleeingConfused = 0x100000, // No Client Fail While Stunned, Fleeing, Confused Description Clientside - Skips Stunned/Fleeing/Confused Checks
|
||||
RetainCooldownThroughLoad = 0x200000, /*Nyi*/ // Retain Cooldown Through Load
|
||||
IgnoresColdWeatherFlyingRequirement = 0x400000, /*Nyi - Deprecated Attribute*/ // Ignores Cold Weather Flying Requirement
|
||||
NoAttackDodge = 0x800000, // No Attack Dodge
|
||||
NoAttackParry = 0x1000000, // No Attack Parry
|
||||
NoAttackMiss = 0x2000000, // No Attack Miss
|
||||
Unk26 = 0x4000000, // 26
|
||||
BypassNoResurrectAura = 0x8000000, // 27 Bypass No Resurrect Aura
|
||||
ConsolidatedRaidBuff = 0x10000000, // 28 Related To Player Positive Buff
|
||||
Unk29 = 0x20000000, // 29 Only 69028, 71237
|
||||
Unk30 = 0x40000000, // 30 Burning Determination, Divine Sacrifice, Earth Shield, Prayer Of Mending
|
||||
ClientIndicator = 0x80000000 // 31 Only 70769
|
||||
TreatAsNpcAoe = 0x4000000, // Treat As Npc Aoe
|
||||
BypassNoResurrectAura = 0x8000000, // Bypass No Resurrect Aura
|
||||
DoNotCountForPvpScoreboard = 0x10000000, // Do Not Count For Pvp Scoreboard
|
||||
ReflectionOnlyDefends = 0x20000000, // Reflection Only Defends
|
||||
CanProcFromSuppressedTargetProcs = 0x40000000, // Can Proc From Suppressed Target Procs
|
||||
AlwaysCastLog = 0x80000000 // Always Cast Log
|
||||
}
|
||||
public enum SpellAttr8 : uint
|
||||
{
|
||||
@@ -2067,8 +2067,8 @@ namespace Framework.Constants
|
||||
}
|
||||
public enum SpellAttr12 : uint
|
||||
{
|
||||
Unk0 = 0x01, // 0
|
||||
Unk1 = 0x02, // 1
|
||||
EnableProcsFromSuppressedCasterProcs = 0x01, // 0
|
||||
CanProcFromSuppressedCasterProcs = 0x02, // 1
|
||||
Unk2 = 0x04, // 2
|
||||
Unk3 = 0x08, // 3
|
||||
Unk4 = 0x10, // 4
|
||||
@@ -2595,7 +2595,7 @@ namespace Framework.Constants
|
||||
|
||||
RangedMask = DealRangedAttack | TakeRangedAttack | DealRangedAbility | TakeRangedAbility,
|
||||
|
||||
SpellMask = DealMeleeAbility | TakeMeleeAbility | DealRangedAttack | TakeRangedAttack
|
||||
SpellMask = DealMeleeAbility | TakeMeleeAbility | DealRangedAttack | TakeRangedAttack
|
||||
| DealRangedAbility | TakeRangedAbility | DealHelpfulAbility | TakeHelpfulAbility
|
||||
| DealHarmfulAbility | TakeHarmfulAbility | DealHelpfulSpell | TakeHelpfulSpell
|
||||
| DealHarmfulSpell | TakeHarmfulSpell | DealHarmfulPeriodic | TakeHarmfulPeriodic | DealHelpfulPeriodic | TakeHelpfulPeriodic,
|
||||
|
||||
@@ -1917,7 +1917,7 @@ namespace Game.Entities
|
||||
return duration;
|
||||
|
||||
// some auras are not affected by duration modifiers
|
||||
if (spellInfo.HasAttribute(SpellAttr7.IgnoreDurationMods))
|
||||
if (spellInfo.HasAttribute(SpellAttr7.NoTargetDurationMod))
|
||||
return duration;
|
||||
|
||||
// cut duration only of negative effects
|
||||
@@ -2163,7 +2163,7 @@ namespace Game.Entities
|
||||
reflectchance += victim.GetTotalAuraModifierByMiscMask(AuraType.ReflectSpellsSchool, (int)spellInfo.GetSchoolMask());
|
||||
|
||||
if (reflectchance > 0 && RandomHelper.randChance(reflectchance))
|
||||
return SpellMissInfo.Reflect;
|
||||
return spellInfo.HasAttribute(SpellAttr7.ReflectionOnlyDefends) ? SpellMissInfo.Deflect : SpellMissInfo.Reflect;
|
||||
}
|
||||
|
||||
if (spellInfo.HasAttribute(SpellAttr3.AlwaysHit))
|
||||
|
||||
@@ -295,23 +295,6 @@ namespace Game.Entities
|
||||
petStable.SetCurrentActivePetIndex((uint)activePetIndex);
|
||||
}
|
||||
|
||||
// Send fake summon spell cast - this is needed for correct cooldown application for spells
|
||||
// Example: 46584 - without this cooldown (which should be set always when pet is loaded) isn't set clientside
|
||||
// @todo pets should be summoned from real cast instead of just faking it?
|
||||
if (petInfo.CreatedBySpellId != 0)
|
||||
{
|
||||
SpellGo spellGo = new();
|
||||
SpellCastData castData = spellGo.Cast;
|
||||
|
||||
castData.CasterGUID = owner.GetGUID();
|
||||
castData.CasterUnit = owner.GetGUID();
|
||||
castData.CastID = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, owner.GetMapId(), petInfo.CreatedBySpellId, map.GenerateLowGuid(HighGuid.Cast));
|
||||
castData.SpellID = (int)petInfo.CreatedBySpellId;
|
||||
castData.CastFlags = SpellCastFlags.Unk9;
|
||||
castData.CastTime = Time.GetMSTime();
|
||||
owner.SendMessageToSet(spellGo, true);
|
||||
}
|
||||
|
||||
owner.SetMinion(this, true);
|
||||
|
||||
if (!isTemporarySummon)
|
||||
|
||||
@@ -794,10 +794,10 @@ namespace Game.Entities
|
||||
damage -= (int)target.GetDamageReduction((uint)damage);
|
||||
}
|
||||
|
||||
public int CalculateAOEAvoidance(int damage, uint schoolMask, ObjectGuid casterGuid)
|
||||
public int CalculateAOEAvoidance(int damage, uint schoolMask, bool npcCaster)
|
||||
{
|
||||
damage = (int)((float)damage * GetTotalAuraMultiplierByMiscMask(AuraType.ModAoeDamageAvoidance, schoolMask));
|
||||
if (casterGuid.IsAnyTypeCreature())
|
||||
if (npcCaster)
|
||||
damage = (int)((float)damage * GetTotalAuraMultiplierByMiscMask(AuraType.ModCreatureAoeDamageAvoidance, schoolMask));
|
||||
|
||||
return damage;
|
||||
|
||||
@@ -945,7 +945,7 @@ namespace Game.Entities
|
||||
public void SetSilencedSchoolMask(SpellSchoolMask schoolMask) { SetUpdateFieldFlagValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.SilencedSchoolMask), (uint)schoolMask); }
|
||||
|
||||
public void ReplaceAllSilencedSchoolMask(SpellSchoolMask schoolMask) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.SilencedSchoolMask), (uint)schoolMask); }
|
||||
|
||||
|
||||
public SpellHistory GetSpellHistory() { return _spellHistory; }
|
||||
|
||||
public static ProcFlagsHit CreateProcHitMask(SpellNonMeleeDamage damageInfo, SpellMissInfo missCondition)
|
||||
@@ -1511,10 +1511,18 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
WeaponAttackType attType = damageInfo != null ? damageInfo.GetAttackType() : WeaponAttackType.BaseAttack;
|
||||
if (typeMaskActor && actor != null)
|
||||
SpellInfo spellInfo = null;
|
||||
if (spell != null)
|
||||
spellInfo = spell.GetSpellInfo();
|
||||
else if (damageInfo != null)
|
||||
spellInfo = damageInfo.GetSpellInfo();
|
||||
else if (healInfo != null)
|
||||
spellInfo = healInfo.GetSpellInfo();
|
||||
|
||||
if (typeMaskActor != null && actor != null && !(spellInfo != null && spellInfo.HasAttribute(SpellAttr3.SuppressCasterProcs)))
|
||||
actor.ProcSkillsAndReactives(false, actionTarget, typeMaskActor, hitMask, attType);
|
||||
|
||||
if (typeMaskActionTarget && actionTarget != null)
|
||||
if (typeMaskActionTarget && actionTarget != null && !(spellInfo != null && spellInfo.HasAttribute(SpellAttr3.SuppressTargetProcs)))
|
||||
actionTarget.ProcSkillsAndReactives(true, actor, typeMaskActionTarget, hitMask, attType);
|
||||
|
||||
if (actor != null)
|
||||
@@ -1903,9 +1911,12 @@ namespace Game.Entities
|
||||
Player bgPlayer = unit.ToPlayer();
|
||||
if (bgPlayer != null)
|
||||
{
|
||||
Battleground bg = bgPlayer.GetBattleground();
|
||||
if (bg != null)
|
||||
bg.UpdatePlayerScore(bgPlayer, ScoreType.HealingDone, (uint)gain);
|
||||
if (healInfo.GetSpellInfo() == null || !healInfo.GetSpellInfo().HasAttribute(SpellAttr7.DoNotCountForPvpScoreboard))
|
||||
{
|
||||
Battleground bg = bgPlayer.GetBattleground();
|
||||
if (bg != null)
|
||||
bg.UpdatePlayerScore(bgPlayer, ScoreType.HealingDone, (uint)gain);
|
||||
}
|
||||
|
||||
// use the actual gain, as the overheal shall not be counted, skip gain 0 (it ignored anyway in to criteria)
|
||||
if (gain != 0)
|
||||
@@ -2758,7 +2769,7 @@ namespace Game.Entities
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public bool HasNegativeAuraWithInterruptFlag(SpellAuraInterruptFlags flag, ObjectGuid guid = default)
|
||||
{
|
||||
if (!HasInterruptFlag(flag))
|
||||
@@ -2806,7 +2817,7 @@ namespace Game.Entities
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public uint GetAuraCount(uint spellId)
|
||||
{
|
||||
uint count = 0;
|
||||
@@ -2873,7 +2884,7 @@ namespace Game.Entities
|
||||
// The charges / stack amounts don't count towards the total number of auras that can be dispelled.
|
||||
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) . 50% chance to dispell
|
||||
// Polymorph instead of 1 / (5 + 1) . 16%.
|
||||
bool dispelCharges = aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelCharges);
|
||||
bool dispelCharges = aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelRemovesCharges);
|
||||
byte charges = dispelCharges ? aura.GetCharges() : aura.GetStackAmount();
|
||||
if (charges > 0)
|
||||
dispelList.Add(new DispelableAura(aura, chance, charges));
|
||||
@@ -2911,7 +2922,7 @@ namespace Game.Entities
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
public void RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags flag, SpellInfo source = null)
|
||||
{
|
||||
if (!HasInterruptFlag(flag))
|
||||
@@ -3038,7 +3049,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
bool stealCharge = aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelCharges);
|
||||
bool stealCharge = aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelRemovesCharges);
|
||||
// Cast duration to unsigned to prevent permanent aura's such as Righteous Fury being permanently added to caster
|
||||
uint dur = (uint)Math.Min(2u * Time.Minute * Time.InMilliseconds, aura.GetDuration());
|
||||
|
||||
@@ -3241,7 +3252,7 @@ namespace Game.Entities
|
||||
// Call OnDispel hook on AuraScript
|
||||
aura.CallScriptDispel(dispelInfo);
|
||||
|
||||
if (aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelCharges))
|
||||
if (aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelRemovesCharges))
|
||||
aura.ModCharges(-dispelInfo.GetRemovedCharges(), AuraRemoveMode.EnemySpell);
|
||||
else
|
||||
aura.ModStackAmount(-dispelInfo.GetRemovedCharges(), AuraRemoveMode.EnemySpell);
|
||||
@@ -3455,7 +3466,7 @@ namespace Game.Entities
|
||||
// this may be a dead loop if some events on aura remove will continiously apply aura on remove
|
||||
// we want to have all auras removed, so use your brain when linking events
|
||||
for (int counter = 0; !m_appliedAuras.Empty() || !m_ownedAuras.Empty(); counter++)
|
||||
{
|
||||
{
|
||||
foreach (var aurAppIter in GetAppliedAuras())
|
||||
_UnapplyAura(aurAppIter, AuraRemoveMode.Default);
|
||||
|
||||
@@ -3815,7 +3826,7 @@ namespace Game.Entities
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// spell mustn't have familyflags
|
||||
public AuraEffect GetAuraEffect(AuraType type, SpellFamilyNames family, FlagArray128 familyFlag, ObjectGuid casterGUID = default)
|
||||
{
|
||||
@@ -3903,7 +3914,7 @@ namespace Game.Entities
|
||||
AuraApplication aurApp = GetAuraApplication(predicate);
|
||||
return aurApp?.GetBase();
|
||||
}
|
||||
|
||||
|
||||
public uint BuildAuraStateUpdateForTarget(Unit target)
|
||||
{
|
||||
uint auraStates = m_unitData.AuraState & ~(uint)AuraStateType.PerCasterAuraStateMask;
|
||||
@@ -3918,7 +3929,7 @@ namespace Game.Entities
|
||||
public bool CanProc() { return m_procDeep == 0; }
|
||||
|
||||
public int GetProcChainLength() { return m_procChainLength; }
|
||||
|
||||
|
||||
public void _ApplyAuraEffect(Aura aura, uint effIndex)
|
||||
{
|
||||
Cypher.Assert(aura != null);
|
||||
@@ -3982,8 +3993,8 @@ namespace Game.Entities
|
||||
if (player != null)
|
||||
{
|
||||
if (Global.ConditionMgr.IsSpellUsedInSpellClickConditions(aurApp.GetBase().GetId()))
|
||||
player.UpdateVisibleGameobjectsOrSpellClicks();
|
||||
|
||||
player.UpdateVisibleGameobjectsOrSpellClicks();
|
||||
|
||||
player.FailCriteria(CriteriaFailEvent.GainAura, aurApp.GetBase().GetId());
|
||||
player.StartCriteria(CriteriaStartEvent.GainAura, aurApp.GetBase().GetId());
|
||||
player.UpdateCriteria(CriteriaType.GainAura, aurApp.GetBase().GetId());
|
||||
@@ -4168,7 +4179,7 @@ namespace Game.Entities
|
||||
//uint removedAuras = m_removedAurasCount;
|
||||
RemoveAura(aurApp);
|
||||
//if (hasMoreThanOneEffect || m_removedAurasCount > removedAuras + 1)
|
||||
//continue;
|
||||
//continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2724,7 +2724,7 @@ namespace Game.Entities
|
||||
if (killer != null)
|
||||
{
|
||||
// in bg, count dmg if victim is also a player
|
||||
if (victim.IsPlayer())
|
||||
if (victim.IsPlayer() && !(spellProto != null && spellProto.HasAttribute(SpellAttr7.DoNotCountForPvpScoreboard)))
|
||||
{
|
||||
Battleground bg = killer.GetBattleground();
|
||||
if (bg != null)
|
||||
@@ -2864,7 +2864,7 @@ namespace Game.Entities
|
||||
|
||||
if (damagetype != DamageEffectType.NoDamage && damagetype != DamageEffectType.DOT)
|
||||
{
|
||||
if (victim != attacker && (spellProto == null || !(spellProto.HasAttribute(SpellAttr6.NoPushback) || spellProto.HasAttribute(SpellAttr7.NoPushbackOnDamage) || spellProto.HasAttribute(SpellAttr3.TreatAsPeriodic))))
|
||||
if (victim != attacker && (spellProto == null || !(spellProto.HasAttribute(SpellAttr6.NoPushback) || spellProto.HasAttribute(SpellAttr7.DontCauseSpellPushback) || spellProto.HasAttribute(SpellAttr3.TreatAsPeriodic))))
|
||||
{
|
||||
Spell spell = victim.GetCurrentSpell(CurrentSpellTypes.Generic);
|
||||
if (spell != null)
|
||||
|
||||
@@ -1726,6 +1726,20 @@ namespace Game.Spells
|
||||
|
||||
if (GetSpellInfo().HasAttribute(SpellAttr12.OnlyProcFromClassAbilities) && !spell.GetSpellInfo().HasAttribute(SpellAttr13.AllowClassAbilityProcs))
|
||||
return 0;
|
||||
|
||||
if (eventInfo.GetTypeMask().HasFlag(ProcFlags.TakenHitMask))
|
||||
{
|
||||
if (spell.GetSpellInfo().HasAttribute(SpellAttr3.SuppressTargetProcs)
|
||||
&& !GetSpellInfo().HasAttribute(SpellAttr7.CanProcFromSuppressedTargetProcs))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (spell.GetSpellInfo().HasAttribute(SpellAttr3.SuppressCasterProcs)
|
||||
&& !spell.GetSpellInfo().HasAttribute(SpellAttr12.EnableProcsFromSuppressedCasterProcs)
|
||||
&& !GetSpellInfo().HasAttribute(SpellAttr12.CanProcFromSuppressedCasterProcs))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// check don't break stealth attr present
|
||||
|
||||
@@ -5126,8 +5126,8 @@ namespace Game.Spells
|
||||
|
||||
if (!GetSpellInfo().HasAttribute(SpellAttr4.IgnoreDamageTakenModifiers))
|
||||
{
|
||||
if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SpellEffectName.PersistentAreaAura) || GetSpellInfo().HasAttribute(SpellAttr5.TreatAsAreaEffect))
|
||||
damage = (uint)target.CalculateAOEAvoidance((int)damage, (uint)m_spellInfo.SchoolMask, GetBase().GetCastItemGUID());
|
||||
if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SpellEffectName.PersistentAreaAura) || GetSpellInfo().HasAttribute(SpellAttr5.TreatAsAreaEffect) || GetSpellInfo().HasAttribute(SpellAttr7.TreatAsNpcAoe))
|
||||
damage = (uint)target.CalculateAOEAvoidance((int)damage, (uint)m_spellInfo.SchoolMask, (caster != null && !caster.IsControlledByPlayer()) || GetSpellInfo().HasAttribute(SpellAttr7.TreatAsNpcAoe));
|
||||
}
|
||||
|
||||
int dmg = (int)damage;
|
||||
@@ -5208,8 +5208,8 @@ namespace Game.Spells
|
||||
|
||||
if (!GetSpellInfo().HasAttribute(SpellAttr4.IgnoreDamageTakenModifiers))
|
||||
{
|
||||
if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SpellEffectName.PersistentAreaAura) || GetSpellInfo().HasAttribute(SpellAttr5.TreatAsAreaEffect))
|
||||
damage = (uint)target.CalculateAOEAvoidance((int)damage, (uint)m_spellInfo.SchoolMask, GetBase().GetCastItemGUID());
|
||||
if (GetSpellEffectInfo().IsTargetingArea() || GetSpellEffectInfo().IsAreaAuraEffect() || GetSpellEffectInfo().IsEffect(SpellEffectName.PersistentAreaAura) || GetSpellInfo().HasAttribute(SpellAttr5.TreatAsAreaEffect) || GetSpellInfo().HasAttribute(SpellAttr7.TreatAsNpcAoe))
|
||||
damage = (uint)target.CalculateAOEAvoidance((int)damage, (uint)m_spellInfo.SchoolMask, (caster != null && !caster.IsControlledByPlayer()) || GetSpellInfo().HasAttribute(SpellAttr7.TreatAsNpcAoe));
|
||||
}
|
||||
|
||||
int dmg = (int)damage;
|
||||
|
||||
+59
-52
@@ -90,7 +90,7 @@ namespace Game.Spells
|
||||
|
||||
// Determine if spell can be reflected back to the caster
|
||||
// Patch 1.2 notes: Spell Reflection no longer reflects abilities
|
||||
m_canReflect = caster.IsUnit() && m_spellInfo.DmgClass == SpellDmgClass.Magic && !m_spellInfo.HasAttribute(SpellAttr0.IsAbility)
|
||||
m_canReflect = caster.IsUnit() && ((m_spellInfo.DmgClass == SpellDmgClass.Magic && !m_spellInfo.HasAttribute(SpellAttr0.IsAbility)) || m_spellInfo.HasAttribute(SpellAttr7.AllowSpellReflection))
|
||||
&& !m_spellInfo.HasAttribute(SpellAttr1.NoReflection) && !m_spellInfo.HasAttribute(SpellAttr0.NoImmunities)
|
||||
&& !m_spellInfo.IsPassive();
|
||||
|
||||
@@ -1746,9 +1746,9 @@ namespace Game.Spells
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.ChainFromCaster))
|
||||
searchRadius = GetMinMaxRange(false).maxRange;
|
||||
else if (spellEffectInfo.EffectAttributes.HasFlag(SpellEffectAttributes.ChainFromInitialTarget))
|
||||
searchRadius= jumpRadius;
|
||||
searchRadius = jumpRadius;
|
||||
else
|
||||
searchRadius= jumpRadius * chainTargets;
|
||||
searchRadius = jumpRadius * chainTargets;
|
||||
|
||||
WorldObject chainSource = m_spellInfo.HasAttribute(SpellAttr2.ChainFromCaster) ? m_caster : target;
|
||||
List<WorldObject> tempTargets = new();
|
||||
@@ -1924,7 +1924,7 @@ namespace Game.Spells
|
||||
float hitDelay = m_spellInfo.LaunchDelay;
|
||||
WorldObject missileSource = m_caster;
|
||||
if (m_spellInfo.HasAttribute(SpellAttr4.BouncyChainMissiles))
|
||||
{
|
||||
{
|
||||
var previousTargetInfo = m_UniqueTargetInfo.FindLast(target => (target.EffectMask & effectMask) != 0);
|
||||
if (previousTargetInfo != null)
|
||||
{
|
||||
@@ -2614,6 +2614,9 @@ namespace Game.Spells
|
||||
if (m_spellInfo.HasAttribute(SpellAttr12.StartCooldownOnCastStart))
|
||||
SendSpellCooldown();
|
||||
|
||||
if (m_spellInfo.HasAttribute(SpellAttr7.ResetSwingTimerAtSpellStart) && IsAutoActionResetSpell())
|
||||
ResetCombatTimers();
|
||||
|
||||
//Containers for channeled spells have to be set
|
||||
// @todoApply this to all casted spells if needed
|
||||
// Why check duration? 29350: channelled triggers channelled
|
||||
@@ -2951,6 +2954,9 @@ namespace Game.Spells
|
||||
m_launchHandled = true;
|
||||
}
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr7.ResetSwingTimerAtSpellStart) && IsAutoActionResetSpell())
|
||||
ResetCombatTimers();
|
||||
|
||||
// we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()...
|
||||
SendSpellGo();
|
||||
|
||||
@@ -3052,8 +3058,7 @@ namespace Game.Spells
|
||||
if (!_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.IgnoreCastInProgress) && !m_spellInfo.HasAttribute(SpellAttr2.NotAnAction))
|
||||
m_originalCaster.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.ActionDelayed, m_spellInfo);
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr3.SuppressCasterProcs))
|
||||
Unit.ProcSkillsAndAuras(m_originalCaster, null, procAttacker, new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Cast, hitMask, this, null, null);
|
||||
Unit.ProcSkillsAndAuras(m_originalCaster, null, procAttacker, new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Cast, hitMask, this, null, null);
|
||||
|
||||
// Call CreatureAI hook OnSpellCast
|
||||
Creature caster = m_originalCaster.ToCreature();
|
||||
@@ -3306,8 +3311,7 @@ namespace Game.Spells
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr3.SuppressCasterProcs))
|
||||
Unit.ProcSkillsAndAuras(m_originalCaster, null, procAttacker, new ProcFlagsInit(ProcFlags.None), m_procSpellType, ProcFlagsSpellPhase.Finish, m_hitMask, this, null, null);
|
||||
Unit.ProcSkillsAndAuras(m_originalCaster, null, procAttacker, new ProcFlagsInit(ProcFlags.None), m_procSpellType, ProcFlagsSpellPhase.Finish, m_hitMask, this, null, null);
|
||||
}
|
||||
|
||||
void SendSpellCooldown()
|
||||
@@ -3452,8 +3456,7 @@ namespace Game.Spells
|
||||
if (creatureCaster != null)
|
||||
creatureCaster.ReleaseSpellFocus(this);
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr3.SuppressCasterProcs))
|
||||
Unit.ProcSkillsAndAuras(unitCaster, null, new ProcFlagsInit(ProcFlags.CastEnded), new ProcFlagsInit(), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, this, null, null);
|
||||
Unit.ProcSkillsAndAuras(unitCaster, null, new ProcFlagsInit(ProcFlags.CastEnded), new ProcFlagsInit(), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.None, ProcFlagsHit.None, this, null, null);
|
||||
|
||||
if (result != SpellCastResult.SpellCastOk)
|
||||
{
|
||||
@@ -3481,17 +3484,6 @@ namespace Game.Spells
|
||||
}
|
||||
}
|
||||
|
||||
if (IsAutoActionResetSpell())
|
||||
{
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.DoNotResetCombatTimers))
|
||||
{
|
||||
unitCaster.ResetAttackTimer(WeaponAttackType.BaseAttack);
|
||||
if (unitCaster.HaveOffhandWeapon())
|
||||
unitCaster.ResetAttackTimer(WeaponAttackType.OffAttack);
|
||||
unitCaster.ResetAttackTimer(WeaponAttackType.RangedAttack);
|
||||
}
|
||||
}
|
||||
|
||||
// potions disabled by client, send event "not in combat" if need
|
||||
if (unitCaster.IsTypeId(TypeId.Player))
|
||||
{
|
||||
@@ -3675,7 +3667,7 @@ namespace Game.Spells
|
||||
uint itemid = (uint)spellInfo.Reagent[i];
|
||||
uint itemcount = spellInfo.ReagentCount[i];
|
||||
|
||||
if (!caster.HasItemCount(itemid, itemcount))
|
||||
if (caster != null && !caster.HasItemCount(itemid, itemcount))
|
||||
{
|
||||
packet.FailedArg1 = (int)itemid; // first missing item
|
||||
break;
|
||||
@@ -3689,7 +3681,7 @@ namespace Game.Spells
|
||||
{
|
||||
foreach (var reagentsCurrency in spellInfo.ReagentsCurrency)
|
||||
{
|
||||
if (!caster.HasCurrency(reagentsCurrency.CurrencyTypesID, reagentsCurrency.CurrencyCount))
|
||||
if (caster != null && !caster.HasCurrency(reagentsCurrency.CurrencyTypesID, reagentsCurrency.CurrencyCount))
|
||||
{
|
||||
packet.FailedArg1 = -1;
|
||||
packet.FailedArg2 = reagentsCurrency.CurrencyTypesID;
|
||||
@@ -3716,10 +3708,18 @@ namespace Game.Spells
|
||||
if (result == SpellCastResult.SpellCastOk)
|
||||
return;
|
||||
|
||||
if (!m_caster.IsTypeId(TypeId.Player))
|
||||
Player receiver = m_caster.ToPlayer();
|
||||
if (m_spellInfo.HasAttribute(SpellAttr7.ReportSpellFailureToUnitTarget))
|
||||
{
|
||||
Player target = m_targets.GetUnitTarget()?.ToPlayer();
|
||||
if (target != null)
|
||||
receiver = target;
|
||||
}
|
||||
|
||||
if (receiver == null)
|
||||
return;
|
||||
|
||||
if (m_caster.ToPlayer().IsLoading()) // don't send cast results at loading time
|
||||
if (receiver.IsLoading()) // don't send cast results at loading time
|
||||
return;
|
||||
|
||||
if (_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.DontReportCastError))
|
||||
@@ -3728,7 +3728,7 @@ namespace Game.Spells
|
||||
CastFailed castFailed = new();
|
||||
castFailed.Visual = m_SpellVisual;
|
||||
FillSpellCastFailedArgs(castFailed, m_castId, m_spellInfo, result, m_customError, param1, param2, m_caster.ToPlayer());
|
||||
m_caster.ToPlayer().SendPacket(castFailed);
|
||||
receiver.SendPacket(castFailed);
|
||||
}
|
||||
|
||||
public void SendPetCastResult(SpellCastResult result, int? param1 = null, int? param2 = null)
|
||||
@@ -4740,7 +4740,7 @@ namespace Game.Spells
|
||||
}
|
||||
}
|
||||
|
||||
if (m_spellInfo.HasAttribute(SpellAttr7.IsCheatSpell) && m_caster.IsUnit() && !m_caster.ToUnit().HasUnitFlag2(UnitFlags2.AllowCheatSpells))
|
||||
if (m_spellInfo.HasAttribute(SpellAttr7.DebugSpell) && m_caster.IsUnit() && !m_caster.ToUnit().HasUnitFlag2(UnitFlags2.AllowCheatSpells))
|
||||
{
|
||||
m_customError = SpellCustomErrors.GmOnly;
|
||||
return SpellCastResult.CustomError;
|
||||
@@ -7113,7 +7113,7 @@ namespace Game.Spells
|
||||
|
||||
if (target.GetGUID() != corpse.GetOwnerGUID())
|
||||
return false;
|
||||
|
||||
|
||||
if (!corpse.HasCorpseDynamicFlag(CorpseDynFlags.Lootable))
|
||||
return false;
|
||||
|
||||
@@ -7178,7 +7178,7 @@ namespace Game.Spells
|
||||
|
||||
bool IsAutoActionResetSpell()
|
||||
{
|
||||
if (IsTriggered())
|
||||
if (IsTriggered() || m_spellInfo.HasAttribute(SpellAttr2.DoNotResetCombatTimers))
|
||||
return false;
|
||||
|
||||
if (m_casttime == 0 && m_spellInfo.HasAttribute(SpellAttr6.DoesntResetSwingTimerIfInstant))
|
||||
@@ -7195,7 +7195,8 @@ namespace Game.Spells
|
||||
bool IsNeedSendToClient()
|
||||
{
|
||||
return m_SpellVisual.SpellXSpellVisualID != 0 || m_SpellVisual.ScriptVisualID != 0 || m_spellInfo.IsChanneled() ||
|
||||
m_spellInfo.HasAttribute(SpellAttr8.AuraSendAmount) || m_spellInfo.HasHitDelay() || (m_triggeredByAuraSpell == null && !IsTriggered());
|
||||
(m_spellInfo.HasAttribute(SpellAttr8.AuraSendAmount)) || m_spellInfo.HasHitDelay() || (m_triggeredByAuraSpell == null && !IsTriggered()) ||
|
||||
m_spellInfo.HasAttribute(SpellAttr7.AlwaysCastLog);
|
||||
}
|
||||
|
||||
public Unit GetUnitCasterForEffectHandlers()
|
||||
@@ -7226,7 +7227,7 @@ namespace Game.Spells
|
||||
|
||||
PrepareTargetProcessing();
|
||||
|
||||
foreach (TargetInfo target in m_UniqueTargetInfo)
|
||||
foreach (TargetInfo target in m_UniqueTargetInfo)
|
||||
PreprocessSpellLaunch(target);
|
||||
|
||||
foreach (var spellEffectInfo in m_spellInfo.GetEffects())
|
||||
@@ -7300,9 +7301,9 @@ namespace Game.Spells
|
||||
if (m_originalCaster != null && m_damage > 0)
|
||||
{
|
||||
bool isAoeTarget = spellEffectInfo.IsTargetingArea() || spellEffectInfo.IsAreaAuraEffect() || spellEffectInfo.IsEffect(SpellEffectName.PersistentAreaAura);
|
||||
if (isAoeTarget || m_spellInfo.HasAttribute(SpellAttr5.TreatAsAreaEffect))
|
||||
if (isAoeTarget || m_spellInfo.HasAttribute(SpellAttr5.TreatAsAreaEffect) || m_spellInfo.HasAttribute(SpellAttr7.TreatAsNpcAoe))
|
||||
{
|
||||
m_damage = unit.CalculateAOEAvoidance(m_damage, (uint)m_spellInfo.SchoolMask, m_originalCaster.GetGUID());
|
||||
m_damage = unit.CalculateAOEAvoidance(m_damage, (uint)m_spellInfo.SchoolMask, !m_originalCaster.IsControlledByPlayer() || m_spellInfo.HasAttribute(SpellAttr7.TreatAsNpcAoe));
|
||||
|
||||
if (m_originalCaster.IsPlayer())
|
||||
{
|
||||
@@ -7352,6 +7353,18 @@ namespace Game.Spells
|
||||
targetInfo.Healing += m_healing;
|
||||
}
|
||||
|
||||
void ResetCombatTimers()
|
||||
{
|
||||
Unit unitCaster = m_caster.ToUnit();
|
||||
if (unitCaster == null)
|
||||
return;
|
||||
|
||||
unitCaster.ResetAttackTimer(WeaponAttackType.BaseAttack);
|
||||
if (unitCaster.HaveOffhandWeapon())
|
||||
unitCaster.ResetAttackTimer(WeaponAttackType.OffAttack);
|
||||
unitCaster.ResetAttackTimer(WeaponAttackType.RangedAttack);
|
||||
}
|
||||
|
||||
SpellCastResult CanOpenLock(SpellEffectInfo effect, uint lockId, ref SkillType skillId, ref int reqSkillValue, ref int skillValue)
|
||||
{
|
||||
if (lockId == 0) // possible case for GO and maybe for items.
|
||||
@@ -7700,7 +7713,7 @@ namespace Game.Spells
|
||||
script._FinishScriptCall();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CallScriptObjectAreaTargetSelectHandlers(List<WorldObject> targets, uint effIndex, SpellImplicitTargetInfo targetType)
|
||||
{
|
||||
foreach (var script in m_loadedScripts)
|
||||
@@ -7782,7 +7795,7 @@ namespace Game.Spells
|
||||
|
||||
return source.IsWithinLOS(target.GetPositionX(), target.GetPositionY(), target.GetPositionZ(), LineOfSightChecks.All, ignoreFlags);
|
||||
}
|
||||
|
||||
|
||||
bool CheckScriptEffectImplicitTargets(uint effIndex, uint effIndexToCheck)
|
||||
{
|
||||
// Skip if there are not any script
|
||||
@@ -8033,7 +8046,7 @@ namespace Game.Spells
|
||||
public bool IsChannelActive() { return m_caster.IsUnit() && m_caster.ToUnit().GetChannelSpellId() != 0; }
|
||||
|
||||
public int GetProcChainLength() { return m_procChainLength; }
|
||||
|
||||
|
||||
public bool IsDeletable()
|
||||
{
|
||||
return !m_referencedFromCurrentSpell && !m_executedCurrently;
|
||||
@@ -8090,7 +8103,7 @@ namespace Game.Spells
|
||||
public SpellInfo GetTriggeredByAuraSpell() { return m_triggeredByAuraSpell; }
|
||||
|
||||
public int GetTimer() { return m_timer; }
|
||||
|
||||
|
||||
#region Fields
|
||||
Dictionary<SpellEffectName, SpellLogEffect> _executeLogEffects = new();
|
||||
PathGenerator m_preGeneratedPath;
|
||||
@@ -8499,7 +8512,7 @@ namespace Game.Spells
|
||||
ProcFlagsHit hitMask = ProcFlagsHit.None;
|
||||
|
||||
// Spells with this flag cannot trigger if effect is cast on self
|
||||
bool canEffectTrigger = (!spell.m_spellInfo.HasAttribute(SpellAttr3.SuppressCasterProcs) || !spell.m_spellInfo.HasAttribute(SpellAttr3.SuppressTargetProcs)) && spell.unitTarget.CanProc();
|
||||
bool canEffectTrigger = spell.unitTarget.CanProc();
|
||||
|
||||
// Trigger info was not filled in Spell::prepareDataForTriggerSystem - we do it now
|
||||
if (canEffectTrigger && !procAttacker && !procVictim)
|
||||
@@ -8667,12 +8680,6 @@ namespace Game.Spells
|
||||
// Do triggers for unit
|
||||
if (canEffectTrigger)
|
||||
{
|
||||
if (spell.m_spellInfo.HasAttribute(SpellAttr3.SuppressCasterProcs))
|
||||
procAttacker = new ProcFlagsInit();
|
||||
|
||||
if (spell.m_spellInfo.HasAttribute(SpellAttr3.SuppressTargetProcs))
|
||||
procVictim = new ProcFlagsInit();
|
||||
|
||||
Unit.ProcSkillsAndAuras(caster, spell.unitTarget, procAttacker, procVictim, procSpellType, ProcFlagsSpellPhase.Hit, hitMask, spell, spellDamageInfo, healInfo);
|
||||
|
||||
// item spells (spell hit of non-damage spell may also activate items, for example seal of corruption hidden hit)
|
||||
@@ -8709,7 +8716,7 @@ namespace Game.Spells
|
||||
}
|
||||
|
||||
// Check for SPELL_ATTR7_INTERRUPT_ONLY_NONPLAYER
|
||||
if (MissCondition == SpellMissInfo.None && spell.m_spellInfo.HasAttribute(SpellAttr7.InterruptOnlyNonplayer) && !unit.IsPlayer())
|
||||
if (MissCondition == SpellMissInfo.None && spell.m_spellInfo.HasAttribute(SpellAttr7.CanCauseInterrupt) && !unit.IsPlayer())
|
||||
caster.CastSpell(unit, 32747, new CastSpellExtraArgs(spell));
|
||||
}
|
||||
|
||||
@@ -9256,7 +9263,7 @@ namespace Game.Spells
|
||||
|
||||
Spell m_Spell;
|
||||
}
|
||||
|
||||
|
||||
class ProcReflectDelayed : BasicEvent
|
||||
{
|
||||
public ProcReflectDelayed(Unit owner, ObjectGuid casterGuid)
|
||||
@@ -9333,7 +9340,7 @@ namespace Game.Spells
|
||||
Targets = new();
|
||||
Targets.SetDst(dest);
|
||||
}
|
||||
|
||||
|
||||
public CastSpellTargetArg(SpellCastTargets targets)
|
||||
{
|
||||
Targets = new();
|
||||
@@ -9482,15 +9489,15 @@ namespace Game.Spells
|
||||
}
|
||||
|
||||
public static implicit operator CastSpellExtraArgs(bool triggered) => new CastSpellExtraArgs(triggered);
|
||||
|
||||
|
||||
public static implicit operator CastSpellExtraArgs(TriggerCastFlags trigger) => new CastSpellExtraArgs(trigger);
|
||||
|
||||
|
||||
public static implicit operator CastSpellExtraArgs(Item item) => new CastSpellExtraArgs(item);
|
||||
|
||||
|
||||
public static implicit operator CastSpellExtraArgs(Spell triggeringSpell) => new CastSpellExtraArgs(triggeringSpell);
|
||||
|
||||
|
||||
public static implicit operator CastSpellExtraArgs(AuraEffect eff) => new CastSpellExtraArgs(eff);
|
||||
|
||||
|
||||
public static implicit operator CastSpellExtraArgs(Difficulty castDifficulty) => new CastSpellExtraArgs(castDifficulty);
|
||||
}
|
||||
|
||||
|
||||
@@ -3597,7 +3597,7 @@ namespace Game.Spells
|
||||
if (effectHandleMode == SpellEffectHandleMode.HitTarget)
|
||||
{
|
||||
// not all charge effects used in negative spells
|
||||
if (!m_spellInfo.IsPositive() && m_caster.IsTypeId(TypeId.Player))
|
||||
if (m_spellInfo.HasAttribute(SpellAttr7.AttackOnChargeToUnit))
|
||||
unitCaster.Attack(unitTarget, true);
|
||||
|
||||
if (effectInfo.TriggerSpell != 0)
|
||||
@@ -4389,7 +4389,7 @@ namespace Game.Spells
|
||||
// The charges / stack amounts don't count towards the total number of auras that can be dispelled.
|
||||
// Ie: A dispel on a target with 5 stacks of Winters Chill and a Polymorph has 1 / (1 + 1) . 50% chance to dispell
|
||||
// Polymorph instead of 1 / (5 + 1) . 16%.
|
||||
bool dispelCharges = aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelCharges);
|
||||
bool dispelCharges = aura.GetSpellInfo().HasAttribute(SpellAttr7.DispelRemovesCharges);
|
||||
byte charges = dispelCharges ? aura.GetCharges() : aura.GetStackAmount();
|
||||
if (charges > 0)
|
||||
stealList.Add(new DispelableAura(aura, chance, charges));
|
||||
@@ -4864,7 +4864,7 @@ namespace Game.Spells
|
||||
if (!player.HasSpell(spell_id) || player.GetSpellHistory().HasCooldown(spell_id))
|
||||
continue;
|
||||
|
||||
if (!spellInfo.HasAttribute(SpellAttr9.SummonPlayerTotem))
|
||||
if (!spellInfo.HasAttribute(SpellAttr7.CanBeMultiCast))
|
||||
continue;
|
||||
|
||||
CastSpellExtraArgs args = new(TriggerCastFlags.IgnoreGCD | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.CastDirectly | TriggerCastFlags.DontReportCastError);
|
||||
|
||||
@@ -3952,7 +3952,7 @@ namespace Game.Spells
|
||||
|
||||
public bool CanBeInterrupted(WorldObject interruptCaster, Unit interruptTarget, bool ignoreImmunity = false)
|
||||
{
|
||||
return HasAttribute(SpellAttr7.CanAlwaysBeInterrupted)
|
||||
return HasAttribute(SpellAttr7.NoUiNotInterruptible)
|
||||
|| HasChannelInterruptFlag(SpellAuraInterruptFlags.Damage | SpellAuraInterruptFlags.EnteringCombat)
|
||||
|| (interruptTarget.IsPlayer() && InterruptFlags.HasFlag(SpellInterruptFlags.DamageCancelsPlayerOnly))
|
||||
|| InterruptFlags.HasFlag(SpellInterruptFlags.DamageCancels)
|
||||
|
||||
Reference in New Issue
Block a user