From 4568cdad48aa39112097c046adb1394268ed3a34 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 17 Mar 2021 18:52:59 -0400 Subject: [PATCH] Core/Spells: Define all spell modifier types and implement ProcCooldown mod and PeriodicHealingAndDamage for melee periodic damage Port From (https://github.com/TrinityCore/TrinityCore/commit/6585666e6e34ade0333e4c23876acdf847d169c0) --- Source/Framework/Collections/BitSet.cs | 11 ++ .../Framework/Constants/Spells/SpellConst.cs | 74 ++++++------ Source/Game/AI/CoreAI/TotemAI.cs | 2 +- Source/Game/Combat/ThreatManager.cs | 2 +- Source/Game/Entities/Player/Player.Spells.cs | 8 +- Source/Game/Entities/StatSystem.cs | 4 +- Source/Game/Entities/Unit/Unit.Combat.cs | 15 ++- Source/Game/Entities/Unit/Unit.Fields.cs | 3 +- Source/Game/Entities/Unit/Unit.Spells.cs | 46 ++++---- Source/Game/Spells/Auras/Aura.cs | 19 +++- Source/Game/Spells/Auras/AuraEffect.cs | 106 ++++++++---------- Source/Game/Spells/Spell.cs | 16 +-- Source/Game/Spells/SpellEffects.cs | 2 +- Source/Game/Spells/SpellInfo.cs | 14 ++- Source/Scripts/Spells/Druid.cs | 2 +- Source/Scripts/Spells/Warlock.cs | 2 +- 16 files changed, 168 insertions(+), 158 deletions(-) diff --git a/Source/Framework/Collections/BitSet.cs b/Source/Framework/Collections/BitSet.cs index 2cd5aa715..d84f774c5 100644 --- a/Source/Framework/Collections/BitSet.cs +++ b/Source/Framework/Collections/BitSet.cs @@ -192,6 +192,17 @@ namespace System.Collections return this; } + public bool Any() + { + for (var i = 0; i < Length; ++i) + { + if (Get(i)) + return true; + } + + return false; + } + public int Length { get diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index 5fa2ed281..a61e0ea58 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -317,50 +317,50 @@ namespace Framework.Constants public enum SpellModOp { - Damage = 0, + HealingAndDamage = 0, Duration = 1, - Threat = 2, - Effect1 = 3, - Charges = 4, + Hate = 2, + PointsIndex0 = 3, + ProcCharges = 4, Range = 5, Radius = 6, - CriticalChance = 7, - AllEffects = 8, - NotLoseCastingTime = 9, - CastingTime = 10, + CritChance = 7, + Points = 8, + ResistPushback = 9, + ChangeCastTime = 10, Cooldown = 11, - Effect2 = 12, - IgnoreArmor = 13, - Cost = 14, // Used when SpellPowerEntry.PowerIndex == 0 - CritDamageBonus = 15, - ResistMissChance = 16, - JumpTargets = 17, - ChanceOfSuccess = 18, - ActivationTime = 19, - DamageMultiplier = 20, - GlobalCooldown = 21, - Dot = 22, - Effect3 = 23, - BonusMultiplier = 24, - // Spellmod 25 - ProcPerMinute = 26, - ValueMultiplier = 27, - ResistDispelChance = 28, - CritDamageBonus2 = 29, //One Not Used Spell - SpellCostRefundOnFail = 30, - StackAmount = 31, - Effect4 = 32, - Effect5 = 33, - SpellCost2 = 34, // Used when SpellPowerEntry.PowerIndex == 1 - JumpDistance = 35, - // spellmod 36 - MaxStackAmount = 37, - // spellmod 38 - SpellCost3 = 39, + PointsIndex1 = 12, + TargetResistance = 13, + PowerCost0 = 14, // Used when SpellPowerEntry::PowerIndex == 0 + CritDamageAndHealing = 15, + HitChance = 16, + ChainTargets = 17, + ProcChance = 18, + Period = 19, + ChainAmplitude = 20, + StartCooldown = 21, + PeriodicHealingAndDamage = 22, + PointsIndex2 = 23, + BonusCoefficient = 24, + TriggerDamage = 25, // NYI + ProcFrequency = 26, + Amplitude = 27, + DispelResistance = 28, + CrowdDamage = 29, // NYI + PowerCostOnMiss = 30, + Doses = 31, + PointsIndex3 = 32, + PointsIndex4 = 33, + PowerCost1 = 34, // Used when SpellPowerEntry::PowerIndex == 1 + ChainJumpDistance = 35, + AreaTriggerMaxSummons = 36, // NYI + MaxAuraStacks = 37, + ProcCooldown = 38, + PowerCost2 = 39, // Used when SpellPowerEntry::PowerIndex == 2 Max = 40 } - // Note: SPELLMOD_* values is aura types in fact + public enum SpellModType { Flat = 0, // SPELL_AURA_ADD_FLAT_MODIFIER diff --git a/Source/Game/AI/CoreAI/TotemAI.cs b/Source/Game/AI/CoreAI/TotemAI.cs index 6755f8b24..eb962e6c5 100644 --- a/Source/Game/AI/CoreAI/TotemAI.cs +++ b/Source/Game/AI/CoreAI/TotemAI.cs @@ -49,7 +49,7 @@ namespace Game.AI // Get spell range float max_range = spellInfo.GetMaxRange(false); - // SPELLMOD_RANGE not applied in this place just because not existence range mods for attacking totems + // SpellModOp.Range not applied in this place just because not existence range mods for attacking totems Unit victim = !i_victimGuid.IsEmpty() ? Global.ObjAccessor.GetUnit(me, i_victimGuid) : null; diff --git a/Source/Game/Combat/ThreatManager.cs b/Source/Game/Combat/ThreatManager.cs index eccaff156..c047865a2 100644 --- a/Source/Game/Combat/ThreatManager.cs +++ b/Source/Game/Combat/ThreatManager.cs @@ -352,7 +352,7 @@ namespace Game.Combat Player modOwner = hatedUnit.GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(threatSpell, SpellModOp.Threat, ref threat); + modOwner.ApplySpellMod(threatSpell, SpellModOp.Hate, ref threat); } return hatedUnit.ApplyTotalThreatModifier(threat, schoolMask); diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index 74c0a4167..a6a726c3d 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -2729,7 +2729,7 @@ namespace Game.Entities switch (op) { // special case, if a mod makes spell instant, only consume that mod - case SpellModOp.CastingTime: + case SpellModOp.ChangeCastTime: { SpellModifier modInstantSpell = null; foreach (SpellModifier mod in m_spellMods[(int)op][(int)SpellModType.Pct]) @@ -2753,7 +2753,7 @@ namespace Game.Entities break; } // special case if two mods apply 100% critical chance, only consume one - case SpellModOp.CriticalChance: + case SpellModOp.CritChance: { SpellModifier modCritical = null; foreach (SpellModifier mod in m_spellMods[(int)op][(int)SpellModType.Flat]) @@ -2799,7 +2799,7 @@ namespace Game.Entities continue; // special case (skip > 10sec spell casts for instant cast setting) - if (op == SpellModOp.CastingTime) + if (op == SpellModOp.ChangeCastTime) { if (baseValue.CompareTo(10000) > 0 && mod.value <= -100) continue; @@ -3213,7 +3213,7 @@ namespace Game.Entities } // Apply spell mods - ApplySpellMod(spellInfo, SpellModOp.ChanceOfSuccess, ref chance); + ApplySpellMod(spellInfo, SpellModOp.ProcChance, ref chance); // Shiv has 100% chance to apply the poison if (FindCurrentSpellBySpellId(5938) != null && e_slot == (byte)EnchantmentSlot.Temp) diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index d7464d5bd..5f056db46 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -771,13 +771,13 @@ namespace Game.Entities if (spellInfo == null && HaveOffhandWeapon() && !IsInFeralForm()) missChance += 19.0f; - // Spellmod from SPELLMOD_RESIST_MISS_CHANCE + // Spellmod from SpellModOp.HitChance float resistMissChance = 100.0f; if (spellInfo != null) { Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spellInfo, SpellModOp.ResistMissChance, ref resistMissChance); + modOwner.ApplySpellMod(spellInfo, SpellModOp.HitChance, ref resistMissChance); } missChance += resistMissChance - 100.0f; diff --git a/Source/Game/Entities/Unit/Unit.Combat.cs b/Source/Game/Entities/Unit/Unit.Combat.cs index 2fffea28b..d7a26d0ac 100644 --- a/Source/Game/Entities/Unit/Unit.Combat.cs +++ b/Source/Game/Entities/Unit/Unit.Combat.cs @@ -1772,7 +1772,7 @@ namespace Game.Entities { Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spellProto, SpellModOp.ProcPerMinute, ref PPM); + modOwner.ApplySpellMod(spellProto, SpellModOp.ProcFrequency, ref PPM); } return (float)Math.Floor((WeaponSpeed * PPM) / 600.0f); // result is chance in percents (probability = Speed_in_sec * (PPM / 60)) @@ -1916,7 +1916,7 @@ namespace Game.Entities damage += CalculateDamage(damageInfo.attackType, false, true); // Add melee damage bonus - damage = MeleeDamageBonusDone(damageInfo.target, damage, damageInfo.attackType); + damage = MeleeDamageBonusDone(damageInfo.target, damage, damageInfo.attackType, DamageEffectType.Direct); damage = damageInfo.target.MeleeDamageBonusTaken(this, damage, damageInfo.attackType, DamageEffectType.Direct); // Script Hook For CalculateMeleeDamage -- Allow scripts to change the Damage pre class mitigation calculations @@ -2737,7 +2737,7 @@ namespace Game.Entities { Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spellInfo, SpellModOp.IgnoreArmor, ref armor); + modOwner.ApplySpellMod(spellInfo, SpellModOp.TargetResistance, ref armor); } var resIgnoreAuras = GetAuraEffectsByType(AuraType.ModIgnoreTargetResist); @@ -2780,7 +2780,7 @@ namespace Game.Entities return Math.Max((uint)(damage * (1.0f - mitigation)), 1); } - public uint MeleeDamageBonusDone(Unit victim, uint pdamage, WeaponAttackType attType, SpellInfo spellProto = null) + public uint MeleeDamageBonusDone(Unit victim, uint pdamage, WeaponAttackType attType, DamageEffectType damagetype, SpellInfo spellProto = null) { if (victim == null || pdamage == 0) return 0; @@ -2874,7 +2874,12 @@ namespace Game.Entities { Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spellProto, SpellModOp.Damage, ref tmpDamage); + { + if (damagetype == DamageEffectType.DOT) + modOwner.ApplySpellMod(spellProto, SpellModOp.PeriodicHealingAndDamage, ref tmpDamage); + else + modOwner.ApplySpellMod(spellProto, SpellModOp.HealingAndDamage, ref tmpDamage); + } } // bonus result can be negative diff --git a/Source/Game/Entities/Unit/Unit.Fields.cs b/Source/Game/Entities/Unit/Unit.Fields.cs index 91e33d154..7b36edfb6 100644 --- a/Source/Game/Entities/Unit/Unit.Fields.cs +++ b/Source/Game/Entities/Unit/Unit.Fields.cs @@ -286,6 +286,7 @@ namespace Game.Entities case MeleeHitOutcome.Evade: m_hitMask |= ProcFlagsHit.Evade; break; + case MeleeHitOutcome.Block: case MeleeHitOutcome.Crushing: case MeleeHitOutcome.Glancing: case MeleeHitOutcome.Normal: @@ -296,8 +297,6 @@ namespace Game.Entities if (!damageNullified) m_hitMask |= ProcFlagsHit.Critical; break; - default: - break; } } diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index d77159445..a78691199 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -121,7 +121,7 @@ namespace Game.Entities if (modOwner) { ApCoeffMod *= 100.0f; - modOwner.ApplySpellMod(spellProto, SpellModOp.BonusMultiplier, ref ApCoeffMod); + modOwner.ApplySpellMod(spellProto, SpellModOp.BonusCoefficient, ref ApCoeffMod); ApCoeffMod /= 100.0f; } @@ -145,7 +145,7 @@ namespace Game.Entities if (modOwner) { coeff *= 100.0f; - modOwner.ApplySpellMod(spellProto, SpellModOp.BonusMultiplier, ref coeff); + modOwner.ApplySpellMod(spellProto, SpellModOp.BonusCoefficient, ref coeff); coeff /= 100.0f; } DoneTotal += (int)(DoneAdvertisedBenefit * coeff * stack); @@ -158,9 +158,9 @@ namespace Game.Entities if (_modOwner) { if (damagetype == DamageEffectType.DOT) - _modOwner.ApplySpellMod(spellProto, SpellModOp.Dot, ref tmpDamage); + _modOwner.ApplySpellMod(spellProto, SpellModOp.PeriodicHealingAndDamage, ref tmpDamage); else - _modOwner.ApplySpellMod(spellProto, SpellModOp.Damage, ref tmpDamage); + _modOwner.ApplySpellMod(spellProto, SpellModOp.HealingAndDamage, ref tmpDamage); } return (uint)Math.Max(tmpDamage, 0.0f); @@ -321,7 +321,7 @@ namespace Game.Entities if (modOwner) { coeff *= 100.0f; - modOwner.ApplySpellMod(spellProto, SpellModOp.BonusMultiplier, ref coeff); + modOwner.ApplySpellMod(spellProto, SpellModOp.BonusCoefficient, ref coeff); coeff /= 100.0f; } TakenTotal += (int)(TakenAdvertisedBenefit * coeff * stack); @@ -400,7 +400,7 @@ namespace Game.Entities // adds additional damage to critBonus (from talents) Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spellProto, SpellModOp.CritDamageBonus, ref crit_bonus); + modOwner.ApplySpellMod(spellProto, SpellModOp.CritDamageAndHealing, ref crit_bonus); damage += crit_bonus; @@ -467,7 +467,7 @@ namespace Game.Entities if (modOwner) { coeff *= 100.0f; - modOwner.ApplySpellMod(spellProto, SpellModOp.BonusMultiplier, ref coeff); + modOwner.ApplySpellMod(spellProto, SpellModOp.BonusCoefficient, ref coeff); coeff /= 100.0f; } @@ -498,9 +498,9 @@ namespace Game.Entities if (_modOwner) { if (damagetype == DamageEffectType.DOT) - _modOwner.ApplySpellMod(spellProto, SpellModOp.Dot, ref heal); + _modOwner.ApplySpellMod(spellProto, SpellModOp.PeriodicHealingAndDamage, ref heal); else - _modOwner.ApplySpellMod(spellProto, SpellModOp.Damage, ref heal); + _modOwner.ApplySpellMod(spellProto, SpellModOp.HealingAndDamage, ref heal); } return (uint)Math.Max(heal, 0.0f); @@ -599,7 +599,7 @@ namespace Game.Entities if (modOwner) { coeff *= 100.0f; - modOwner.ApplySpellMod(spellProto, SpellModOp.BonusMultiplier, ref coeff); + modOwner.ApplySpellMod(spellProto, SpellModOp.BonusCoefficient, ref coeff); coeff /= 100.0f; } @@ -763,7 +763,7 @@ namespace Game.Entities // only players use intelligence for critical chance computations Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spellProto, SpellModOp.CriticalChance, ref crit_chance); + modOwner.ApplySpellMod(spellProto, SpellModOp.CritChance, ref crit_chance); // for this types the bonus was already added in GetUnitCriticalChance, do not add twice if (spellProto.DmgClass != SpellDmgClass.Melee && spellProto.DmgClass != SpellDmgClass.Ranged) @@ -1012,10 +1012,10 @@ namespace Game.Entities else modHitChance = 97 - levelBasedHitDiff; - // Spellmod from SPELLMOD_RESIST_MISS_CHANCE + // Spellmod from SpellModOp.HitChance Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spell, SpellModOp.ResistMissChance, ref modHitChance); + modOwner.ApplySpellMod(spell, SpellModOp.HitChance, ref modHitChance); // Spells with SPELL_ATTR3_IGNORE_HIT_RESULT will ignore target's avoidance effects if (!spell.HasAttribute(SpellAttr3.IgnoreHitResult)) @@ -2021,7 +2021,7 @@ namespace Game.Entities // called from caster Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spellInfo, SpellModOp.CastingTime, ref castTime, spell); + modOwner.ApplySpellMod(spellInfo, SpellModOp.ChangeCastTime, ref castTime, spell); if (!(spellInfo.HasAttribute(SpellAttr0.Ability | SpellAttr0.Tradespell) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus)) && (IsTypeId(TypeId.Player) && spellInfo.SpellFamilyName != 0) || IsTypeId(TypeId.Unit)) @@ -2042,7 +2042,7 @@ namespace Game.Entities // called from caster Player modOwner = GetSpellModOwner(); if (modOwner) - modOwner.ApplySpellMod(spellInfo, SpellModOp.CastingTime, ref duration, spell); + modOwner.ApplySpellMod(spellInfo, SpellModOp.ChangeCastTime, ref duration, spell); if (!(spellInfo.HasAttribute(SpellAttr0.Ability) || spellInfo.HasAttribute(SpellAttr0.Tradespell) || spellInfo.HasAttribute(SpellAttr3.NoDoneBonus)) && (IsTypeId(TypeId.Player) && spellInfo.SpellFamilyName != 0) || IsTypeId(TypeId.Unit)) @@ -2055,23 +2055,23 @@ namespace Game.Entities Player modOwner = GetSpellModOwner(); if (modOwner != null) { - modOwner.ApplySpellMod(spellProto, SpellModOp.AllEffects, ref value); + modOwner.ApplySpellMod(spellProto, SpellModOp.Points, ref value); switch (effect_index) { case 0: - modOwner.ApplySpellMod(spellProto, SpellModOp.Effect1, ref value); + modOwner.ApplySpellMod(spellProto, SpellModOp.PointsIndex0, ref value); break; case 1: - modOwner.ApplySpellMod(spellProto, SpellModOp.Effect2, ref value); + modOwner.ApplySpellMod(spellProto, SpellModOp.PointsIndex1, ref value); break; case 2: - modOwner.ApplySpellMod(spellProto, SpellModOp.Effect3, ref value); + modOwner.ApplySpellMod(spellProto, SpellModOp.PointsIndex2, ref value); break; case 3: - modOwner.ApplySpellMod(spellProto, SpellModOp.Effect4, ref value); + modOwner.ApplySpellMod(spellProto, SpellModOp.PointsIndex3, ref value); break; case 4: - modOwner.ApplySpellMod(spellProto, SpellModOp.Effect5, ref value); + modOwner.ApplySpellMod(spellProto, SpellModOp.PointsIndex4, ref value); break; } } @@ -2230,7 +2230,7 @@ namespace Game.Entities // adds additional damage to critBonus (from talents) Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spellProto, SpellModOp.CritDamageBonus, ref crit_bonus); + modOwner.ApplySpellMod(spellProto, SpellModOp.CritDamageAndHealing, ref crit_bonus); crit_bonus += (int)damage; @@ -2444,7 +2444,7 @@ namespace Game.Entities // Apply crit_damage bonus for melee spells Player modOwner = GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(spellInfo, SpellModOp.CritDamageBonus, ref crit_bonus); + modOwner.ApplySpellMod(spellInfo, SpellModOp.CritDamageAndHealing, ref crit_bonus); damage += (int)crit_bonus; // Increase crit damage from SPELL_AURA_MOD_CRIT_DAMAGE_BONUS diff --git a/Source/Game/Spells/Auras/Aura.cs b/Source/Game/Spells/Auras/Aura.cs index 1cce0aea6..34d2bb7c4 100644 --- a/Source/Game/Spells/Auras/Aura.cs +++ b/Source/Game/Spells/Auras/Aura.cs @@ -878,7 +878,7 @@ namespace Game.Spells { Player modOwner = caster.GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(m_spellInfo, SpellModOp.MaxStackAmount, ref maxStackAmount); + modOwner.ApplySpellMod(m_spellInfo, SpellModOp.MaxAuraStacks, ref maxStackAmount); } return maxStackAmount; } @@ -1025,7 +1025,7 @@ namespace Game.Spells { Player modOwner = caster.GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.ResistDispelChance, ref resistChance); + modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.DispelResistance, ref resistChance); } resistChance = resistChance < 0 ? 0 : resistChance; @@ -1652,7 +1652,16 @@ namespace Game.Spells } // cooldowns should be added to the whole aura (see 51698 area aura) - AddProcCooldown(now + TimeSpan.FromMilliseconds(procEntry.Cooldown)); + int procCooldown = (int)procEntry.Cooldown; + Unit caster = GetCaster(); + if (caster != null) + { + Player modOwner = caster.GetSpellModOwner(); + if (modOwner != null) + modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.ProcCooldown, ref procCooldown); + } + + AddProcCooldown(now + TimeSpan.FromMilliseconds(procCooldown)); SetLastProcSuccessTime(now); } @@ -1807,7 +1816,7 @@ namespace Game.Spells // apply chance modifer aura, applies also to ppm chance (see improved judgement of light spell) Player modOwner = caster.GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.ChanceOfSuccess, ref chance); + modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.ProcChance, ref chance); } // proc chance is reduced by an additional 3.333% per level past 60 @@ -2321,7 +2330,7 @@ namespace Game.Spells { Player modOwner = caster.GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.Charges, ref maxProcCharges); + modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.ProcCharges, ref maxProcCharges); } return (byte)maxProcCharges; } diff --git a/Source/Game/Spells/Auras/AuraEffect.cs b/Source/Game/Spells/Auras/AuraEffect.cs index 077c65b5d..1343e272e 100644 --- a/Source/Game/Spells/Auras/AuraEffect.cs +++ b/Source/Game/Spells/Auras/AuraEffect.cs @@ -27,6 +27,7 @@ using Game.Networking.Packets; using System; using System.Collections.Generic; using System.Linq; +using System.Collections; namespace Game.Spells { @@ -188,7 +189,7 @@ namespace Game.Spells { // Apply periodic time mod if (modOwner != null) - modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.ActivationTime, ref _period); + modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.Period, ref _period); if (caster != null) { @@ -346,71 +347,54 @@ namespace Game.Spells return; // reapply some passive spells after add/remove related spellmods // Warning: it is a dead loop if 2 auras each other amount-shouldn't happen + BitSet recalculateEffectMask = new(SpellConst.MaxEffects); switch ((SpellModOp)GetMiscValue()) { - case SpellModOp.AllEffects: - case SpellModOp.Effect1: - case SpellModOp.Effect2: - case SpellModOp.Effect3: - case SpellModOp.Effect4: - case SpellModOp.Effect5: - { - ObjectGuid guid = target.GetGUID(); - foreach (var iter in target.GetAppliedAuras()) - { - if (iter.Value == null) - continue; - Aura aura = iter.Value.GetBase(); - // only passive and permament auras-active auras should have amount set on spellcast and not be affected - // if aura is casted by others, it will not be affected - if ((aura.IsPassive() || aura.IsPermanent()) && aura.GetCasterGUID() == guid && aura.GetSpellInfo().IsAffectedBySpellMod(m_spellmod)) - { - AuraEffect aurEff; - if ((SpellModOp)GetMiscValue() == SpellModOp.AllEffects) - { - for (byte i = 0; i < SpellConst.MaxEffects; ++i) - { - if ((aurEff = aura.GetEffect(i)) != null) - aurEff.RecalculateAmount(); - } - } - else if ((SpellModOp)GetMiscValue() == SpellModOp.Effect1) - { - aurEff = aura.GetEffect(0); - if (aurEff != null) - aurEff.RecalculateAmount(); - } - else if ((SpellModOp)GetMiscValue() == SpellModOp.Effect2) - { - aurEff = aura.GetEffect(1); - if (aurEff != null) - aurEff.RecalculateAmount(); - } - else if ((SpellModOp)GetMiscValue() == SpellModOp.Effect3) - { - aurEff = aura.GetEffect(2); - if (aurEff != null) - aurEff.RecalculateAmount(); - } - else if ((SpellModOp)GetMiscValue() == SpellModOp.Effect4) - { - aurEff = aura.GetEffect(3); - if (aurEff != null) - aurEff.RecalculateAmount(); - } - else if ((SpellModOp)GetMiscValue() == SpellModOp.Effect5) - { - aurEff = aura.GetEffect(4); - if (aurEff != null) - aurEff.RecalculateAmount(); - } - } - } - } + case SpellModOp.Points: + recalculateEffectMask.SetAll(true); + break; + case SpellModOp.PointsIndex0: + recalculateEffectMask.Set(0, true); + break; + case SpellModOp.PointsIndex1: + recalculateEffectMask.Set(1, true); + break; + case SpellModOp.PointsIndex2: + recalculateEffectMask.Set(2, true); + break; + case SpellModOp.PointsIndex3: + recalculateEffectMask.Set(3, true); + break; + case SpellModOp.PointsIndex4: + recalculateEffectMask.Set(4, true); break; default: break; } + + if (recalculateEffectMask.Any()) + { + ObjectGuid guid = target.GetGUID(); + var auras = target.GetAppliedAuras(); + foreach (var iter in auras) + { + Aura aura = iter.Value.GetBase(); + // only passive and permament auras-active auras should have amount set on spellcast and not be affected + // if aura is cast by others, it will not be affected + if ((aura.IsPassive() || aura.IsPermanent()) && aura.GetCasterGUID() == guid && aura.GetSpellInfo().IsAffectedBySpellMod(m_spellmod)) + { + for (uint i = 0; i < recalculateEffectMask.Count; ++i) + { + if (recalculateEffectMask[(int)i]) + { + AuraEffect aurEff = aura.GetEffect(i); + if (aurEff != null) + aurEff.RecalculateAmount(); + } + } + } + } + } } public void Update(uint diff, Unit caster) @@ -4910,7 +4894,7 @@ namespace Game.Spells uint weaponDamage = MathFunctions.CalculatePct(caster.CalculateDamage(attackType, false, true), GetAmount()); // Add melee damage bonuses (also check for negative) - uint damageBonusDone = caster.MeleeDamageBonusDone(target, Math.Max(weaponDamage, 0), attackType, GetSpellInfo()); + uint damageBonusDone = caster.MeleeDamageBonusDone(target, Math.Max(weaponDamage, 0), attackType, DamageEffectType.DOT, GetSpellInfo()); damage = target.MeleeDamageBonusTaken(caster, damageBonusDone, attackType, DamageEffectType.DOT, GetSpellInfo()); break; diff --git a/Source/Game/Spells/Spell.cs b/Source/Game/Spells/Spell.cs index d64a42679..8c908bfce 100644 --- a/Source/Game/Spells/Spell.cs +++ b/Source/Game/Spells/Spell.cs @@ -68,7 +68,7 @@ namespace Game.Spells Player modOwner = caster.GetSpellModOwner(); if (modOwner != null) - modOwner.ApplySpellMod(info, SpellModOp.StackAmount, ref m_spellValue.AuraStackAmount, this); + modOwner.ApplySpellMod(info, SpellModOp.Doses, ref m_spellValue.AuraStackAmount, this); if (!originalCasterGUID.IsEmpty()) m_originalCasterGUID = originalCasterGUID; @@ -1089,7 +1089,7 @@ namespace Game.Spells int maxTargets = effect.ChainTargets; Player modOwner = m_caster.GetSpellModOwner(); if (modOwner) - modOwner.ApplySpellMod(m_spellInfo, SpellModOp.JumpTargets, ref maxTargets, this); + modOwner.ApplySpellMod(m_spellInfo, SpellModOp.ChainTargets, ref maxTargets, this); if (maxTargets > 1) { @@ -1411,7 +1411,7 @@ namespace Game.Spells Player modOwner = m_caster.GetSpellModOwner(); if (modOwner) - modOwner.ApplySpellMod(m_spellInfo, SpellModOp.JumpDistance, ref jumpRadius, this); + modOwner.ApplySpellMod(m_spellInfo, SpellModOp.ChainJumpDistance, ref jumpRadius, this); // chain lightning/heal spells and similar - allow to jump at larger distance and go out of los bool isBouncingFar = (m_spellInfo.HasAttribute(SpellAttr4.AreaTargetChain) @@ -4210,7 +4210,7 @@ namespace Game.Spells //lower spell cost on fail (by talent aura) Player modOwner = m_caster.ToPlayer().GetSpellModOwner(); if (modOwner) - modOwner.ApplySpellMod(m_spellInfo, SpellModOp.SpellCostRefundOnFail, ref cost.Amount); + modOwner.ApplySpellMod(m_spellInfo, SpellModOp.PowerCostOnMiss, ref cost.Amount); } break; } @@ -6434,7 +6434,7 @@ namespace Game.Spells //check pushback reduce int delaytime = 500; // spellcasting delay is normally 500ms int delayReduce = 100; // must be initialized to 100 for percent modifiers - m_caster.ToPlayer().ApplySpellMod(m_spellInfo, SpellModOp.NotLoseCastingTime, ref delayReduce, this); + m_caster.ToPlayer().ApplySpellMod(m_spellInfo, SpellModOp.ResistPushback, ref delayReduce, this); delayReduce += m_caster.GetTotalAuraModifier(AuraType.ReducePushback) - 100; if (delayReduce >= 100) return; @@ -6469,7 +6469,7 @@ namespace Game.Spells //check pushback reduce int delaytime = MathFunctions.CalculatePct(m_spellInfo.GetDuration(), 25); // channeling delay is normally 25% of its time per hit int delayReduce = 100; // must be initialized to 100 for percent modifiers - m_caster.ToPlayer().ApplySpellMod(m_spellInfo, SpellModOp.NotLoseCastingTime, ref delayReduce, this); + m_caster.ToPlayer().ApplySpellMod(m_spellInfo, SpellModOp.ResistPushback, ref delayReduce, this); delayReduce += m_caster.GetTotalAuraModifier(AuraType.ReducePushback) - 100; if (delayReduce >= 100) return; @@ -7236,7 +7236,7 @@ namespace Game.Spells // gcd modifier auras are applied only to own spells and only players have such mods Player modOwner = m_caster.GetSpellModOwner(); if (modOwner) - modOwner.ApplySpellMod(m_spellInfo, SpellModOp.GlobalCooldown, ref gcd, this); + modOwner.ApplySpellMod(m_spellInfo, SpellModOp.StartCooldown, ref gcd, this); bool isMeleeOrRangedSpell = m_spellInfo.DmgClass == SpellDmgClass.Melee || m_spellInfo.DmgClass == SpellDmgClass.Ranged || m_spellInfo.HasAttribute(SpellAttr0.ReqAmmo) || m_spellInfo.HasAttribute(SpellAttr0.Ability); @@ -7724,7 +7724,7 @@ namespace Game.Spells { public SpellModifier(Aura _ownerAura) { - op = SpellModOp.Damage; + op = SpellModOp.HealingAndDamage; type = SpellModType.Flat; value = 0; mask = new FlagArray128(); diff --git a/Source/Game/Spells/SpellEffects.cs b/Source/Game/Spells/SpellEffects.cs index 1e18699c7..0ecc0d44f 100644 --- a/Source/Game/Spells/SpellEffects.cs +++ b/Source/Game/Spells/SpellEffects.cs @@ -2635,7 +2635,7 @@ namespace Game.Spells uint eff_damage = Math.Max(weaponDamage, 0); // Add melee damage bonuses (also check for negative) - uint damage = m_caster.MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, m_spellInfo); + uint damage = m_caster.MeleeDamageBonusDone(unitTarget, eff_damage, m_attackType, DamageEffectType.Direct, m_spellInfo); m_damage += (int)unitTarget.MeleeDamageBonusTaken(m_caster, damage, m_attackType, DamageEffectType.SpellDirect, m_spellInfo); } diff --git a/Source/Game/Spells/SpellInfo.cs b/Source/Game/Spells/SpellInfo.cs index e7c48406a..598e7a415 100644 --- a/Source/Game/Spells/SpellInfo.cs +++ b/Source/Game/Spells/SpellInfo.cs @@ -2839,13 +2839,13 @@ namespace Game.Spells switch (power.OrderIndex) { case 0: - mod = SpellModOp.Cost; + mod = SpellModOp.PowerCost0; break; case 1: - mod = SpellModOp.SpellCost2; + mod = SpellModOp.PowerCost1; break; case 2: - mod = SpellModOp.SpellCost3; + mod = SpellModOp.PowerCost2; break; default: break; @@ -3410,7 +3410,9 @@ namespace Game.Spells // non-positive mods switch ((SpellModOp)effect.MiscValue) { - case SpellModOp.Cost: // dependent from bas point sign (negative . positive) + case SpellModOp.PowerCost0: // dependent from bas point sign (negative . positive) + case SpellModOp.PowerCost1: + case SpellModOp.PowerCost2: if (effect.CalcValue() > 0) { if (!deep) @@ -3963,7 +3965,7 @@ namespace Game.Spells float multiplier = Amplitude; Player modOwner = (caster != null ? caster.GetSpellModOwner() : null); if (modOwner != null) - modOwner.ApplySpellMod(_spellInfo, SpellModOp.ValueMultiplier, ref multiplier, spell); + modOwner.ApplySpellMod(_spellInfo, SpellModOp.Amplitude, ref multiplier, spell); return multiplier; } @@ -3972,7 +3974,7 @@ namespace Game.Spells float multiplierPercent = ChainAmplitude * 100.0f; Player modOwner = (caster != null ? caster.GetSpellModOwner() : null); if (modOwner != null) - modOwner.ApplySpellMod(_spellInfo, SpellModOp.DamageMultiplier, ref multiplierPercent, spell); + modOwner.ApplySpellMod(_spellInfo, SpellModOp.ChainAmplitude, ref multiplierPercent, spell); return multiplierPercent / 100.0f; } diff --git a/Source/Scripts/Spells/Druid.cs b/Source/Scripts/Spells/Druid.cs index 830889bed..e91e3b363 100644 --- a/Source/Scripts/Spells/Druid.cs +++ b/Source/Scripts/Spells/Druid.cs @@ -415,7 +415,7 @@ namespace Scripts.Spells.Druid if (spellMod == null) { spellMod = new SpellModifier(GetAura()); - spellMod.op = SpellModOp.Dot; + spellMod.op = SpellModOp.PeriodicHealingAndDamage; spellMod.type = SpellModType.Flat; spellMod.spellId = GetId(); spellMod.mask = aurEff.GetSpellEffectInfo().SpellClassMask; diff --git a/Source/Scripts/Spells/Warlock.cs b/Source/Scripts/Spells/Warlock.cs index c3861e714..0f55b8660 100644 --- a/Source/Scripts/Spells/Warlock.cs +++ b/Source/Scripts/Spells/Warlock.cs @@ -279,7 +279,7 @@ namespace Scripts.Spells.Warlock Player modOwner = caster.GetSpellModOwner(); if (modOwner) - modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.Cost, ref damage); + modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.PowerCost0, ref damage); SpellNonMeleeDamage damageInfo = new SpellNonMeleeDamage(caster, caster, GetSpellInfo(), GetAura().GetSpellVisual(), GetSpellInfo().SchoolMask, GetAura().GetCastGUID()); damageInfo.periodicLog = true;