From a294da63e4bbeea7eb1773e3b8c7c2c8de9a0fa7 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Sat, 31 Aug 2019 11:22:34 -0400 Subject: [PATCH] Core/Spells: refactor spell_enchant_proc_data table Port From (https://github.com/TrinityCore/TrinityCore/commit/420f2e8ec2c5f19db313492c52a730c87fa2dab6) --- .../Framework/Constants/Spells/SpellConst.cs | 6 +++ Source/Game/Entities/Player/Player.Spells.cs | 39 ++++++++++++++++--- Source/Game/Spells/SpellManager.cs | 18 +++++---- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/Source/Framework/Constants/Spells/SpellConst.cs b/Source/Framework/Constants/Spells/SpellConst.cs index 14a10c237..aeb04f16f 100644 --- a/Source/Framework/Constants/Spells/SpellConst.cs +++ b/Source/Framework/Constants/Spells/SpellConst.cs @@ -2502,4 +2502,10 @@ namespace Framework.Constants AutoRemove = 0x2, // if has autoremove, spell is remove automatically inside zone/area (always removed on leaving area or zone) IgnoreAutocastOnQuestStatusChange = 0x4, // if this flag is set then spell will not be applied automatically on quest status change } + + public enum EnchantProcAttributes + { + WhiteHit = 0x01, // enchant shall only proc off white hits (not abilities) + Limit60 = 0x02 // enchant effects shall be reduced past lvl 60 + } } diff --git a/Source/Game/Entities/Player/Player.Spells.cs b/Source/Game/Entities/Player/Player.Spells.cs index 2aa47e5fb..f1d34052b 100644 --- a/Source/Game/Entities/Player/Player.Spells.cs +++ b/Source/Game/Entities/Player/Player.Spells.cs @@ -3324,10 +3324,10 @@ namespace Game.Entities SpellEnchantProcEntry entry = Global.SpellMgr.GetSpellEnchantProcEvent(enchant_id); - if (entry != null && entry.procEx != 0) + if (entry != null && entry.HitMask != 0) { // Check hit/crit/dodge/parry requirement - if (((uint)entry.procEx & (uint)damageInfo.GetHitMask()) == 0) + if (((uint)entry.HitMask & (uint)damageInfo.GetHitMask()) == 0) continue; } else @@ -3337,6 +3337,10 @@ namespace Game.Entities continue; } + // check if enchant procs only on white hits + if (entry != null && entry.AttributesMask.HasAnyFlag(EnchantProcAttributes.WhiteHit) && damageInfo.GetSpellInfo() != null) + continue; + SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo(pEnchant.EffectArg[s]); if (spellInfo == null) { @@ -3349,10 +3353,10 @@ namespace Game.Entities if (entry != null) { - if (entry.PPMChance != 0) - chance = GetPPMProcChance(proto.GetDelay(), entry.PPMChance, spellInfo); - else if (entry.customChance != 0) - chance = entry.customChance; + if (entry.ProcsPerMinute != 0) + chance = GetPPMProcChance(proto.GetDelay(), entry.ProcsPerMinute, spellInfo); + else if (entry.Chance != 0) + chance = entry.Chance; } // Apply spell mods @@ -3369,6 +3373,29 @@ namespace Game.Entities else CastSpell(damageInfo.GetVictim(), spellInfo, true, item); } + + if (RandomHelper.randChance(chance)) + { + Unit target = spellInfo.IsPositive() ? this : damageInfo.GetVictim(); + + // reduce effect values if enchant is limited + Dictionary values = new Dictionary(); + if (entry != null && entry.AttributesMask.HasAnyFlag(EnchantProcAttributes.Limit60) && target.GetLevelForTarget(this) > 60) + { + int lvlDifference = (int)target.GetLevelForTarget(this) - 60; + int lvlPenaltyFactor = 4; // 4% lost effectiveness per level + + int effectPct = Math.Max(0, 100 - (lvlDifference * lvlPenaltyFactor)); + + for (byte i = 0; i < SpellConst.MaxEffects; ++i) + { + if (spellInfo.GetEffect(Difficulty.None, i).IsEffect()) + values.Add(SpellValueMod.BasePoint0 + i, MathFunctions.CalculatePct(spellInfo.GetEffect(Difficulty.None, i).CalcValue(this), effectPct)); + } + } + + CastCustomSpell(spellInfo.Id, values, target, TriggerCastFlags.FullMask, item); + } } } } diff --git a/Source/Game/Spells/SpellManager.cs b/Source/Game/Spells/SpellManager.cs index 027e8a2d1..d0249a780 100644 --- a/Source/Game/Spells/SpellManager.cs +++ b/Source/Game/Spells/SpellManager.cs @@ -1548,8 +1548,8 @@ namespace Game.Entities mSpellEnchantProcEventMap.Clear(); // need for reload case - // 0 1 2 3 - SQLResult result = DB.World.Query("SELECT entry, customChance, PPMChance, procEx FROM spell_enchant_proc_data"); + // 0 1 2 3 4 + SQLResult result = DB.World.Query("SELECT EnchantID, Chance, ProcsPerMinute, HitMask, AttributesMask FROM spell_enchant_proc_data"); if (result.IsEmpty()) { Log.outInfo(LogFilter.ServerLoading, "Loaded 0 spell enchant proc event conditions. DB table `spell_enchant_proc_data` is empty."); @@ -1569,9 +1569,10 @@ namespace Game.Entities } SpellEnchantProcEntry spe = new SpellEnchantProcEntry(); - spe.customChance = result.Read(1); - spe.PPMChance = result.Read(2); - spe.procEx = result.Read(3); + spe.Chance = result.Read(1); + spe.ProcsPerMinute = result.Read(2); + spe.HitMask = result.Read(3); + spe.AttributesMask = (EnchantProcAttributes)result.Read(4); mSpellEnchantProcEventMap[enchantId] = spe; @@ -3609,9 +3610,10 @@ namespace Game.Entities public class SpellEnchantProcEntry { - public uint customChance; - public float PPMChance; - public uint procEx; + public float Chance; // if nonzero - overwrite SpellItemEnchantment value + public float ProcsPerMinute; // if nonzero - chance to proc is equal to value * aura caster's weapon speed / 60 + public uint HitMask; // if nonzero - bitmask for matching proc condition based on hit result, see enum ProcFlagsHit + public EnchantProcAttributes AttributesMask; // bitmask, see EnchantProcAttributes } public class SpellTargetPosition