From 7bd260c2df1441f4d498adcf4cd75e54eb82189c Mon Sep 17 00:00:00 2001 From: hondacrx Date: Wed, 4 Oct 2017 15:07:46 -0400 Subject: [PATCH] compute aura diminishing return info at startup and cache it --- Framework/Constants/Spells/SpellAuraConst.cs | 2 + Game/Entities/Object/WorldObject.cs | 14 +- Game/Entities/Unit/Unit.Fields.cs | 25 +- Game/Entities/Unit/Unit.Spells.cs | 110 +++-- Game/Server/WorldManager.cs | 3 + Game/Spells/Spell.cs | 36 +- Game/Spells/SpellInfo.cs | 419 +++++++++++++++++++ Game/Spells/SpellManager.cs | 393 +---------------- 8 files changed, 530 insertions(+), 472 deletions(-) diff --git a/Framework/Constants/Spells/SpellAuraConst.cs b/Framework/Constants/Spells/SpellAuraConst.cs index 5def98e67..6b1eab93e 100644 --- a/Framework/Constants/Spells/SpellAuraConst.cs +++ b/Framework/Constants/Spells/SpellAuraConst.cs @@ -551,6 +551,8 @@ namespace Framework.Constants AOEKnockback = 6, Taunt = 7, LimitOnly = 8, + + Max } public enum DiminishingLevels diff --git a/Game/Entities/Object/WorldObject.cs b/Game/Entities/Object/WorldObject.cs index 27deb2aaf..5baa8a721 100644 --- a/Game/Entities/Object/WorldObject.cs +++ b/Game/Entities/Object/WorldObject.cs @@ -2506,14 +2506,14 @@ namespace Game.Entities public void SetFieldNotifyFlag(uint flag) { _fieldNotifyFlags |= flag; } public void RemoveFieldNotifyFlag(uint flag) { _fieldNotifyFlags &= ~flag; } - bool IsCreature() { return GetTypeId() == TypeId.Unit; } + public bool IsCreature() { return GetTypeId() == TypeId.Unit; } public bool IsPlayer() { return GetTypeId() == TypeId.Player; } - bool IsGameObject() { return GetTypeId() == TypeId.GameObject; } - bool IsUnit() { return isTypeMask(TypeMask.Unit); } - bool IsCorpse() { return GetTypeId() == TypeId.Corpse; } - bool IsDynObject() { return GetTypeId() == TypeId.DynamicObject; } - bool IsAreaTrigger() { return GetTypeId() == TypeId.AreaTrigger; } - bool IsConversation() { return GetTypeId() == TypeId.Conversation; } + public bool IsGameObject() { return GetTypeId() == TypeId.GameObject; } + public bool IsUnit() { return isTypeMask(TypeMask.Unit); } + public bool IsCorpse() { return GetTypeId() == TypeId.Corpse; } + public bool IsDynObject() { return GetTypeId() == TypeId.DynamicObject; } + public bool IsAreaTrigger() { return GetTypeId() == TypeId.AreaTrigger; } + public bool IsConversation() { return GetTypeId() == TypeId.Conversation; } public Creature ToCreature() { return IsCreature() ? (this as Creature) : null; } public Player ToPlayer() { return IsPlayer() ? (this as Player) : null; } diff --git a/Game/Entities/Unit/Unit.Fields.cs b/Game/Entities/Unit/Unit.Fields.cs index eaab6d833..27befb439 100644 --- a/Game/Entities/Unit/Unit.Fields.cs +++ b/Game/Entities/Unit/Unit.Fields.cs @@ -107,7 +107,7 @@ namespace Game.Entities uint m_removedAurasCount; //General - List m_Diminishing = new List(); + Array m_Diminishing = new Array((int)DiminishingGroup.Max); protected List m_gameObj = new List(); List m_areaTrigger = new List(); protected List m_dynObj = new List(); @@ -140,18 +140,23 @@ namespace Game.Entities public class DiminishingReturn { - public DiminishingReturn(DiminishingGroup group, uint t, DiminishingLevels count) + public DiminishingReturn(uint hitTime, DiminishingLevels hitCount) { - DRGroup = group; - stack = 0; - hitTime = t; - hitCount = count; + Stack = 0; + HitTime = hitTime; + HitCount = hitCount; } - public DiminishingGroup DRGroup; - public uint stack; - public uint hitTime; - public DiminishingLevels hitCount; + public void Clear() + { + Stack = 0; + HitTime = 0; + HitCount = DiminishingLevels.Level1; + } + + public uint Stack; + public uint HitTime; + public DiminishingLevels HitCount; } public class ProcEventInfo diff --git a/Game/Entities/Unit/Unit.Spells.cs b/Game/Entities/Unit/Unit.Spells.cs index 01e29acdd..2a427f27e 100644 --- a/Game/Entities/Unit/Unit.Spells.cs +++ b/Game/Entities/Unit/Unit.Spells.cs @@ -2657,61 +2657,57 @@ namespace Game.Entities public DiminishingLevels GetDiminishing(DiminishingGroup group) { - foreach (var dim in m_Diminishing) + DiminishingReturn diminish = m_Diminishing[(int)group]; + if (diminish == null) + return DiminishingLevels.Level1; + + if (diminish.HitCount == 0) + return DiminishingLevels.Level1; + + if (diminish.HitTime == 0) + return DiminishingLevels.Level1; + + // If last spell was cast more than 18 seconds ago - reset the count. + if (diminish.Stack == 0 && Time.GetMSTimeDiffToNow(diminish.HitTime) > 18 * Time.InMilliseconds) { - if (dim.DRGroup != group) - continue; - - if (dim.hitCount == 0) - return DiminishingLevels.Level1; - - if (dim.hitTime == 0) - return DiminishingLevels.Level1; - - // If last spell was casted more than 18 seconds ago - reset the count. - if (dim.stack == 0 && Time.GetMSTimeDiff(dim.hitTime, Time.GetMSTime()) > 18 * Time.InMilliseconds) - { - dim.hitCount = DiminishingLevels.Level1; - return DiminishingLevels.Level1; - } - // or else increase the count. - else - return dim.hitCount; + diminish.HitCount = DiminishingLevels.Level1; + return DiminishingLevels.Level1; } - return DiminishingLevels.Level1; + + return diminish.HitCount; } - public void IncrDiminishing(DiminishingGroup group) + public void IncrDiminishing(SpellInfo auraSpellInfo, bool triggered) { + DiminishingGroup group = auraSpellInfo.GetDiminishingReturnsGroupForSpell(triggered); + DiminishingLevels maxLevel = auraSpellInfo.GetDiminishingReturnsMaxLevel(triggered); + // Checking for existing in the table - foreach (var dim in m_Diminishing) - { - if (dim.DRGroup != group) - continue; - if (dim.hitCount < Global.SpellMgr.GetDiminishingReturnsMaxLevel(group)) - dim.hitCount += 1; - return; - } - m_Diminishing.Add(new DiminishingReturn(group, Time.GetMSTime(), DiminishingLevels.Level2)); + DiminishingReturn diminish = m_Diminishing[(int)group]; + if (diminish.HitCount < maxLevel) + ++diminish.HitCount; } - public float ApplyDiminishingToDuration(DiminishingGroup group, int duration, Unit caster, DiminishingLevels Level, int limitduration) + public float ApplyDiminishingToDuration(SpellInfo auraSpellInfo, bool triggered, ref int duration, Unit caster, DiminishingLevels previousLevel) { + DiminishingGroup group = auraSpellInfo.GetDiminishingReturnsGroupForSpell(triggered); if (duration == -1 || group == DiminishingGroup.None) return 1.0f; + int limitDuration = auraSpellInfo.GetDiminishingReturnsLimitDuration(triggered); + // test pet/charm masters instead pets/charmeds Unit targetOwner = GetCharmerOrOwner(); Unit casterOwner = caster.GetCharmerOrOwner(); - if (limitduration > 0 && duration > limitduration) + if (limitDuration > 0 && duration > limitDuration) { Unit target = targetOwner ?? this; Unit source = casterOwner ?? caster; if ((target.IsTypeId(TypeId.Player) || target.ToCreature().GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.AllDiminish)) && source.IsTypeId(TypeId.Player)) - duration = limitduration; + duration = limitDuration; } float mod = 1.0f; @@ -2721,7 +2717,7 @@ namespace Game.Entities case DiminishingGroup.Taunt: if (IsTypeId(TypeId.Unit) && ToCreature().GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.TauntDiminish)) { - DiminishingLevels diminish = Level; + DiminishingLevels diminish = previousLevel; switch (diminish) { case DiminishingLevels.Level1: @@ -2744,11 +2740,11 @@ namespace Game.Entities } break; case DiminishingGroup.AOEKnockback: - if ((Global.SpellMgr.GetDiminishingReturnsGroupType(group) == DiminishingReturnsType.Player && (((targetOwner ? targetOwner : this).ToPlayer()) - || IsTypeId(TypeId.Unit) && ToCreature().GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.AllDiminish))) - || Global.SpellMgr.GetDiminishingReturnsGroupType(group) == DiminishingReturnsType.All) + if ((auraSpellInfo.GetDiminishingReturnsGroupType(triggered) == DiminishingReturnsType.Player && (((targetOwner ? targetOwner : this).ToPlayer()) + || IsCreature() && ToCreature().GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.AllDiminish))) + || auraSpellInfo.GetDiminishingReturnsGroupType(triggered) == DiminishingReturnsType.All) { - DiminishingLevels diminish = Level; + DiminishingLevels diminish = previousLevel; switch (diminish) { case DiminishingLevels.Level1: @@ -2762,11 +2758,11 @@ namespace Game.Entities } break; default: - if ((Global.SpellMgr.GetDiminishingReturnsGroupType(group) == DiminishingReturnsType.Player && (((targetOwner ? targetOwner : this).ToPlayer()) - || IsTypeId(TypeId.Unit) && ToCreature().GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.AllDiminish))) - || Global.SpellMgr.GetDiminishingReturnsGroupType(group) == DiminishingReturnsType.All) + if ((auraSpellInfo.GetDiminishingReturnsGroupType(triggered) == DiminishingReturnsType.Player && (((targetOwner ? targetOwner : this).ToPlayer()) + || IsCreature() && ToCreature().GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.AllDiminish))) + || auraSpellInfo.GetDiminishingReturnsGroupType(triggered) == DiminishingReturnsType.All) { - DiminishingLevels diminish = Level; + DiminishingLevels diminish = previousLevel; switch (diminish) { case DiminishingLevels.Level1: @@ -2793,24 +2789,26 @@ namespace Game.Entities public void ApplyDiminishingAura(DiminishingGroup group, bool apply) { // Checking for existing in the table - foreach (var dim in m_Diminishing) - { - if (dim.DRGroup != group) - continue; + DiminishingReturn diminish = m_Diminishing[(int)group]; - if (apply) - dim.stack += 1; - else if (dim.stack != 0) - { - dim.stack -= 1; - // Remember time after last aura from group removed - if (dim.stack == 0) - dim.hitTime = Time.GetMSTime(); - } - break; + if (apply) + ++diminish.Stack; + else if (diminish.Stack != 0) + { + --diminish.Stack; + + // Remember time after last aura from group removed + if (diminish.Stack == 0) + diminish.HitTime = Time.GetMSTime(); } } + void ClearDiminishings() + { + for (int i = 0; i < (int)DiminishingGroup.Max; ++i) + m_Diminishing[i].Clear(); + } + public uint GetRemainingPeriodicAmount(ObjectGuid caster, uint spellId, AuraType auraType, int effectIndex = 0) { uint amount = 0; diff --git a/Game/Server/WorldManager.cs b/Game/Server/WorldManager.cs index cf4a50e19..708a95336 100644 --- a/Game/Server/WorldManager.cs +++ b/Game/Server/WorldManager.cs @@ -374,6 +374,9 @@ namespace Game Log.outInfo(LogFilter.ServerLoading, "Loading SpellInfo SpellSpecific and AuraState..."); Global.SpellMgr.LoadSpellInfoSpellSpecificAndAuraState(); + Log.outInfo(LogFilter.ServerLoading, "Loading SpellInfo diminishing infos..."); + Global.SpellMgr.LoadSpellInfoDiminishing(); + Log.outInfo(LogFilter.ServerLoading, "Loading PetFamilySpellsStore Data..."); Global.SpellMgr.LoadPetFamilySpellsStore(); diff --git a/Game/Spells/Spell.cs b/Game/Spells/Spell.cs index e8459eb18..df3f7fd09 100644 --- a/Game/Spells/Spell.cs +++ b/Game/Spells/Spell.cs @@ -107,8 +107,6 @@ namespace Game.Spells _triggeredCastFlags = _triggeredCastFlags | TriggerCastFlags.IgnoreCastInProgress | TriggerCastFlags.CastDirectly; effectHandleMode = SpellEffectHandleMode.Launch; - m_diminishLevel = DiminishingLevels.Level1; - m_diminishGroup = DiminishingGroup.None; //Auto Shot & Shoot (wand) m_autoRepeat = m_spellInfo.IsAutoRepeatRangedSpell(); @@ -2113,15 +2111,19 @@ namespace Game.Spells aura_effmask |= (1u << (int)effect.EffectIndex); // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add - m_diminishGroup = Global.SpellMgr.GetDiminishingReturnsGroupForSpell(m_spellInfo); - if (m_diminishGroup != 0 && aura_effmask != 0) - { + bool triggered = m_triggeredByAuraSpell != null; + DiminishingGroup diminishGroup = m_spellInfo.GetDiminishingReturnsGroupForSpell(triggered); - m_diminishLevel = unit.GetDiminishing(m_diminishGroup); - DiminishingReturnsType type = Global.SpellMgr.GetDiminishingReturnsGroupType(m_diminishGroup); + DiminishingLevels diminishLevel = DiminishingLevels.Level1; + if (diminishGroup != 0 && aura_effmask != 0) + { + diminishLevel = unit.GetDiminishing(diminishGroup); + DiminishingReturnsType type = m_spellInfo.GetDiminishingReturnsGroupType(triggered); // Increase Diminishing on unit, current informations for actually casts will use values above - if ((type == DiminishingReturnsType.Player && unit.GetCharmerOrOwnerPlayerOrPlayerItself() != null) || type == DiminishingReturnsType.All) - unit.IncrDiminishing(m_diminishGroup); + if ((type == DiminishingReturnsType.Player && (unit.GetCharmerOrOwnerPlayerOrPlayerItself() + || (unit.IsCreature() && unit.ToCreature().GetCreatureTemplate().FlagsExtra.HasAnyFlag(CreatureFlagsExtra.AllDiminish)))) + || type == DiminishingReturnsType.All) + unit.IncrDiminishing(m_spellInfo, triggered); } if (aura_effmask != 0) @@ -2168,8 +2170,7 @@ namespace Game.Spells // Now Reduce spell duration using data received at spell hit int duration = m_spellAura.GetMaxDuration(); - int limitduration = m_diminishGroup != 0 ? Global.SpellMgr.GetDiminishingReturnsLimitDuration(aurSpellInfo) : 0; - float diminishMod = unit.ApplyDiminishingToDuration(m_diminishGroup, duration, m_originalCaster, m_diminishLevel, limitduration); + float diminishMod = unit.ApplyDiminishingToDuration(aurSpellInfo, triggered, ref duration, m_originalCaster, diminishLevel); // unit is immune to aura if it was diminished to 0 duration if (diminishMod == 0.0f) @@ -2184,7 +2185,7 @@ namespace Game.Spells } else { - ((UnitAura)m_spellAura).SetDiminishGroup(m_diminishGroup); + ((UnitAura)m_spellAura).SetDiminishGroup(diminishGroup); bool positive = m_spellAura.GetSpellInfo().IsPositive(); AuraApplication aurApp = m_spellAura.GetApplicationOfTarget(m_originalCaster.GetGUID()); @@ -3053,9 +3054,6 @@ namespace Game.Spells void _handle_immediate_phase() { m_spellAura = null; - // initialize Diminishing Returns Data - m_diminishLevel = DiminishingLevels.Level1; - m_diminishGroup = DiminishingGroup.None; // handle some immediate features of the spell here HandleThreatSpells(); @@ -4262,7 +4260,7 @@ namespace Game.Spells continue; // positive spells distribute threat among all units that are in combat with target, like healing - if (m_spellInfo._IsPositiveSpell()) + if (m_spellInfo.IsPositive()) target.getHostileRefManager().threatAssist(m_caster, threatToAdd, m_spellInfo); // for negative spells threat gets distributed among affected targets else @@ -4273,7 +4271,7 @@ namespace Game.Spells target.AddThreat(m_caster, threatToAdd, m_spellInfo.GetSchoolMask(), m_spellInfo); } } - Log.outDebug(LogFilter.Spells, "Spell {0}, added an additional {1} threat for {2} {3} target(s)", m_spellInfo.Id, threat, m_spellInfo._IsPositiveSpell() ? "assisting" : "harming", m_UniqueTargetInfo.Count); + Log.outDebug(LogFilter.Spells, "Spell {0}, added an additional {1} threat for {2} {3} target(s)", m_spellInfo.Id, threat, m_spellInfo.IsPositive() ? "assisting" : "harming", m_UniqueTargetInfo.Count); } void HandleEffects(Unit pUnitTarget, Item pItemTarget, GameObject pGOTarget, uint i, SpellEffectHandleMode mode) @@ -7228,10 +7226,6 @@ namespace Game.Spells // used in effects handlers public Aura m_spellAura; - // this is set in Spell Hit, but used in Apply Aura handler - DiminishingLevels m_diminishLevel; - DiminishingGroup m_diminishGroup; - // ------------------------------------------- GameObject focusObject; diff --git a/Game/Spells/SpellInfo.cs b/Game/Spells/SpellInfo.cs index dc4b69fbf..21e09f485 100644 --- a/Game/Spells/SpellInfo.cs +++ b/Game/Spells/SpellInfo.cs @@ -1537,6 +1537,415 @@ namespace Game.Spells } } + public void _LoadSpellDiminishInfo() + { + SpellDiminishInfo diminishInfo = new SpellDiminishInfo(); + diminishInfo.DiminishGroup = diminishingGroupCompute(); + diminishInfo.DiminishReturnType = diminishingTypeCompute(diminishInfo.DiminishGroup); + diminishInfo.DiminishMaxLevel = diminishingMaxLevelCompute(diminishInfo.DiminishGroup); + diminishInfo.DiminishDurationLimit = diminishingLimitDurationCompute(); + + _diminishInfo = diminishInfo; + } + + public DiminishingGroup GetDiminishingReturnsGroupForSpell() + { + return _diminishInfo.DiminishGroup; + } + + public DiminishingReturnsType GetDiminishingReturnsGroupType() + { + return _diminishInfo.DiminishReturnType; + } + + public DiminishingLevels GetDiminishingReturnsMaxLevel(bool triggered) + { + return _diminishInfo.DiminishMaxLevel; + } + + public int GetDiminishingReturnsLimitDuration(bool triggered) + { + return _diminishInfo.DiminishDurationLimit; + } + + DiminishingGroup diminishingGroupCompute() + { + if (IsPositive()) + return DiminishingGroup.None; + + if (HasAura(Difficulty.None, AuraType.ModTaunt)) + return DiminishingGroup.Taunt; + + switch (Id) + { + case 64803: // Entrapment + case 135373: // Entrapment + return DiminishingGroup.Root; + case 24394: // Intimidation + return DiminishingGroup.Stun; + case 118345: // Pulverize (Primal Earth Elemental) + return DiminishingGroup.Stun; + case 118905: // Static Charge (Capacitor Totem) + return DiminishingGroup.Stun; + case 108199: // Gorefiend's Grasp + return DiminishingGroup.AOEKnockback; + default: + break; + } + + // Explicit Diminishing Groups + switch (SpellFamilyName) + { + case SpellFamilyNames.Generic: + break; + case SpellFamilyNames.Mage: + { + // Frostjaw -- 102051 + if (SpellFamilyFlags[2].HasAnyFlag(0x40000u)) + return DiminishingGroup.Silence; + + // Frost Nova -- 122 + if (SpellFamilyFlags[0].HasAnyFlag(0x40u)) + return DiminishingGroup.Root; + // Ice Ward -- 111340 + if (SpellFamilyFlags[0].HasAnyFlag(0x80000u) && SpellFamilyFlags[2].HasAnyFlag(0x2000u)) + return DiminishingGroup.Root; + // Freeze (Water Elemental) -- 33395 + if (SpellFamilyFlags[2].HasAnyFlag(0x200u)) + return DiminishingGroup.Root; + + // Deep Freeze -- 44572 + if (SpellFamilyFlags[1].HasAnyFlag(0x100000u)) + return DiminishingGroup.Stun; + + // Dragon's Breath -- 31661 + if (SpellFamilyFlags[0].HasAnyFlag(0x800000u)) + return DiminishingGroup.Incapacitate; + // Polymorph -- 118 + if (SpellFamilyFlags[0].HasAnyFlag(0x1000000u)) + return DiminishingGroup.Incapacitate; + // Ring of Frost -- 82691 + if (SpellFamilyFlags[2].HasAnyFlag(0x40u)) + return DiminishingGroup.Incapacitate; + // Ice Nova -- 157997 + if (SpellFamilyFlags[2].HasAnyFlag(0x800000u)) + return DiminishingGroup.Incapacitate; + break; + } + case SpellFamilyNames.Warrior: + { + // Shockwave -- 132168 + if (SpellFamilyFlags[1].HasAnyFlag(0x8000u)) + return DiminishingGroup.Stun; + // Storm Bolt -- 132169 + if (SpellFamilyFlags[2].HasAnyFlag(0x1000u)) + return DiminishingGroup.Stun; + + // Intimidating Shout -- 5246 + if (SpellFamilyFlags[0].HasAnyFlag(0x40000u)) + return DiminishingGroup.Disorient; + + // Hamstring -- 1715, 8 seconds in PvP (6.0) + if (SpellFamilyFlags[0].HasAnyFlag(0x2u)) + return DiminishingGroup.LimitOnly; + break; + } + case SpellFamilyNames.Warlock: + { + // Mortal Coil -- 6789 + if (SpellFamilyFlags[0].HasAnyFlag(0x80000u)) + return DiminishingGroup.Incapacitate; + // Banish -- 710 + if (SpellFamilyFlags[1].HasAnyFlag(0x8000000u)) + return DiminishingGroup.Incapacitate; + + // Fear -- 118699 + if (SpellFamilyFlags[1].HasAnyFlag(0x400u)) + return DiminishingGroup.Disorient; + // Howl of Terror -- 5484 + if (SpellFamilyFlags[1].HasAnyFlag(0x8u)) + return DiminishingGroup.Disorient; + + // Shadowfury -- 30283 + if (SpellFamilyFlags[1].HasAnyFlag(0x1000u)) + return DiminishingGroup.Stun; + // Summon Infernal -- 22703 + if (SpellFamilyFlags[0].HasAnyFlag(0x1000u)) + return DiminishingGroup.Stun; + break; + } + case SpellFamilyNames.WarlockPet: + { + // Fellash -- 115770 + // Whiplash -- 6360 + if (SpellFamilyFlags[0].HasAnyFlag(0x8000000u)) + return DiminishingGroup.AOEKnockback; + + // Mesmerize (Shivarra pet) -- 115268 + // Seduction (Succubus pet) -- 6358 + if (SpellFamilyFlags[0].HasAnyFlag(0x2000000u)) + return DiminishingGroup.Disorient; + + // Axe Toss (Felguard pet) -- 89766 + if (SpellFamilyFlags[1].HasAnyFlag(0x4u)) + return DiminishingGroup.Stun; + break; + } + case SpellFamilyNames.Druid: + { + // Maim -- 22570 + if (SpellFamilyFlags[1].HasAnyFlag(0x80u)) + return DiminishingGroup.Stun; + // Mighty Bash -- 5211 + if (SpellFamilyFlags[0].HasAnyFlag(0x2000u)) + return DiminishingGroup.Stun; + // Rake -- 163505 -- no flags on the stun + if (Id == 163505) + return DiminishingGroup.Stun; + + // Incapacitating Roar -- 99, no flags on the stun, 14 + if (SpellFamilyFlags[1].HasAnyFlag(0x1u)) + return DiminishingGroup.Incapacitate; + + // Cyclone -- 33786 + if (SpellFamilyFlags[1].HasAnyFlag(0x20u)) + return DiminishingGroup.Disorient; + + // Typhoon -- 61391 + if (SpellFamilyFlags[1].HasAnyFlag(0x1000000u)) + return DiminishingGroup.AOEKnockback; + // Ursol's Vortex -- 118283, no family flags + if (Id == 118283) + return DiminishingGroup.AOEKnockback; + + // Entangling Roots -- 339 + if (SpellFamilyFlags[0].HasAnyFlag(0x200u)) + return DiminishingGroup.Root; + // Mass Entanglement -- 102359 + if (SpellFamilyFlags[2].HasAnyFlag(0x4u)) + return DiminishingGroup.Root; + + // Faerie Fire -- 770, 20 seconds in PvP (6.0) + if (SpellFamilyFlags[0].HasAnyFlag(0x400u)) + return DiminishingGroup.LimitOnly; + break; + } + case SpellFamilyNames.Rogue: + { + // Cheap Shot -- 1833 + if (SpellFamilyFlags[0].HasAnyFlag(0x400u)) + return DiminishingGroup.Stun; + // Kidney Shot -- 408 + if (SpellFamilyFlags[0].HasAnyFlag(0x200000u)) + return DiminishingGroup.Stun; + + // Gouge -- 1776 + if (SpellFamilyFlags[0].HasAnyFlag(0x8u)) + return DiminishingGroup.Incapacitate; + // Sap -- 6770 + if (SpellFamilyFlags[0].HasAnyFlag(0x80u)) + return DiminishingGroup.Incapacitate; + + // Blind -- 2094 + if (SpellFamilyFlags[0].HasAnyFlag(0x1000000u)) + return DiminishingGroup.Disorient; + + // Garrote -- 1330 + if (SpellFamilyFlags[1].HasAnyFlag(0x20000000u)) + return DiminishingGroup.Silence; + break; + } + case SpellFamilyNames.Hunter: + { + // Charge (Tenacity pet) -- 53148, no flags + if (Id == 53148) + return DiminishingGroup.Root; + // Narrow Escape -- 136634, no flags + if (Id == 136634) + return DiminishingGroup.Root; + + // Binding Shot -- 117526, no flags + if (Id == 117526) + return DiminishingGroup.Stun; + + // Freezing Trap -- 3355 + if (SpellFamilyFlags[0].HasAnyFlag(0x8u)) + return DiminishingGroup.Incapacitate; + // Wyvern Sting -- 19386 + if (SpellFamilyFlags[1].HasAnyFlag(0x1000u)) + return DiminishingGroup.Incapacitate; + break; + } + case SpellFamilyNames.Paladin: + { + // Repentance -- 20066 + if (SpellFamilyFlags[0].HasAnyFlag(0x4u)) + return DiminishingGroup.Incapacitate; + + // Turn Evil -- 10326 + if (SpellFamilyFlags[1].HasAnyFlag(0x800000u)) + return DiminishingGroup.Disorient; + + // Avenger's Shield -- 31935 + if (SpellFamilyFlags[0].HasAnyFlag(0x4000u)) + return DiminishingGroup.Silence; + + // Fist of Justice -- 105593 + // Hammer of Justice -- 853 + if (SpellFamilyFlags[0].HasAnyFlag(0x800u)) + return DiminishingGroup.Stun; + // Holy Wrath -- 119072 + if (SpellFamilyFlags[1].HasAnyFlag(0x200000u)) + return DiminishingGroup.Stun; + break; + } + case SpellFamilyNames.Shaman: + { + // Hex -- 51514 + if (SpellFamilyFlags[1].HasAnyFlag(0x8000u)) + return DiminishingGroup.Incapacitate; + + // Thunderstorm -- 51490 + if (SpellFamilyFlags[1].HasAnyFlag(0x2000u)) + return DiminishingGroup.AOEKnockback; + // Earthgrab Totem -- 64695 + if (SpellFamilyFlags[2].HasAnyFlag(0x4000u)) + return DiminishingGroup.Root; + break; + } + case SpellFamilyNames.Deathknight: + { + // Strangulate -- 47476 + if (SpellFamilyFlags[0].HasAnyFlag(0x200u)) + return DiminishingGroup.Silence; + + // Asphyxiate -- 108194 + if (SpellFamilyFlags[2].HasAnyFlag(0x100000u)) + return DiminishingGroup.Stun; + // Gnaw (Ghoul) -- 91800, no flags + if (Id == 91800) + return DiminishingGroup.Stun; + // Monstrous Blow (Ghoul w/ Dark Transformation active) -- 91797 + if (Id == 91797) + return DiminishingGroup.Stun; + break; + } + case SpellFamilyNames.Priest: + { + // Dominate Mind -- 605 + if (SpellFamilyFlags[0].HasAnyFlag(0x20000u) && GetSpellVisual() == 39068) + return DiminishingGroup.Incapacitate; + // Holy Word: Chastise -- 88625 + if (SpellFamilyFlags[2].HasAnyFlag(0x20u)) + return DiminishingGroup.Incapacitate; + // Psychic Horror -- 64044 + if (SpellFamilyFlags[2].HasAnyFlag(0x2000u)) + return DiminishingGroup.Incapacitate; + + // Psychic Scream -- 8122 + if (SpellFamilyFlags[0].HasAnyFlag(0x10000u)) + return DiminishingGroup.Disorient; + + // Silence -- 15487 + if (SpellFamilyFlags[1].HasAnyFlag(0x200000u) && SchoolMask == (SpellSchoolMask)32) + return DiminishingGroup.Silence; + break; + } + case SpellFamilyNames.Monk: + { + // Disable -- 116706, no flags + if (Id == 116706) + return DiminishingGroup.Root; + + // Charging Ox Wave -- 119392 + if (SpellFamilyFlags[1].HasAnyFlag(0x10000u)) + return DiminishingGroup.Stun; + // Fists of Fury -- 120086 + if (SpellFamilyFlags[1].HasAnyFlag(0x800000u) && !SpellFamilyFlags[2].HasAnyFlag(0x8u)) + return DiminishingGroup.Stun; + // Leg Sweep -- 119381 + if (SpellFamilyFlags[1].HasAnyFlag(0x200u)) + return DiminishingGroup.Stun; + + // Incendiary Breath (honor talent) -- 202274, no flags + if (Id == 202274) + return DiminishingGroup.Incapacitate; + // Paralysis -- 115078 + if (SpellFamilyFlags[2].HasAnyFlag(0x800000u)) + return DiminishingGroup.Incapacitate; + break; + } + default: + break; + } + + return DiminishingGroup.None; + } + + DiminishingReturnsType diminishingTypeCompute(DiminishingGroup group) + { + switch (group) + { + case DiminishingGroup.Taunt: + case DiminishingGroup.Stun: + return DiminishingReturnsType.All; + case DiminishingGroup.LimitOnly: + case DiminishingGroup.None: + return DiminishingReturnsType.None; + default: + return DiminishingReturnsType.Player; + } + } + + DiminishingLevels diminishingMaxLevelCompute(DiminishingGroup group) + { + switch (group) + { + case DiminishingGroup.Taunt: + return DiminishingLevels.TauntImmune; + case DiminishingGroup.AOEKnockback: + return DiminishingLevels.Level2; + default: + return DiminishingLevels.Immune; + } + } + + int diminishingLimitDurationCompute() + { + // Explicit diminishing duration + switch (SpellFamilyName) + { + case SpellFamilyNames.Druid: + { + // Faerie Fire - 20 seconds in PvP (6.0) + if (SpellFamilyFlags[0].HasAnyFlag(0x400u)) + return 20 * Time.InMilliseconds; + break; + } + case SpellFamilyNames.Hunter: + { + // Binding Shot - 3 seconds in PvP (6.0) + if (Id == 117526) + return 3 * Time.InMilliseconds; + // Wyvern Sting - 6 seconds in PvP (6.0) + if (SpellFamilyFlags[1].HasAnyFlag(0x1000u)) + return 6 * Time.InMilliseconds; + break; + } + case SpellFamilyNames.Monk: + { + // Paralysis - 4 seconds in PvP regardless of if they are facing you (6.0) + if (SpellFamilyFlags[2].HasAnyFlag(0x800000u)) + return 4 * Time.InMilliseconds; + break; + } + default: + break; + } + + return 8 * Time.InMilliseconds; + } + public float GetMinRange(bool positive = false) { if (RangeEntry == null) @@ -2666,6 +3075,8 @@ namespace Game.Spells bool _hasPowerDifficultyData; SpellSpecificType _spellSpecific; AuraStateType _auraState; + + SpellDiminishInfo _diminishInfo; #endregion public struct ScalingInfo @@ -3707,5 +4118,13 @@ namespace Game.Spells public PowerType Power; public int Amount; } + + class SpellDiminishInfo + { + public DiminishingGroup DiminishGroup = DiminishingGroup.None; + public DiminishingReturnsType DiminishReturnType = DiminishingReturnsType.None; + public DiminishingLevels DiminishMaxLevel = DiminishingLevels.Immune; + public int DiminishDurationLimit; + } } diff --git a/Game/Spells/SpellManager.cs b/Game/Spells/SpellManager.cs index c2a850944..c645b0642 100644 --- a/Game/Spells/SpellManager.cs +++ b/Game/Spells/SpellManager.cs @@ -626,384 +626,6 @@ namespace Game.Entities return mSpellAreaForQuestAreaMap.LookupByKey(Tuple.Create(area_id, quest_id)); } - public DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo spellproto) - { - if (spellproto.IsPositive()) - return DiminishingGroup.None; - - if (spellproto.HasAura(Difficulty.None, AuraType.ModTaunt)) - return DiminishingGroup.Taunt; - - switch (spellproto.Id) - { - case 64803: // Entrapment - case 135373: // Entrapment - return DiminishingGroup.Root; - case 24394: // Intimidation - return DiminishingGroup.Stun; - case 118345: // Pulverize (Primal Earth Elemental) - return DiminishingGroup.Stun; - case 118905: // Static Charge (Capacitor Totem) - return DiminishingGroup.Stun; - case 108199: // Gorefiend's Grasp - return DiminishingGroup.AOEKnockback; - default: - break; - } - - // Explicit Diminishing Groups - switch (spellproto.SpellFamilyName) - { - case SpellFamilyNames.Generic: - break; - case SpellFamilyNames.Mage: - { - // Frostjaw -- 102051 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x40000u)) - return DiminishingGroup.Silence; - - // Frost Nova -- 122 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x40u)) - return DiminishingGroup.Root; - // Ice Ward -- 111340 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x80000u) && spellproto.SpellFamilyFlags[2].HasAnyFlag(0x2000u)) - return DiminishingGroup.Root; - // Freeze (Water Elemental) -- 33395 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x200u)) - return DiminishingGroup.Root; - - // Deep Freeze -- 44572 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x100000u)) - return DiminishingGroup.Stun; - - // Dragon's Breath -- 31661 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x800000u)) - return DiminishingGroup.Incapacitate; - // Polymorph -- 118 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x1000000u)) - return DiminishingGroup.Incapacitate; - // Ring of Frost -- 82691 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x40u)) - return DiminishingGroup.Incapacitate; - // Ice Nova -- 157997 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x800000u)) - return DiminishingGroup.Incapacitate; - break; - } - case SpellFamilyNames.Warrior: - { - // Shockwave -- 132168 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x8000u)) - return DiminishingGroup.Stun; - // Storm Bolt -- 132169 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x1000u)) - return DiminishingGroup.Stun; - - // Intimidating Shout -- 5246 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x40000u)) - return DiminishingGroup.Disorient; - - // Hamstring -- 1715, 8 seconds in PvP (6.0) - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x2u)) - return DiminishingGroup.LimitOnly; - break; - } - case SpellFamilyNames.Warlock: - { - // Mortal Coil -- 6789 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x80000u)) - return DiminishingGroup.Incapacitate; - // Banish -- 710 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x8000000u)) - return DiminishingGroup.Incapacitate; - - // Fear -- 118699 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x400u)) - return DiminishingGroup.Disorient; - // Howl of Terror -- 5484 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x8u)) - return DiminishingGroup.Disorient; - - // Shadowfury -- 30283 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x1000u)) - return DiminishingGroup.Stun; - // Summon Infernal -- 22703 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x1000u)) - return DiminishingGroup.Stun; - break; - } - case SpellFamilyNames.WarlockPet: - { - // Fellash -- 115770 - // Whiplash -- 6360 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x8000000u)) - return DiminishingGroup.AOEKnockback; - - // Mesmerize (Shivarra pet) -- 115268 - // Seduction (Succubus pet) -- 6358 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x2000000u)) - return DiminishingGroup.Disorient; - - // Axe Toss (Felguard pet) -- 89766 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x4u)) - return DiminishingGroup.Stun; - break; - } - case SpellFamilyNames.Druid: - { - // Maim -- 22570 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x80u)) - return DiminishingGroup.Stun; - // Mighty Bash -- 5211 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x2000u)) - return DiminishingGroup.Stun; - // Rake -- 163505 -- no flags on the stun - if (spellproto.Id == 163505) - return DiminishingGroup.Stun; - - // Incapacitating Roar -- 99, no flags on the stun, 14 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x1u)) - return DiminishingGroup.Incapacitate; - - // Cyclone -- 33786 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x20u)) - return DiminishingGroup.Disorient; - - // Typhoon -- 61391 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x1000000u)) - return DiminishingGroup.AOEKnockback; - // Ursol's Vortex -- 118283, no family flags - if (spellproto.Id == 118283) - return DiminishingGroup.AOEKnockback; - - // Entangling Roots -- 339 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x200u)) - return DiminishingGroup.Root; - // Mass Entanglement -- 102359 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x4u)) - return DiminishingGroup.Root; - - // Faerie Fire -- 770, 20 seconds in PvP (6.0) - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x400u)) - return DiminishingGroup.LimitOnly; - break; - } - case SpellFamilyNames.Rogue: - { - // Cheap Shot -- 1833 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x400u)) - return DiminishingGroup.Stun; - // Kidney Shot -- 408 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x200000u)) - return DiminishingGroup.Stun; - - // Gouge -- 1776 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x8u)) - return DiminishingGroup.Incapacitate; - // Sap -- 6770 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x80u)) - return DiminishingGroup.Incapacitate; - - // Blind -- 2094 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x1000000u)) - return DiminishingGroup.Disorient; - - // Garrote -- 1330 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x20000000u)) - return DiminishingGroup.Silence; - break; - } - case SpellFamilyNames.Hunter: - { - // Charge (Tenacity pet) -- 53148, no flags - if (spellproto.Id == 53148) - return DiminishingGroup.Root; - // Narrow Escape -- 136634, no flags - if (spellproto.Id == 136634) - return DiminishingGroup.Root; - - // Binding Shot -- 117526, no flags - if (spellproto.Id == 117526) - return DiminishingGroup.Stun; - - // Freezing Trap -- 3355 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x8u)) - return DiminishingGroup.Incapacitate; - // Wyvern Sting -- 19386 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x1000u)) - return DiminishingGroup.Incapacitate; - break; - } - case SpellFamilyNames.Paladin: - { - // Repentance -- 20066 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x4u)) - return DiminishingGroup.Incapacitate; - - // Turn Evil -- 10326 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x800000u)) - return DiminishingGroup.Disorient; - - // Avenger's Shield -- 31935 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x4000u)) - return DiminishingGroup.Silence; - - // Fist of Justice -- 105593 - // Hammer of Justice -- 853 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x800u)) - return DiminishingGroup.Stun; - // Holy Wrath -- 119072 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x200000u)) - return DiminishingGroup.Stun; - break; - } - case SpellFamilyNames.Shaman: - { - // Hex -- 51514 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x8000u)) - return DiminishingGroup.Incapacitate; - - // Thunderstorm -- 51490 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x2000u)) - return DiminishingGroup.AOEKnockback; - // Earthgrab Totem -- 64695 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x4000u)) - return DiminishingGroup.Root; - break; - } - case SpellFamilyNames.Deathknight: - { - // Strangulate -- 47476 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x200u)) - return DiminishingGroup.Silence; - - // Asphyxiate -- 108194 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x100000u)) - return DiminishingGroup.Stun; - // Gnaw (Ghoul) -- 91800, no flags - if (spellproto.Id == 91800) - return DiminishingGroup.Stun; - // Monstrous Blow (Ghoul w/ Dark Transformation active) -- 91797 - if (spellproto.Id == 91797) - return DiminishingGroup.Stun; - break; - } - case SpellFamilyNames.Priest: - { - // Dominate Mind -- 605 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x20000u) && spellproto.GetSpellVisual() == 39068) - return DiminishingGroup.Incapacitate; - // Holy Word: Chastise -- 88625 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x20u)) - return DiminishingGroup.Incapacitate; - // Psychic Horror -- 64044 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x2000u)) - return DiminishingGroup.Incapacitate; - - // Psychic Scream -- 8122 - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x10000u)) - return DiminishingGroup.Disorient; - - // Silence -- 15487 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x200000u) && spellproto.SchoolMask == (SpellSchoolMask)32) - return DiminishingGroup.Silence; - break; - } - case SpellFamilyNames.Monk: - { - // Disable -- 116706, no flags - if (spellproto.Id == 116706) - return DiminishingGroup.Root; - - // Charging Ox Wave -- 119392 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x10000u)) - return DiminishingGroup.Stun; - // Fists of Fury -- 120086 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x800000u) && !spellproto.SpellFamilyFlags[2].HasAnyFlag(0x8u)) - return DiminishingGroup.Stun; - // Leg Sweep -- 119381 - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x200u)) - return DiminishingGroup.Stun; - - // Incendiary Breath (honor talent) -- 202274, no flags - if (spellproto.Id == 202274) - return DiminishingGroup.Incapacitate; - // Paralysis -- 115078 - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x800000u)) - return DiminishingGroup.Incapacitate; - break; - } - default: - break; - } - - return DiminishingGroup.None; - } - - public DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group) - { - switch (group) - { - case DiminishingGroup.Taunt: - case DiminishingGroup.Stun: - return DiminishingReturnsType.All; - case DiminishingGroup.LimitOnly: - case DiminishingGroup.None: - return DiminishingReturnsType.None; - default: - return DiminishingReturnsType.Player; - } - } - - public DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group) - { - switch (group) - { - case DiminishingGroup.Taunt: - return DiminishingLevels.TauntImmune; - case DiminishingGroup.AOEKnockback: - return DiminishingLevels.Level2; - default: - return DiminishingLevels.Immune; - } - } - - public int GetDiminishingReturnsLimitDuration(SpellInfo spellproto) - { - // Explicit diminishing duration - switch (spellproto.SpellFamilyName) - { - case SpellFamilyNames.Druid: - { - // Faerie Fire - 20 seconds in PvP (6.0) - if (spellproto.SpellFamilyFlags[0].HasAnyFlag(0x400u)) - return 20 * Time.InMilliseconds; - break; - } - case SpellFamilyNames.Hunter: - { - // Binding Shot - 3 seconds in PvP (6.0) - if (spellproto.Id == 117526) - return 3 * Time.InMilliseconds; - // Wyvern Sting - 6 seconds in PvP (6.0) - if (spellproto.SpellFamilyFlags[1].HasAnyFlag(0x1000u)) - return 6 * Time.InMilliseconds; - break; - } - case SpellFamilyNames.Monk: - { - // Paralysis - 4 seconds in PvP regardless of if they are facing you (6.0) - if (spellproto.SpellFamilyFlags[2].HasAnyFlag(0x800000u)) - return 4 * Time.InMilliseconds; - break; - } - default: - break; - } - - return 8 * Time.InMilliseconds; - } - void UnloadSpellInfoChains() { foreach (var chain in mSpellChains) @@ -3119,6 +2741,21 @@ namespace Game.Entities Log.outInfo(LogFilter.ServerLoading, $"Loaded SpellInfo SpellSpecific and AuraState in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); } + public void LoadSpellInfoDiminishing() + { + uint oldMSTime = Time.GetMSTime(); + + foreach (SpellInfo spellInfo in mSpellInfoMap.Values) + { + if (spellInfo == null) + continue; + + spellInfo._LoadSpellDiminishInfo(); + } + + Log.outInfo(LogFilter.ServerLoading, "Loaded SpellInfo diminishing infos in {0} ms", Time.GetMSTimeDiffToNow(oldMSTime)); + } + public void LoadPetFamilySpellsStore() { Dictionary levelsBySpell = new Dictionary();