Core/Spells: Named and implemented most of SpellAttr7

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