From 6421672adc9cc00476b3fb9947ed0f0145cd4ae3 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Fri, 1 Sep 2017 10:40:48 -0400 Subject: [PATCH] cache SpellSpecific and AuraState information instead of computing them each time they're needed --- Game/Entities/Unit/Unit.Spells.cs | 4 +- Game/Entities/Unit/Unit.cs | 2 +- Game/Scripting/SpellScript.cs | 2 +- Game/Server/WorldManager.cs | 3 + Game/Spells/Auras/AuraEffect.cs | 15 +++- Game/Spells/SpellEffects.cs | 60 ---------------- Game/Spells/SpellInfo.cs | 114 ++++++++++++++++++------------ Game/Spells/SpellManager.cs | 17 +++++ 8 files changed, 104 insertions(+), 113 deletions(-) diff --git a/Game/Entities/Unit/Unit.Spells.cs b/Game/Entities/Unit/Unit.Spells.cs index f182bf8c0..d250cbb95 100644 --- a/Game/Entities/Unit/Unit.Spells.cs +++ b/Game/Entities/Unit/Unit.Spells.cs @@ -3922,7 +3922,7 @@ namespace Game.Entities } bool auraStateFound = false; - AuraStateType auraState = aura.GetSpellInfo().GetAuraState(GetMap().GetDifficultyID()); + AuraStateType auraState = aura.GetSpellInfo().GetAuraState(); if (auraState != 0) { bool canBreak = false; @@ -4095,7 +4095,7 @@ namespace Game.Entities return; // Update target aura state flag - AuraStateType aState = aura.GetSpellInfo().GetAuraState(GetMap().GetDifficultyID()); + AuraStateType aState = aura.GetSpellInfo().GetAuraState(); if (aState != 0) ModifyAuraState(aState, true); diff --git a/Game/Entities/Unit/Unit.cs b/Game/Entities/Unit/Unit.cs index 17ff7fb61..46106de9a 100644 --- a/Game/Entities/Unit/Unit.cs +++ b/Game/Entities/Unit/Unit.cs @@ -1881,7 +1881,7 @@ namespace Game.Entities AddInterruptMask((uint)aurSpellInfo.AuraInterruptFlags); } - AuraStateType aState = aura.GetSpellInfo().GetAuraState(GetMap().GetDifficultyID()); + AuraStateType aState = aura.GetSpellInfo().GetAuraState(); if (aState != 0) m_auraStateAuras.Add(aState, aurApp); diff --git a/Game/Scripting/SpellScript.cs b/Game/Scripting/SpellScript.cs index c228eb832..ca1ee4aac 100644 --- a/Game/Scripting/SpellScript.cs +++ b/Game/Scripting/SpellScript.cs @@ -496,7 +496,7 @@ namespace Game.Scripting public Unit GetCaster() { return m_spell.GetCaster(); } public Unit GetOriginalCaster() { return m_spell.GetOriginalCaster(); } public SpellInfo GetSpellInfo() { return m_spell.GetSpellInfo(); } - SpellValue GetSpellValue() { return m_spell.m_spellValue; } + public SpellValue GetSpellValue() { return m_spell.m_spellValue; } public SpellEffectInfo GetEffectInfo(uint effIndex) { diff --git a/Game/Server/WorldManager.cs b/Game/Server/WorldManager.cs index e2c885c1f..c2c567da5 100644 --- a/Game/Server/WorldManager.cs +++ b/Game/Server/WorldManager.cs @@ -371,6 +371,9 @@ namespace Game Log.outInfo(LogFilter.ServerLoading, "Loading SpellInfo custom attributes..."); Global.SpellMgr.LoadSpellInfoCustomAttributes(); + Log.outInfo(LogFilter.ServerLoading, "Loading SpellInfo SpellSpecific and AuraState..."); + Global.SpellMgr.LoadSpellInfoSpellSpecificAndAuraState(); + Log.outInfo(LogFilter.ServerLoading, "Loading PetFamilySpellsStore Data..."); Global.SpellMgr.LoadPetFamilySpellsStore(); diff --git a/Game/Spells/Auras/AuraEffect.cs b/Game/Spells/Auras/AuraEffect.cs index 65f041560..103f36eda 100644 --- a/Game/Spells/Auras/AuraEffect.cs +++ b/Game/Spells/Auras/AuraEffect.cs @@ -666,12 +666,12 @@ namespace Game.Spells case AuraType.MechanicImmunity: case AuraType.ModMechanicResistance: // compare mechanic - if (spellInfo == null || (int)spellInfo.Mechanic != GetMiscValue()) + if (spellInfo == null || !Convert.ToBoolean(spellInfo.GetAllEffectsMechanicMask() & (1 << GetMiscValue()))) result = false; break; case AuraType.ModCastingSpeedNotStack: // skip melee hits and instant cast spells - if (spellInfo == null || spellInfo.CalcCastTime() == 0) + if (!eventInfo.GetProcSpell() || eventInfo.GetProcSpell().GetCastTime() == 0) result = false; break; case AuraType.ModSpellDamageFromCaster: @@ -702,6 +702,17 @@ namespace Game.Spells if (spellInfo == null || !Convert.ToBoolean((int)spellInfo.GetSchoolMask() & GetMiscValue())) result = false; break; + case AuraType.ProcTriggerSpell: + case AuraType.ProcTriggerSpellWithValue: + { + // Don't proc extra attacks while already processing extra attack spell + uint triggerSpellId = GetSpellEffectInfo().TriggerSpell; + SpellInfo triggeredSpellInfo = Global.SpellMgr.GetSpellInfo(triggerSpellId); + if (triggeredSpellInfo != null) + if (aurApp.GetTarget().m_extraAttacks != 0 && triggeredSpellInfo.HasEffect(SpellEffectName.AddExtraAttacks)) + result = false; + break; + } default: break; } diff --git a/Game/Spells/SpellEffects.cs b/Game/Spells/SpellEffects.cs index fe550e658..b7776b0b8 100644 --- a/Game/Spells/SpellEffects.cs +++ b/Game/Spells/SpellEffects.cs @@ -903,14 +903,6 @@ namespace Game.Spells if (unitTarget == null || !unitTarget.IsAlive() || unitTarget.getPowerType() != powerType || damage < 0) return; - // burn x% of target's mana, up to maximum of 2x% of caster's mana (Mana Burn) - if (m_spellInfo.Id == 8129) - { - int maxDamage = MathFunctions.CalculatePct(m_caster.GetMaxPower(powerType), damage * 2); - damage = MathFunctions.CalculatePct(unitTarget.GetMaxPower(powerType), damage); - damage = Math.Min(damage, maxDamage); - } - int newDamage = -(unitTarget.ModifyPower(powerType, -damage)); // NO - Not a typo - EffectPowerBurn uses effect value multiplier - not effect damage multiplier @@ -963,48 +955,6 @@ namespace Game.Spells if (player.HasSkill(SkillType.Engineering)) MathFunctions.AddPct(ref addhealth, 25); } - // Swiftmend - consumes Regrowth or Rejuvenation - else if (m_spellInfo.TargetAuraState == AuraStateType.Swiftmend && unitTarget.HasAuraState(AuraStateType.Swiftmend, m_spellInfo, m_caster)) - { - var RejorRegr = unitTarget.GetAuraEffectsByType(AuraType.PeriodicHeal); - // find most short by duration - AuraEffect targetAura = null; - foreach (var eff in RejorRegr) - { - if (eff.GetSpellInfo().SpellFamilyName == SpellFamilyNames.Druid - && eff.GetSpellInfo().SpellFamilyFlags[0].HasAnyFlag(0x50u)) - { - if (targetAura == null || eff.GetBase().GetDuration() < targetAura.GetBase().GetDuration()) - targetAura = eff; - } - } - - if (targetAura == null) - { - Log.outError(LogFilter.Spells, "Target(GUID: {0}) has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget.GetGUID()); - return; - } - - int tickheal = targetAura.GetAmount(); - Unit auraCaster = targetAura.GetCaster(); - if (auraCaster != null) - tickheal = (int)auraCaster.SpellHealingBonusDone(unitTarget, targetAura.GetSpellInfo(), (uint)tickheal, DamageEffectType.DOT, effectInfo); - //It is said that talent bonus should not be included - - int tickcount = 0; - // Rejuvenation - if (targetAura.GetSpellInfo().SpellFamilyFlags[0].HasAnyFlag(0x10u)) - tickcount = 4; - // Regrowth - else - tickcount = 6; - - addhealth += tickheal * tickcount; - - // Glyph of Swiftmend - if (!caster.HasAura(54824)) - unitTarget.RemoveAura(targetAura.GetId(), targetAura.GetCasterGUID()); - } // Death Pact - return pct of max health to caster else if (m_spellInfo.SpellFamilyName == SpellFamilyNames.Deathknight && m_spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x00080000u)) addhealth = (int)caster.SpellHealingBonusDone(unitTarget, m_spellInfo, (uint)caster.CountPctFromMaxHealth(damage), DamageEffectType.Heal, effectInfo); @@ -1834,10 +1784,6 @@ namespace Game.Spells if (summon == null || !summon.IsTotem()) return; - // Mana Tide Totem - if (m_spellInfo.Id == 16190) - damage = (int)m_caster.CountPctFromMaxHealth(10); - if (damage != 0) // if not spell info, DB values used { summon.SetMaxHealth((uint)damage); @@ -4945,12 +4891,6 @@ namespace Game.Spells return; int creatureEntry = effectInfo.MiscValue; - if (creatureEntry == 0) - { - if (m_spellInfo.Id == 42793) // Burn Body - creatureEntry = 24008; // Fallen Combatant - } - if (creatureEntry != 0) unitTarget.ToPlayer().RewardPlayerAndGroupAtEvent((uint)creatureEntry, unitTarget); } diff --git a/Game/Spells/SpellInfo.cs b/Game/Spells/SpellInfo.cs index f92f24718..ad60d73d0 100644 --- a/Game/Spells/SpellInfo.cs +++ b/Game/Spells/SpellInfo.cs @@ -244,6 +244,9 @@ namespace Game.Spells } ChainEntry = null; ExplicitTargetMask = 0; + + _spellSpecific = SpellSpecificType.Normal; + _auraState = AuraStateType.None; } public bool HasEffect(Difficulty difficulty, SpellEffectName effect) @@ -1272,11 +1275,18 @@ namespace Game.Spells return (SpellCastTargetFlags)ExplicitTargetMask; } - public AuraStateType GetAuraState(Difficulty difficulty) + public AuraStateType GetAuraState() { + return _auraState; + } + + public void _LoadAuraState() + { + _auraState = AuraStateType.None; + // Seals if (GetSpellSpecific() == SpellSpecificType.Seal) - return AuraStateType.Judgement; + _auraState = AuraStateType.Judgement; // Conflagrate aura state on Immolate and Shadowflame if (SpellFamilyName == SpellFamilyNames.Warlock && @@ -1284,58 +1294,64 @@ namespace Game.Spells (SpellFamilyFlags[0].HasAnyFlag(4u) || // Shadowflame SpellFamilyFlags[2].HasAnyFlag(2u))) - return AuraStateType.Conflagrate; + _auraState = AuraStateType.Conflagrate; // Faerie Fire (druid versions) if (SpellFamilyName == SpellFamilyNames.Druid && SpellFamilyFlags[0].HasAnyFlag(0x400u)) - return AuraStateType.FaerieFire; + _auraState = AuraStateType.FaerieFire; // Sting (hunter's pet ability) if (GetCategory() == 1133) - return AuraStateType.FaerieFire; + _auraState = AuraStateType.FaerieFire; // Victorious if (SpellFamilyName == SpellFamilyNames.Warrior && SpellFamilyFlags[1].HasAnyFlag(0x40000u)) - return AuraStateType.WarriorVictoryRush; + _auraState = AuraStateType.WarriorVictoryRush; // Swiftmend state on Regrowth & Rejuvenation if (SpellFamilyName == SpellFamilyNames.Druid && SpellFamilyFlags[0].HasAnyFlag(0x50u)) - return AuraStateType.Swiftmend; + _auraState = AuraStateType.Swiftmend; // Deadly poison aura state if (SpellFamilyName == SpellFamilyNames.Rogue && SpellFamilyFlags[0].HasAnyFlag(0x10000u)) - return AuraStateType.DeadlyPoison; + _auraState = AuraStateType.DeadlyPoison; // Enrage aura state if (Dispel == DispelType.Enrage) - return AuraStateType.Enrage; + _auraState = AuraStateType.Enrage; // Bleeding aura state if (Convert.ToBoolean(GetAllEffectsMechanicMask() & 1 << (int)Mechanics.Bleed)) - return AuraStateType.Bleeding; + _auraState = AuraStateType.Bleeding; if (Convert.ToBoolean(GetSchoolMask() & SpellSchoolMask.Frost)) { - foreach (SpellEffectInfo effect in GetEffectsForDifficulty(difficulty)) - if (effect != null && effect.IsAura() && (effect.ApplyAuraName == AuraType.ModStun - || effect.ApplyAuraName == AuraType.ModRoot)) - return AuraStateType.Frozen; + foreach (var pair in _effects) + foreach (SpellEffectInfo effect in pair.Value) + if (effect != null && (effect.IsAura(AuraType.ModStun) || effect.IsAura(AuraType.ModRoot))) + _auraState = AuraStateType.Frozen; } switch (Id) { case 71465: // Divine Surge case 50241: // Evasive Charges - return AuraStateType.Unk22; + _auraState = AuraStateType.Unk22; + break; default: break; } - - return AuraStateType.None; } public SpellSpecificType GetSpellSpecific() { + return _spellSpecific; + } + + public void _LoadSpellSpecific() + { + _spellSpecific = SpellSpecificType.Normal; + switch (SpellFamilyName) { case SpellFamilyNames.Generic: @@ -1370,11 +1386,11 @@ namespace Game.Spells } if (food && drink) - return SpellSpecificType.FoodAndDrink; + _spellSpecific = SpellSpecificType.FoodAndDrink; else if (food) - return SpellSpecificType.Food; + _spellSpecific = SpellSpecificType.Food; else if (drink) - return SpellSpecificType.Drink; + _spellSpecific = SpellSpecificType.Drink; } // scrolls effects else @@ -1388,10 +1404,12 @@ namespace Game.Spells case 8096: // Intellect case 8115: // Agility case 8091: // Armor - return SpellSpecificType.Scroll; + _spellSpecific = SpellSpecificType.Scroll; + break; case 12880: // Enrage (Enrage) case 57518: // Enrage (Wrecking Crew) - return SpellSpecificType.WarriorEnrage; + _spellSpecific = SpellSpecificType.WarriorEnrage; + break; } } break; @@ -1400,21 +1418,21 @@ namespace Game.Spells { // family flags 18(Molten), 25(Frost/Ice), 28(Mage) if (SpellFamilyFlags[0].HasAnyFlag(0x12040000u)) - return SpellSpecificType.MageArmor; + _spellSpecific = SpellSpecificType.MageArmor; // Arcane brillance and Arcane intelect (normal check fails because of flags difference) if (SpellFamilyFlags[0].HasAnyFlag(0x400u)) - return SpellSpecificType.MageArcaneBrillance; + _spellSpecific = SpellSpecificType.MageArcaneBrillance; SpellEffectInfo effect = GetEffect(Difficulty.None, 0); - if (effect != null && SpellFamilyFlags[0].HasAnyFlag(0x1000000u) && effect.ApplyAuraName == AuraType.ModConfuse) - return SpellSpecificType.MagePolymorph; + if (effect != null && SpellFamilyFlags[0].HasAnyFlag(0x1000000u) && effect.IsAura(AuraType.ModConfuse)) + _spellSpecific = SpellSpecificType.MagePolymorph; break; } case SpellFamilyNames.Warrior: { if (Id == 12292) // Death Wish - return SpellSpecificType.WarriorEnrage; + _spellSpecific = SpellSpecificType.WarriorEnrage; break; } @@ -1422,26 +1440,26 @@ namespace Game.Spells { // Warlock (Bane of Doom | Bane of Agony | Bane of Havoc) if (Id == 603 || Id == 980 || Id == 80240) - return SpellSpecificType.Bane; + _spellSpecific = SpellSpecificType.Bane; // only warlock curses have this if (Dispel == DispelType.Curse) - return SpellSpecificType.Curse; + _spellSpecific = SpellSpecificType.Curse; // Warlock (Demon Armor | Demon Skin | Fel Armor) if (SpellFamilyFlags[1].HasAnyFlag(0x20000020u) || SpellFamilyFlags[2].HasAnyFlag(0x00000010u)) - return SpellSpecificType.WarlockArmor; + _spellSpecific = SpellSpecificType.WarlockArmor; //seed of corruption and corruption if (SpellFamilyFlags[1].HasAnyFlag(0x10u) || SpellFamilyFlags[0].HasAnyFlag(0x2u)) - return SpellSpecificType.WarlockCorruption; + _spellSpecific = SpellSpecificType.WarlockCorruption; break; } case SpellFamilyNames.Priest: { // Divine Spirit and Prayer of Spirit if (SpellFamilyFlags[0].HasAnyFlag(0x20u)) - return SpellSpecificType.PriestDivineSpirit; + _spellSpecific = SpellSpecificType.PriestDivineSpirit; break; } @@ -1449,30 +1467,30 @@ namespace Game.Spells { // only hunter stings have this if (Dispel == DispelType.Poison) - return SpellSpecificType.Sting; + _spellSpecific = SpellSpecificType.Sting; // only hunter aspects have this (but not all aspects in hunter family) - if (SpellFamilyFlags & new FlagArray128(0x00380000, 0x00440000, 0x00001010)) - return SpellSpecificType.Aspect; + if (SpellFamilyFlags & new FlagArray128(0x00200000, 0x00000000, 0x00001010, 0x00000000)) + _spellSpecific = SpellSpecificType.Aspect; break; } case SpellFamilyNames.Paladin: { // Collection of all the seal family flags. No other paladin spell has any of those. - if (SpellFamilyFlags[1].HasAnyFlag(0x26000C00u)) - return SpellSpecificType.Seal; + if (SpellFamilyFlags[1].HasAnyFlag(0xA2000800)) + _spellSpecific = SpellSpecificType.Seal; if (SpellFamilyFlags[0].HasAnyFlag(0x00002190u)) - return SpellSpecificType.Hand; + _spellSpecific = SpellSpecificType.Hand; // Judgement if (Id == 20271) - return SpellSpecificType.Judgement; + _spellSpecific = SpellSpecificType.Judgement; // only paladin auras have this (for palaldin class family) if (SpellFamilyFlags[2].HasAnyFlag(0x00000020u)) - return SpellSpecificType.Aura; + _spellSpecific = SpellSpecificType.Aura; break; } @@ -1480,13 +1498,13 @@ namespace Game.Spells { // family flags 10 (Lightning), 42 (Earth), 37 (Water), proc shield from T2 8 pieces bonus if (SpellFamilyFlags[1].HasAnyFlag(0x420u) || SpellFamilyFlags[0].HasAnyFlag(0x00000400u) || Id == 23552) - return SpellSpecificType.ElementalShield; + _spellSpecific = SpellSpecificType.ElementalShield; break; } case SpellFamilyNames.Deathknight: if (Id == 48266 || Id == 48263 || Id == 48265) - return SpellSpecificType.Presence; + _spellSpecific = SpellSpecificType.Presence; break; } @@ -1502,21 +1520,21 @@ namespace Game.Spells case AuraType.ModPossessPet: case AuraType.ModPossess: case AuraType.AoeCharm: - return SpellSpecificType.Charm; + _spellSpecific = SpellSpecificType.Charm; + break; case AuraType.TrackCreatures: // @workaround For non-stacking tracking spells (We need generic solution) if (Id == 30645) // Gas Cloud Tracking - return SpellSpecificType.Normal; + _spellSpecific = SpellSpecificType.Normal; break; case AuraType.TrackResources: case AuraType.TrackStealthed: - return SpellSpecificType.Tracker; + _spellSpecific = SpellSpecificType.Tracker; + break; } } } } - - return SpellSpecificType.Normal; } public float GetMinRange(bool positive = false) @@ -2650,6 +2668,8 @@ namespace Game.Spells internal Dictionary _effects; MultiMap _visuals = new MultiMap(); bool _hasPowerDifficultyData; + SpellSpecificType _spellSpecific; + AuraStateType _auraState; #endregion public struct ScalingInfo diff --git a/Game/Spells/SpellManager.cs b/Game/Spells/SpellManager.cs index e62489dc4..dfb5d693c 100644 --- a/Game/Spells/SpellManager.cs +++ b/Game/Spells/SpellManager.cs @@ -2790,6 +2790,9 @@ namespace Game.Entities case 42767: // Sic'em spellInfo.GetEffect(0).TargetA = new SpellImplicitTargetInfo(Targets.UnitNearbyEntry); break; + case 42793: // Burn Body + spellInfo.GetEffect(2).MiscValue = 24008; // Fallen Combatant + break; // VIOLET HOLD SPELLS // case 54258: // Water Globule (Ichoron) @@ -3095,6 +3098,20 @@ namespace Game.Entities Log.outInfo(LogFilter.ServerLoading, "Loaded SpellInfo corrections in {0} ms", Time.GetMSTimeDiffToNow(oldMSTime)); } + public void LoadSpellInfoSpellSpecificAndAuraState() + { + uint oldMSTime = Time.GetMSTime(); + + foreach (SpellInfo spellInfo in mSpellInfoMap.Values) + { + // AuraState depends on SpellSpecific + spellInfo._LoadSpellSpecific(); + spellInfo._LoadAuraState(); + } + + Log.outInfo(LogFilter.ServerLoading, $"Loaded SpellInfo SpellSpecific and AuraState in {Time.GetMSTimeDiffToNow(oldMSTime)} ms"); + } + public void LoadPetFamilySpellsStore() { Dictionary levelsBySpell = new Dictionary();