diff options
author | ariel- <ariel-@users.noreply.github.com> | 2016-10-17 01:52:40 -0300 |
---|---|---|
committer | joschiwald <joschiwald.trinity@gmail.com> | 2017-10-03 20:53:49 +0200 |
commit | 2d75d8071bb6d85987bdc5d88ed2271822fcbcfd (patch) | |
tree | 01389c522f87cdff0be720bf66f9d0ca804beb90 | |
parent | 4d5eacd3af8406e41f6f335355b1f860f2323ee1 (diff) |
Core/Globals: compute aura diminishing return info at startup and cache it
Core/Entities: Save diminish return on an array instead of a linked list
(cherry picked from commit 9b0fa51022fba3d5ece96dd0ac8399be01ea5b0f)
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 99 | ||||
-rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 25 | ||||
-rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 27 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 4 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 416 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 489 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 394 | ||||
-rw-r--r-- | src/server/game/Spells/SpellMgr.h | 7 | ||||
-rw-r--r-- | src/server/game/World/World.cpp | 3 |
10 files changed, 767 insertions, 699 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 0afe6e08c37..cd6bf8073da 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -8987,54 +8987,47 @@ void Unit::ModSpellDurationTime(SpellInfo const* spellInfo, int32 & duration, Sp DiminishingLevels Unit::GetDiminishing(DiminishingGroup group) { - for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) - { - if (i->DRGroup != group) - continue; - - if (!i->hitCount) - return DIMINISHING_LEVEL_1; + DiminishingReturn& diminish = m_Diminishing[group]; + if (!diminish.hitCount) + return DIMINISHING_LEVEL_1; - if (!i->hitTime) - return DIMINISHING_LEVEL_1; + if (!diminish.hitTime) + return DIMINISHING_LEVEL_1; - // If last spell was cast more than 18 seconds ago - reset the count. - if (i->stack == 0 && getMSTimeDiff(i->hitTime, getMSTime()) > 18 * IN_MILLISECONDS) - { - i->hitCount = DIMINISHING_LEVEL_1; - return DIMINISHING_LEVEL_1; - } - // or else increase the count. - else - return DiminishingLevels(i->hitCount); + // If last spell was cast more than 18 seconds ago - reset the count. + if (!diminish.stack && GetMSTimeDiffToNow(diminish.hitTime) > 18 * IN_MILLISECONDS) + { + diminish.hitCount = DIMINISHING_LEVEL_1; + return DIMINISHING_LEVEL_1; } - return DIMINISHING_LEVEL_1; + + return DiminishingLevels(diminish.hitCount); } -void Unit::IncrDiminishing(DiminishingGroup group) +void Unit::IncrDiminishing(SpellInfo const* auraSpellInfo, bool triggered) { + DiminishingGroup const group = auraSpellInfo->GetDiminishingReturnsGroupForSpell(triggered); + DiminishingLevels const maxLevel = auraSpellInfo->GetDiminishingReturnsMaxLevel(triggered); + // Checking for existing in the table - for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) - { - if (i->DRGroup != group) - continue; - if (int32(i->hitCount) < GetDiminishingReturnsMaxLevel(group)) - i->hitCount += 1; - return; - } - m_Diminishing.push_back(DiminishingReturn(group, getMSTime(), DIMINISHING_LEVEL_2)); + DiminishingReturn& diminish = m_Diminishing[group]; + if (static_cast<int32>(diminish.hitCount) < maxLevel) + ++diminish.hitCount; } -float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, Unit* caster, DiminishingLevels Level, int32 limitduration) +float Unit::ApplyDiminishingToDuration(SpellInfo const* auraSpellInfo, bool triggered, int32& duration, Unit* caster, DiminishingLevels previousLevel) { + DiminishingGroup const group = auraSpellInfo->GetDiminishingReturnsGroupForSpell(triggered); if (duration == -1 || group == DIMINISHING_NONE) return 1.0f; + int32 const limitDuration = auraSpellInfo->GetDiminishingReturnsLimitDuration(triggered); + // test pet/charm masters instead pets/charmeds Unit const* targetOwner = GetCharmerOrOwner(); Unit const* casterOwner = caster->GetCharmerOrOwner(); - if (limitduration > 0 && duration > limitduration) + if (limitDuration > 0 && duration > limitDuration) { Unit const* target = targetOwner ? targetOwner : this; Unit const* source = casterOwner ? casterOwner : caster; @@ -9042,7 +9035,7 @@ float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, if ((target->GetTypeId() == TYPEID_PLAYER || (target->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH)) && source->GetTypeId() == TYPEID_PLAYER) - duration = limitduration; + duration = limitDuration; } float mod = 1.0f; @@ -9053,7 +9046,7 @@ float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, { if (GetTypeId() == TYPEID_UNIT && (ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_TAUNT_DIMINISH)) { - DiminishingLevels diminish = Level; + DiminishingLevels diminish = previousLevel; switch (diminish) { case DIMINISHING_LEVEL_1: break; @@ -9068,11 +9061,11 @@ float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, } case DIMINISHING_AOE_KNOCKBACK: { - if ((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && (((targetOwner ? targetOwner : this)->ToPlayer()) + if ((auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_PLAYER && (((targetOwner ? targetOwner : this)->ToPlayer()) || (ToCreature() && (ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH)))) - || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL) + || auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_ALL) { - DiminishingLevels diminish = Level; + DiminishingLevels diminish = previousLevel; switch (diminish) { case DIMINISHING_LEVEL_1: break; @@ -9084,11 +9077,11 @@ float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, } default: { - if ((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER && (((targetOwner ? targetOwner : this)->ToPlayer()) + if ((auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_PLAYER && (((targetOwner ? targetOwner : this)->ToPlayer()) || (ToCreature() && (ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH)))) - || GetDiminishingReturnsGroupType(group) == DRTYPE_ALL) + || auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_ALL) { - DiminishingLevels diminish = Level; + DiminishingLevels diminish = previousLevel; switch (diminish) { case DIMINISHING_LEVEL_1: break; @@ -9109,24 +9102,26 @@ float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, void Unit::ApplyDiminishingAura(DiminishingGroup group, bool apply) { // Checking for existing in the table - for (Diminishing::iterator i = m_Diminishing.begin(); i != m_Diminishing.end(); ++i) + DiminishingReturn& diminish = m_Diminishing[group]; + + if (apply) + ++diminish.stack; + else if (diminish.stack) { - if (i->DRGroup != group) - continue; + --diminish.stack; - if (apply) - i->stack += 1; - else if (i->stack) - { - i->stack -= 1; - // Remember time after last aura from group removed - if (i->stack == 0) - i->hitTime = getMSTime(); - } - break; + // Remember time after last aura from group removed + if (!diminish.stack) + diminish.hitTime = getMSTime(); } } +void Unit::ClearDiminishings() +{ + for (uint32 i = 0; i < DIMINISHING_MAX; ++i) + m_Diminishing[i].Clear(); +} + float Unit::GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const { if (!spellInfo->RangeEntry) diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index b1fc3811791..572a6ec4c8c 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -31,6 +31,7 @@ #include "Util.h" #include <boost/container/flat_set.hpp> #include <algorithm> +#include <array> #include <map> #define WORLD_TRIGGER 12999 @@ -539,11 +540,15 @@ enum UnitTypeMask struct DiminishingReturn { - DiminishingReturn(DiminishingGroup group, uint32 t, uint32 count) - : DRGroup(group), stack(0), hitTime(t), hitCount(count) - { } + DiminishingReturn() : stack(0), hitTime(0), hitCount(DIMINISHING_LEVEL_1) { } + + void Clear() + { + stack = 0; + hitTime = 0; + hitCount = DIMINISHING_LEVEL_1; + } - DiminishingGroup DRGroup; uint16 stack; uint32 hitTime; uint32 hitCount; @@ -959,7 +964,7 @@ class TC_GAME_API Unit : public WorldObject typedef std::list<AuraEffect*> AuraEffectList; typedef std::list<Aura*> AuraList; typedef std::list<AuraApplication *> AuraApplicationList; - typedef std::list<DiminishingReturn> Diminishing; + typedef std::array<DiminishingReturn, DIMINISHING_MAX> Diminishing; typedef std::deque<std::pair<uint32 /*procEffectMask*/, AuraApplication*>> AuraApplicationProcContainer; @@ -979,11 +984,11 @@ class TC_GAME_API Unit : public WorldObject void SendCombatLogMessage(WorldPackets::CombatLog::CombatLogServerPacket* combatLog) const; - DiminishingLevels GetDiminishing(DiminishingGroup group); - void IncrDiminishing(DiminishingGroup group); - float ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, Unit* caster, DiminishingLevels Level, int32 limitduration); - void ApplyDiminishingAura(DiminishingGroup group, bool apply); - void ClearDiminishings() { m_Diminishing.clear(); } + DiminishingLevels GetDiminishing(DiminishingGroup group); + void IncrDiminishing(SpellInfo const* auraSpellInfo, bool triggered); + float ApplyDiminishingToDuration(SpellInfo const* auraSpellInfo, bool triggered, int32& duration, Unit* caster, DiminishingLevels previousLevel); + void ApplyDiminishingAura(DiminishingGroup group, bool apply); + void ClearDiminishings(); // target dependent range checks float GetSpellMaxRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const; diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index e887176f5d2..4f239fa6e61 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -4597,6 +4597,8 @@ enum DiminishingGroup : uint16 DIMINISHING_AOE_KNOCKBACK = 6, DIMINISHING_TAUNT = 7, DIMINISHING_LIMITONLY = 8, + + DIMINISHING_MAX }; enum SummonCategory diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index fdb1ade8648..0e5bfa0d653 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -601,8 +601,6 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)) variance = 0.0f; effectHandleMode = SPELL_EFFECT_HANDLE_LAUNCH; effectInfo = nullptr; - m_diminishLevel = DIMINISHING_LEVEL_1; - m_diminishGroup = DIMINISHING_NONE; m_damage = 0; m_healing = 0; m_procAttacker = 0; @@ -2635,16 +2633,19 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA aura_effmask |= 1 << 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 = GetDiminishingReturnsGroupForSpell(m_spellInfo); - if (m_diminishGroup && aura_effmask) + bool const triggered = m_triggeredByAuraSpell != nullptr; + DiminishingGroup const diminishGroup = m_spellInfo->GetDiminishingReturnsGroupForSpell(triggered); + + DiminishingLevels diminishLevel = DIMINISHING_LEVEL_1; + if (diminishGroup && aura_effmask) { - m_diminishLevel = unit->GetDiminishing(m_diminishGroup); - DiminishingReturnsType type = GetDiminishingReturnsGroupType(m_diminishGroup); + 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 == DRTYPE_PLAYER && (unit->GetCharmerOrOwnerPlayerOrPlayerItself() || (unit->GetTypeId() == TYPEID_UNIT && unit->ToCreature()->GetCreatureTemplate()->flags_extra & CREATURE_FLAG_EXTRA_ALL_DIMINISH))) || type == DRTYPE_ALL) - unit->IncrDiminishing(m_diminishGroup); + unit->IncrDiminishing(m_spellInfo, triggered); } if (aura_effmask) @@ -2691,8 +2692,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA // Now Reduce spell duration using data received at spell hit int32 duration = m_spellAura->GetMaxDuration(); - int32 limitduration = m_diminishGroup ? GetDiminishingReturnsLimitDuration(aurSpellInfo) : 0; - float diminishMod = unit->ApplyDiminishingToDuration(m_diminishGroup, duration, m_originalCaster, m_diminishLevel, limitduration); + float diminishMod = unit->ApplyDiminishingToDuration(aurSpellInfo, triggered, duration, m_originalCaster, diminishLevel); // unit is immune to aura if it was diminished to 0 duration if (diminishMod == 0.0f) @@ -2707,7 +2707,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA } else { - ((UnitAura*)m_spellAura)->SetDiminishGroup(m_diminishGroup); + ((UnitAura*)m_spellAura)->SetDiminishGroup(diminishGroup); bool positive = m_spellAura->GetSpellInfo()->IsPositive(); if (AuraApplication* aurApp = m_spellAura->GetApplicationOfTarget(m_originalCaster->GetGUID())) @@ -3537,9 +3537,6 @@ uint64 Spell::handle_delayed(uint64 t_offset) void Spell::_handle_immediate_phase() { m_spellAura = NULL; - // initialize Diminishing Returns Data - m_diminishLevel = DIMINISHING_LEVEL_1; - m_diminishGroup = DIMINISHING_NONE; // handle some immediate features of the spell here HandleThreatSpells(); @@ -4733,7 +4730,7 @@ void Spell::HandleThreatSpells() 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 @@ -4744,7 +4741,7 @@ void Spell::HandleThreatSpells() target->AddThreat(m_caster, threatToAdd, m_spellInfo->GetSchoolMask(), m_spellInfo); } } - TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size())); + TC_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->IsPositive() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size())); } void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode) diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index be318a0d541..297240b0f2f 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -743,10 +743,6 @@ class TC_GAME_API Spell // used in effects handlers 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/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index bb2f497313a..27049feb3b5 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -2467,6 +2467,422 @@ void SpellInfo::_LoadSpellSpecific() }(); } +void SpellInfo::_LoadSpellDiminishInfo() +{ + auto diminishingGroupCompute = [this](bool triggered) -> DiminishingGroup + { + if (IsPositive()) + return DIMINISHING_NONE; + + if (HasAura(DIFFICULTY_NONE, SPELL_AURA_MOD_TAUNT)) + return DIMINISHING_TAUNT; + + switch (Id) + { + case 64803: // Entrapment + case 135373: // Entrapment + return DIMINISHING_ROOT; + case 24394: // Intimidation + return DIMINISHING_STUN; + case 118345: // Pulverize (Primal Earth Elemental) + return DIMINISHING_STUN; + case 118905: // Static Charge (Capacitor Totem) + return DIMINISHING_STUN; + case 108199: // Gorefiend's Grasp + return DIMINISHING_AOE_KNOCKBACK; + default: + break; + } + + // Explicit Diminishing Groups + switch (SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + break; + case SPELLFAMILY_MAGE: + { + // Frostjaw -- 102051 + if (SpellFamilyFlags[2] & 0x40000) + return DIMINISHING_SILENCE; + + // Frost Nova -- 122 + if (SpellFamilyFlags[0] & 0x40) + return DIMINISHING_ROOT; + // Ice Ward -- 111340 + if (SpellFamilyFlags[0] & 0x80000 && SpellFamilyFlags[2] & 0x2000) + return DIMINISHING_ROOT; + // Freeze (Water Elemental) -- 33395 + if (SpellFamilyFlags[2] & 0x200) + return DIMINISHING_ROOT; + + // Deep Freeze -- 44572 + if (SpellFamilyFlags[1] & 0x100000) + return DIMINISHING_STUN; + + // Dragon's Breath -- 31661 + if (SpellFamilyFlags[0] & 0x800000) + return DIMINISHING_INCAPACITATE; + // Polymorph -- 118 + if (SpellFamilyFlags[0] & 0x1000000) + return DIMINISHING_INCAPACITATE; + // Ring of Frost -- 82691 + if (SpellFamilyFlags[2] & 0x40) + return DIMINISHING_INCAPACITATE; + // Ice Nova -- 157997 + if (SpellFamilyFlags[2] & 0x800000) + return DIMINISHING_INCAPACITATE; + break; + } + case SPELLFAMILY_WARRIOR: + { + // Shockwave -- 132168 + if (SpellFamilyFlags[1] & 0x8000) + return DIMINISHING_STUN; + // Storm Bolt -- 132169 + if (SpellFamilyFlags[2] & 0x1000) + return DIMINISHING_STUN; + + // Intimidating Shout -- 5246 + if (SpellFamilyFlags[0] & 0x40000) + return DIMINISHING_DISORIENT; + + // Hamstring -- 1715, 8 seconds in PvP (6.0) + if (SpellFamilyFlags[0] & 0x2) + return DIMINISHING_LIMITONLY; + break; + } + case SPELLFAMILY_WARLOCK: + { + // Mortal Coil -- 6789 + if (SpellFamilyFlags[0] & 0x80000) + return DIMINISHING_INCAPACITATE; + // Banish -- 710 + if (SpellFamilyFlags[1] & 0x8000000) + return DIMINISHING_INCAPACITATE; + + // Fear -- 118699 + if (SpellFamilyFlags[1] & 0x400) + return DIMINISHING_DISORIENT; + // Howl of Terror -- 5484 + if (SpellFamilyFlags[1] & 0x8) + return DIMINISHING_DISORIENT; + + // Shadowfury -- 30283 + if (SpellFamilyFlags[1] & 0x1000) + return DIMINISHING_STUN; + // Summon Infernal -- 22703 + if (SpellFamilyFlags[0] & 0x1000) + return DIMINISHING_STUN; + break; + } + case SPELLFAMILY_WARLOCK_PET: + { + // Fellash -- 115770 + // Whiplash -- 6360 + if (SpellFamilyFlags[0] & 0x8000000) + return DIMINISHING_AOE_KNOCKBACK; + + // Mesmerize (Shivarra pet) -- 115268 + // Seduction (Succubus pet) -- 6358 + if (SpellFamilyFlags[0] & 0x2000000) + return DIMINISHING_DISORIENT; + + // Axe Toss (Felguard pet) -- 89766 + if (SpellFamilyFlags[1] & 0x4) + return DIMINISHING_STUN; + break; + } + case SPELLFAMILY_DRUID: + { + // Maim -- 22570 + if (SpellFamilyFlags[1] & 0x80) + return DIMINISHING_STUN; + // Mighty Bash -- 5211 + if (SpellFamilyFlags[0] & 0x2000) + return DIMINISHING_STUN; + // Rake -- 163505 -- no flags on the stun + if (Id == 163505) + return DIMINISHING_STUN; + + // Incapacitating Roar -- 99, no flags on the stun, 14 + if (SpellFamilyFlags[1] & 0x1) + return DIMINISHING_INCAPACITATE; + + // Cyclone -- 33786 + if (SpellFamilyFlags[1] & 0x20) + return DIMINISHING_DISORIENT; + + // Typhoon -- 61391 + if (SpellFamilyFlags[1] & 0x1000000) + return DIMINISHING_AOE_KNOCKBACK; + // Ursol's Vortex -- 118283, no family flags + if (Id == 118283) + return DIMINISHING_AOE_KNOCKBACK; + + // Entangling Roots -- 339 + if (SpellFamilyFlags[0] & 0x200) + return DIMINISHING_ROOT; + // Mass Entanglement -- 102359 + if (SpellFamilyFlags[2] & 0x4) + return DIMINISHING_ROOT; + + // Faerie Fire -- 770, 20 seconds in PvP (6.0) + if (SpellFamilyFlags[0] & 0x400) + return DIMINISHING_LIMITONLY; + break; + } + case SPELLFAMILY_ROGUE: + { + // Cheap Shot -- 1833 + if (SpellFamilyFlags[0] & 0x400) + return DIMINISHING_STUN; + // Kidney Shot -- 408 + if (SpellFamilyFlags[0] & 0x200000) + return DIMINISHING_STUN; + + // Gouge -- 1776 + if (SpellFamilyFlags[0] & 0x8) + return DIMINISHING_INCAPACITATE; + // Sap -- 6770 + if (SpellFamilyFlags[0] & 0x80) + return DIMINISHING_INCAPACITATE; + + // Blind -- 2094 + if (SpellFamilyFlags[0] & 0x1000000) + return DIMINISHING_DISORIENT; + + // Garrote -- 1330 + if (SpellFamilyFlags[1] & 0x20000000) + return DIMINISHING_SILENCE; + break; + } + case SPELLFAMILY_HUNTER: + { + // Charge (Tenacity pet) -- 53148, no flags + if (Id == 53148) + return DIMINISHING_ROOT; + // Narrow Escape -- 136634, no flags + if (Id == 136634) + return DIMINISHING_ROOT; + + // Binding Shot -- 117526, no flags + if (Id == 117526) + return DIMINISHING_STUN; + + // Freezing Trap -- 3355 + if (SpellFamilyFlags[0] & 0x8) + return DIMINISHING_INCAPACITATE; + // Wyvern Sting -- 19386 + if (SpellFamilyFlags[1] & 0x1000) + return DIMINISHING_INCAPACITATE; + break; + } + case SPELLFAMILY_PALADIN: + { + // Repentance -- 20066 + if (SpellFamilyFlags[0] & 0x4) + return DIMINISHING_INCAPACITATE; + + // Turn Evil -- 10326 + if (SpellFamilyFlags[1] & 0x800000) + return DIMINISHING_DISORIENT; + + // Avenger's Shield -- 31935 + if (SpellFamilyFlags[0] & 0x4000) + return DIMINISHING_SILENCE; + + // Fist of Justice -- 105593 + // Hammer of Justice -- 853 + if (SpellFamilyFlags[0] & 0x800) + return DIMINISHING_STUN; + // Holy Wrath -- 119072 + if (SpellFamilyFlags[1] & 0x200000) + return DIMINISHING_STUN; + break; + } + case SPELLFAMILY_SHAMAN: + { + // Hex -- 51514 + if (SpellFamilyFlags[1] & 0x8000) + return DIMINISHING_INCAPACITATE; + + // Thunderstorm -- 51490 + if (SpellFamilyFlags[1] & 0x2000) + return DIMINISHING_AOE_KNOCKBACK; + + // Earthgrab Totem -- 64695 + if (SpellFamilyFlags[2] & 0x4000) + return DIMINISHING_ROOT; + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Strangulate -- 47476 + if (SpellFamilyFlags[0] & 0x200) + return DIMINISHING_SILENCE; + + // Asphyxiate -- 108194 + if (SpellFamilyFlags[2] & 0x100000) + return DIMINISHING_STUN; + // Gnaw (Ghoul) -- 91800, no flags + if (Id == 91800) + return DIMINISHING_STUN; + // Monstrous Blow (Ghoul w/ Dark Transformation active) -- 91797 + if (Id == 91797) + return DIMINISHING_STUN; + break; + } + case SPELLFAMILY_PRIEST: + { + // Dominate Mind -- 605 + if (SpellFamilyFlags[0] & 0x20000 && GetSpellVisual() == 39068) + return DIMINISHING_INCAPACITATE; + // Holy Word: Chastise -- 88625 + if (SpellFamilyFlags[2] & 0x20) + return DIMINISHING_INCAPACITATE; + // Psychic Horror -- 64044 + if (SpellFamilyFlags[2] & 0x2000) + return DIMINISHING_INCAPACITATE; + + // Psychic Scream -- 8122 + if (SpellFamilyFlags[0] & 0x10000) + return DIMINISHING_DISORIENT; + + // Silence -- 15487 + if (SpellFamilyFlags[1] & 0x200000 && SchoolMask == SPELL_SCHOOL_MASK_SHADOW) + return DIMINISHING_SILENCE; + break; + } + case SPELLFAMILY_MONK: + { + // Disable -- 116706, no flags + if (Id == 116706) + return DIMINISHING_ROOT; + + // Charging Ox Wave -- 119392 + if (SpellFamilyFlags[1] & 0x10000) + return DIMINISHING_STUN; + // Fists of Fury -- 120086 + if (SpellFamilyFlags[1] & 0x800000 && !(SpellFamilyFlags[2] & 0x8)) + return DIMINISHING_STUN; + // Leg Sweep -- 119381 + if (SpellFamilyFlags[1] & 0x200) + return DIMINISHING_STUN; + + // Incendiary Breath (honor talent) -- 202274, no flags + if (Id == 202274) + return DIMINISHING_INCAPACITATE; + // Paralysis -- 115078 + if (SpellFamilyFlags[2] & 0x800000) + return DIMINISHING_INCAPACITATE; + break; + } + default: + break; + } + + return DIMINISHING_NONE; + }; + + auto diminishingTypeCompute = [](DiminishingGroup group) -> DiminishingReturnsType + { + switch (group) + { + case DIMINISHING_TAUNT: + case DIMINISHING_STUN: + return DRTYPE_ALL; + case DIMINISHING_LIMITONLY: + case DIMINISHING_NONE: + return DRTYPE_NONE; + default: + return DRTYPE_PLAYER; + } + }; + + auto diminishingMaxLevelCompute = [](DiminishingGroup group) -> DiminishingLevels + { + switch (group) + { + case DIMINISHING_TAUNT: + return DIMINISHING_LEVEL_TAUNT_IMMUNE; + case DIMINISHING_AOE_KNOCKBACK: + return DIMINISHING_LEVEL_2; + default: + return DIMINISHING_LEVEL_IMMUNE; + } + }; + + auto diminishingLimitDurationCompute = [this](DiminishingGroup group) -> int32 + { + // Explicit diminishing duration + switch (SpellFamilyName) + { + case SPELLFAMILY_DRUID: + { + // Faerie Fire - 20 seconds in PvP (6.0) + if (SpellFamilyFlags[0] & 0x400) + return 20 * IN_MILLISECONDS; + break; + } + case SPELLFAMILY_HUNTER: + { + // Binding Shot - 3 seconds in PvP (6.0) + if (Id == 117526) + return 3 * IN_MILLISECONDS; + // Wyvern Sting - 6 seconds in PvP (6.0) + if (SpellFamilyFlags[1] & 0x1000) + return 6 * IN_MILLISECONDS; + break; + } + case SPELLFAMILY_MONK: + { + // Paralysis - 4 seconds in PvP regardless of if they are facing you (6.0) + if (SpellFamilyFlags[2] & 0x800000) + return 4 * IN_MILLISECONDS; + break; + } + default: + break; + } + + return 8 * IN_MILLISECONDS; + }; + + SpellDiminishInfo triggeredInfo, normalInfo; + triggeredInfo.DiminishGroup = diminishingGroupCompute(true); + triggeredInfo.DiminishReturnType = diminishingTypeCompute(triggeredInfo.DiminishGroup); + triggeredInfo.DiminishMaxLevel = diminishingMaxLevelCompute(triggeredInfo.DiminishGroup); + triggeredInfo.DiminishDurationLimit = diminishingLimitDurationCompute(triggeredInfo.DiminishGroup); + + normalInfo.DiminishGroup = diminishingGroupCompute(false); + normalInfo.DiminishReturnType = diminishingTypeCompute(normalInfo.DiminishGroup); + normalInfo.DiminishMaxLevel = diminishingMaxLevelCompute(normalInfo.DiminishGroup); + normalInfo.DiminishDurationLimit = diminishingLimitDurationCompute(normalInfo.DiminishGroup); + + _diminishInfoTriggered = triggeredInfo; + _diminishInfoNonTriggered = normalInfo; +} + +DiminishingGroup SpellInfo::GetDiminishingReturnsGroupForSpell(bool triggered) const +{ + return triggered ? _diminishInfoTriggered.DiminishGroup : _diminishInfoNonTriggered.DiminishGroup; +} + +DiminishingReturnsType SpellInfo::GetDiminishingReturnsGroupType(bool triggered) const +{ + return triggered ? _diminishInfoTriggered.DiminishReturnType : _diminishInfoNonTriggered.DiminishReturnType; +} + +DiminishingLevels SpellInfo::GetDiminishingReturnsMaxLevel(bool triggered) const +{ + return triggered ? _diminishInfoTriggered.DiminishMaxLevel : _diminishInfoNonTriggered.DiminishMaxLevel; +} + +int32 SpellInfo::GetDiminishingReturnsLimitDuration(bool triggered) const +{ + return triggered ? _diminishInfoTriggered.DiminishDurationLimit : _diminishInfoNonTriggered.DiminishDurationLimit; +} + float SpellInfo::GetMinRange(bool positive) const { if (!RangeEntry) diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index b04fa2403da..638a137fc32 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -28,6 +28,7 @@ class Unit; class Player; class Item; class Spell; +class SpellMgr; class SpellInfo; class WorldObject; class AuraEffect; @@ -320,6 +321,14 @@ typedef std::vector<AuraEffect*> AuraEffectVector; struct SpellInfoLoadHelper; +struct TC_GAME_API SpellDiminishInfo +{ + DiminishingGroup DiminishGroup = DIMINISHING_NONE; + DiminishingReturnsType DiminishReturnType = DRTYPE_NONE; + DiminishingLevels DiminishMaxLevel = DIMINISHING_LEVEL_IMMUNE; + int32 DiminishDurationLimit = 0; +}; + struct SpellPowerCost { Powers Power; @@ -328,239 +337,253 @@ struct SpellPowerCost class TC_GAME_API SpellInfo { -public: - uint32 Id; - uint32 CategoryId; - uint32 Dispel; - uint32 Mechanic; - uint32 Attributes; - uint32 AttributesEx; - uint32 AttributesEx2; - uint32 AttributesEx3; - uint32 AttributesEx4; - uint32 AttributesEx5; - uint32 AttributesEx6; - uint32 AttributesEx7; - uint32 AttributesEx8; - uint32 AttributesEx9; - uint32 AttributesEx10; - uint32 AttributesEx11; - uint32 AttributesEx12; - uint32 AttributesEx13; - uint32 AttributesCu; - uint64 Stances; - uint64 StancesNot; - uint32 Targets; - uint32 TargetCreatureType; - uint32 RequiresSpellFocus; - uint32 FacingCasterFlags; - uint32 CasterAuraState; - uint32 TargetAuraState; - uint32 ExcludeCasterAuraState; - uint32 ExcludeTargetAuraState; - uint32 CasterAuraSpell; - uint32 TargetAuraSpell; - uint32 ExcludeCasterAuraSpell; - uint32 ExcludeTargetAuraSpell; - SpellCastTimesEntry const* CastTimeEntry; - uint32 RecoveryTime; - uint32 CategoryRecoveryTime; - uint32 StartRecoveryCategory; - uint32 StartRecoveryTime; - uint32 InterruptFlags; - uint32 AuraInterruptFlags; - uint32 ChannelInterruptFlags; - uint32 ProcFlags; - uint32 ProcChance; - uint32 ProcCharges; - uint32 ProcCooldown; - float ProcBasePPM; - std::vector<SpellProcsPerMinuteModEntry const*> ProcPPMMods; - uint32 MaxLevel; - uint32 BaseLevel; - uint32 SpellLevel; - SpellDurationEntry const* DurationEntry; - std::vector<SpellPowerEntry const*> PowerCosts; - uint32 RangeIndex; - SpellRangeEntry const* RangeEntry; - float Speed; - uint32 StackAmount; - uint32 Totem[MAX_SPELL_TOTEMS]; - int32 Reagent[MAX_SPELL_REAGENTS]; - uint32 ReagentCount[MAX_SPELL_REAGENTS]; - int32 EquippedItemClass; - int32 EquippedItemSubClassMask; - int32 EquippedItemInventoryTypeMask; - uint32 TotemCategory[MAX_SPELL_TOTEMS]; - uint32 IconFileDataId; - uint32 ActiveIconFileDataId; - LocalizedString const* SpellName; - float ConeAngle; - float Width; - uint32 MaxTargetLevel; - uint32 MaxAffectedTargets; - uint32 SpellFamilyName; - flag128 SpellFamilyFlags; - uint32 DmgClass; - uint32 PreventionType; - int32 RequiredAreasID; - uint32 SchoolMask; - uint32 ChargeCategoryId; - // SpellScalingEntry - struct ScalingInfo - { - int32 Class; - uint32 MinScalingLevel; - uint32 MaxScalingLevel; - uint32 ScalesFromItemLevel; - } Scaling; - - uint32 ExplicitTargetMask; - SpellChainNode const* ChainEntry; - - SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const& effectsMap, SpellVisualMap&& visuals, - std::unordered_map<uint32, SpellEffectScalingEntry const*> const& effectScaling); - ~SpellInfo(); - - uint32 GetCategory() const; - bool HasEffect(uint32 difficulty, SpellEffectName effect) const; - bool HasEffect(SpellEffectName effect) const; - bool HasAura(uint32 difficulty, AuraType aura) const; - bool HasAreaAuraEffect(uint32 difficulty) const; - bool HasAreaAuraEffect() const; - - inline bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); } - inline bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); } - inline bool HasAttribute(SpellAttr2 attribute) const { return !!(AttributesEx2 & attribute); } - inline bool HasAttribute(SpellAttr3 attribute) const { return !!(AttributesEx3 & attribute); } - inline bool HasAttribute(SpellAttr4 attribute) const { return !!(AttributesEx4 & attribute); } - inline bool HasAttribute(SpellAttr5 attribute) const { return !!(AttributesEx5 & attribute); } - inline bool HasAttribute(SpellAttr6 attribute) const { return !!(AttributesEx6 & attribute); } - inline bool HasAttribute(SpellAttr7 attribute) const { return !!(AttributesEx7 & attribute); } - inline bool HasAttribute(SpellAttr8 attribute) const { return !!(AttributesEx8 & attribute); } - inline bool HasAttribute(SpellAttr9 attribute) const { return !!(AttributesEx9 & attribute); } - inline bool HasAttribute(SpellAttr10 attribute) const { return !!(AttributesEx10 & attribute); } - inline bool HasAttribute(SpellAttr11 attribute) const { return !!(AttributesEx11 & attribute); } - inline bool HasAttribute(SpellAttr12 attribute) const { return !!(AttributesEx12 & attribute); } - inline bool HasAttribute(SpellAttr13 attribute) const { return !!(AttributesEx13 & attribute); } - inline bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } - - bool IsExplicitDiscovery() const; - bool IsLootCrafting() const; - bool IsQuestTame() const; - bool IsProfession(uint32 difficulty = DIFFICULTY_NONE) const; - bool IsPrimaryProfession(uint32 difficulty = DIFFICULTY_NONE) const; - bool IsPrimaryProfessionFirstRank(uint32 difficulty = DIFFICULTY_NONE) const; - bool IsAbilityOfSkillType(uint32 skillType) const; - - bool IsAffectingArea(uint32 difficulty) const; - bool IsTargetingArea(uint32 difficulty) const; - bool NeedsExplicitUnitTarget() const; - bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) const; - - bool IsPassive() const; - bool IsAutocastable() const; - bool IsStackableWithRanks() const; - bool IsPassiveStackableWithRanks(uint32 difficulty) const; - bool IsMultiSlotAura() const; - bool IsStackableOnOneSlotWithDifferentCasters() const; - bool IsCooldownStartedOnEvent() const; - bool IsDeathPersistent() const; - bool IsRequiringDeadTarget() const; - bool IsAllowingDeadTarget() const; - bool IsGroupBuff() const; - bool CanBeUsedInCombat() const; - bool IsPositive() const; - bool IsPositiveEffect(uint8 effIndex) const; - bool IsChanneled() const; - bool NeedsComboPoints() const; - bool IsBreakingStealth() const; - bool IsRangedWeaponSpell() const; - bool IsAutoRepeatRangedSpell() const; - bool HasInitialAggro() const; - - bool IsAffectedBySpellMods() const; - bool IsAffectedBySpellMod(SpellModifier const* mod) const; - - bool CanPierceImmuneAura(SpellInfo const* aura) const; - bool CanDispelAura(SpellInfo const* aura) const; - - bool IsSingleTarget() const; - bool IsAuraExclusiveBySpecificWith(SpellInfo const* spellInfo) const; - bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const* spellInfo) const; - - SpellCastResult CheckShapeshift(uint32 form) const; - SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const; - SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const; - SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const; - SpellCastResult CheckVehicle(Unit const* caster) const; - bool CheckTargetCreatureType(Unit const* target) const; - - SpellSchoolMask GetSchoolMask() const; - uint32 GetAllEffectsMechanicMask() const; - uint32 GetEffectMechanicMask(uint32 effIndex) const; - uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; - Mechanics GetEffectMechanic(uint32 effIndex, uint32 difficulty) const; - //bool HasAnyEffectMechanic() const; - uint32 GetDispelMask() const; - static uint32 GetDispelMask(DispelType type); - uint32 GetExplicitTargetMask() const; - - AuraStateType GetAuraState() const; - SpellSpecificType GetSpellSpecific() const; - - float GetMinRange(bool positive = false) const; - float GetMaxRange(bool positive = false, Unit* caster = NULL, Spell* spell = NULL) const; - - int32 CalcDuration(Unit* caster = nullptr) const; - int32 GetDuration() const; - int32 GetMaxDuration() const; - - uint32 GetMaxTicks(uint32 difficulty) const; - - uint32 CalcCastTime(uint8 level = 0, Spell* spell = NULL) const; - uint32 GetRecoveryTime() const; - - std::vector<SpellPowerCost> CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) const; - - float CalcProcPPM(Unit* caster, int32 itemLevel) const; - - bool IsRanked() const; - uint8 GetRank() const; - SpellInfo const* GetFirstRankSpell() const; - SpellInfo const* GetLastRankSpell() const; - SpellInfo const* GetNextRankSpell() const; - SpellInfo const* GetPrevRankSpell() const; - SpellInfo const* GetAuraRankForLevel(uint8 level) const; - bool IsRankOf(SpellInfo const* spellInfo) const; - bool IsDifferentRankOf(SpellInfo const* spellInfo) const; - bool IsHighRankOf(SpellInfo const* spellInfo) const; - - uint32 GetSpellXSpellVisualId(Unit const* caster = nullptr) const; - uint32 GetSpellVisual(Unit const* caster = nullptr) const; - - // loading helpers - void _InitializeExplicitTargetMask(); - bool _IsPositiveEffect(uint32 effIndex, bool deep) const; - bool _IsPositiveSpell() const; - static bool _IsPositiveTarget(uint32 targetA, uint32 targetB); - void _LoadSpellSpecific(); - void _LoadAuraState(); - - // unloading helpers - void _UnloadImplicitTargetConditionLists(); - void _UnloadSpellEffects(); - - SpellEffectInfoVector GetEffectsForDifficulty(uint32 difficulty) const; - SpellEffectInfo const* GetEffect(uint32 difficulty, uint32 index) const; - SpellEffectInfo const* GetEffect(uint32 index) const { return GetEffect(DIFFICULTY_NONE, index); } - -private: - SpellEffectInfoMap _effects; - SpellVisualMap _visuals; - bool _hasPowerDifficultyData; - SpellSpecificType _spellSpecific; - AuraStateType _auraState; + friend class SpellMgr; + + public: + uint32 Id; + uint32 CategoryId; + uint32 Dispel; + uint32 Mechanic; + uint32 Attributes; + uint32 AttributesEx; + uint32 AttributesEx2; + uint32 AttributesEx3; + uint32 AttributesEx4; + uint32 AttributesEx5; + uint32 AttributesEx6; + uint32 AttributesEx7; + uint32 AttributesEx8; + uint32 AttributesEx9; + uint32 AttributesEx10; + uint32 AttributesEx11; + uint32 AttributesEx12; + uint32 AttributesEx13; + uint32 AttributesCu; + uint64 Stances; + uint64 StancesNot; + uint32 Targets; + uint32 TargetCreatureType; + uint32 RequiresSpellFocus; + uint32 FacingCasterFlags; + uint32 CasterAuraState; + uint32 TargetAuraState; + uint32 ExcludeCasterAuraState; + uint32 ExcludeTargetAuraState; + uint32 CasterAuraSpell; + uint32 TargetAuraSpell; + uint32 ExcludeCasterAuraSpell; + uint32 ExcludeTargetAuraSpell; + SpellCastTimesEntry const* CastTimeEntry; + uint32 RecoveryTime; + uint32 CategoryRecoveryTime; + uint32 StartRecoveryCategory; + uint32 StartRecoveryTime; + uint32 InterruptFlags; + uint32 AuraInterruptFlags; + uint32 ChannelInterruptFlags; + uint32 ProcFlags; + uint32 ProcChance; + uint32 ProcCharges; + uint32 ProcCooldown; + float ProcBasePPM; + std::vector<SpellProcsPerMinuteModEntry const*> ProcPPMMods; + uint32 MaxLevel; + uint32 BaseLevel; + uint32 SpellLevel; + SpellDurationEntry const* DurationEntry; + std::vector<SpellPowerEntry const*> PowerCosts; + uint32 RangeIndex; + SpellRangeEntry const* RangeEntry; + float Speed; + uint32 StackAmount; + uint32 Totem[MAX_SPELL_TOTEMS]; + int32 Reagent[MAX_SPELL_REAGENTS]; + uint32 ReagentCount[MAX_SPELL_REAGENTS]; + int32 EquippedItemClass; + int32 EquippedItemSubClassMask; + int32 EquippedItemInventoryTypeMask; + uint32 TotemCategory[MAX_SPELL_TOTEMS]; + uint32 IconFileDataId; + uint32 ActiveIconFileDataId; + LocalizedString const* SpellName; + float ConeAngle; + float Width; + uint32 MaxTargetLevel; + uint32 MaxAffectedTargets; + uint32 SpellFamilyName; + flag128 SpellFamilyFlags; + uint32 DmgClass; + uint32 PreventionType; + int32 RequiredAreasID; + uint32 SchoolMask; + uint32 ChargeCategoryId; + + // SpellScalingEntry + struct ScalingInfo + { + int32 Class; + uint32 MinScalingLevel; + uint32 MaxScalingLevel; + uint32 ScalesFromItemLevel; + } Scaling; + + uint32 ExplicitTargetMask; + SpellChainNode const* ChainEntry; + + SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const& effectsMap, SpellVisualMap&& visuals, + std::unordered_map<uint32, SpellEffectScalingEntry const*> const& effectScaling); + ~SpellInfo(); + + uint32 GetCategory() const; + bool HasEffect(uint32 difficulty, SpellEffectName effect) const; + bool HasEffect(SpellEffectName effect) const; + bool HasAura(uint32 difficulty, AuraType aura) const; + bool HasAreaAuraEffect(uint32 difficulty) const; + bool HasAreaAuraEffect() const; + + inline bool HasAttribute(SpellAttr0 attribute) const { return !!(Attributes & attribute); } + inline bool HasAttribute(SpellAttr1 attribute) const { return !!(AttributesEx & attribute); } + inline bool HasAttribute(SpellAttr2 attribute) const { return !!(AttributesEx2 & attribute); } + inline bool HasAttribute(SpellAttr3 attribute) const { return !!(AttributesEx3 & attribute); } + inline bool HasAttribute(SpellAttr4 attribute) const { return !!(AttributesEx4 & attribute); } + inline bool HasAttribute(SpellAttr5 attribute) const { return !!(AttributesEx5 & attribute); } + inline bool HasAttribute(SpellAttr6 attribute) const { return !!(AttributesEx6 & attribute); } + inline bool HasAttribute(SpellAttr7 attribute) const { return !!(AttributesEx7 & attribute); } + inline bool HasAttribute(SpellAttr8 attribute) const { return !!(AttributesEx8 & attribute); } + inline bool HasAttribute(SpellAttr9 attribute) const { return !!(AttributesEx9 & attribute); } + inline bool HasAttribute(SpellAttr10 attribute) const { return !!(AttributesEx10 & attribute); } + inline bool HasAttribute(SpellAttr11 attribute) const { return !!(AttributesEx11 & attribute); } + inline bool HasAttribute(SpellAttr12 attribute) const { return !!(AttributesEx12 & attribute); } + inline bool HasAttribute(SpellAttr13 attribute) const { return !!(AttributesEx13 & attribute); } + inline bool HasAttribute(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } + + bool IsExplicitDiscovery() const; + bool IsLootCrafting() const; + bool IsQuestTame() const; + bool IsProfession(uint32 difficulty = DIFFICULTY_NONE) const; + bool IsPrimaryProfession(uint32 difficulty = DIFFICULTY_NONE) const; + bool IsPrimaryProfessionFirstRank(uint32 difficulty = DIFFICULTY_NONE) const; + bool IsAbilityOfSkillType(uint32 skillType) const; + + bool IsAffectingArea(uint32 difficulty) const; + bool IsTargetingArea(uint32 difficulty) const; + bool NeedsExplicitUnitTarget() const; + bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) const; + + bool IsPassive() const; + bool IsAutocastable() const; + bool IsStackableWithRanks() const; + bool IsPassiveStackableWithRanks(uint32 difficulty) const; + bool IsMultiSlotAura() const; + bool IsStackableOnOneSlotWithDifferentCasters() const; + bool IsCooldownStartedOnEvent() const; + bool IsDeathPersistent() const; + bool IsRequiringDeadTarget() const; + bool IsAllowingDeadTarget() const; + bool IsGroupBuff() const; + bool CanBeUsedInCombat() const; + bool IsPositive() const; + bool IsPositiveEffect(uint8 effIndex) const; + bool IsChanneled() const; + bool NeedsComboPoints() const; + bool IsBreakingStealth() const; + bool IsRangedWeaponSpell() const; + bool IsAutoRepeatRangedSpell() const; + bool HasInitialAggro() const; + + bool IsAffectedBySpellMods() const; + bool IsAffectedBySpellMod(SpellModifier const* mod) const; + + bool CanPierceImmuneAura(SpellInfo const* aura) const; + bool CanDispelAura(SpellInfo const* aura) const; + + bool IsSingleTarget() const; + bool IsAuraExclusiveBySpecificWith(SpellInfo const* spellInfo) const; + bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const* spellInfo) const; + + SpellCastResult CheckShapeshift(uint32 form) const; + SpellCastResult CheckLocation(uint32 map_id, uint32 zone_id, uint32 area_id, Player const* player = NULL) const; + SpellCastResult CheckTarget(Unit const* caster, WorldObject const* target, bool implicit = true) const; + SpellCastResult CheckExplicitTarget(Unit const* caster, WorldObject const* target, Item const* itemTarget = NULL) const; + SpellCastResult CheckVehicle(Unit const* caster) const; + bool CheckTargetCreatureType(Unit const* target) const; + + SpellSchoolMask GetSchoolMask() const; + uint32 GetAllEffectsMechanicMask() const; + uint32 GetEffectMechanicMask(uint32 effIndex) const; + uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; + Mechanics GetEffectMechanic(uint32 effIndex, uint32 difficulty) const; + //bool HasAnyEffectMechanic() const; + uint32 GetDispelMask() const; + static uint32 GetDispelMask(DispelType type); + uint32 GetExplicitTargetMask() const; + + AuraStateType GetAuraState() const; + SpellSpecificType GetSpellSpecific() const; + + float GetMinRange(bool positive = false) const; + float GetMaxRange(bool positive = false, Unit* caster = NULL, Spell* spell = NULL) const; + + int32 CalcDuration(Unit* caster = nullptr) const; + int32 GetDuration() const; + int32 GetMaxDuration() const; + + uint32 GetMaxTicks(uint32 difficulty) const; + + uint32 CalcCastTime(uint8 level = 0, Spell* spell = NULL) const; + uint32 GetRecoveryTime() const; + + std::vector<SpellPowerCost> CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) const; + + float CalcProcPPM(Unit* caster, int32 itemLevel) const; + + bool IsRanked() const; + uint8 GetRank() const; + SpellInfo const* GetFirstRankSpell() const; + SpellInfo const* GetLastRankSpell() const; + SpellInfo const* GetNextRankSpell() const; + SpellInfo const* GetPrevRankSpell() const; + SpellInfo const* GetAuraRankForLevel(uint8 level) const; + bool IsRankOf(SpellInfo const* spellInfo) const; + bool IsDifferentRankOf(SpellInfo const* spellInfo) const; + bool IsHighRankOf(SpellInfo const* spellInfo) const; + + uint32 GetSpellXSpellVisualId(Unit const* caster = nullptr) const; + uint32 GetSpellVisual(Unit const* caster = nullptr) const; + + SpellEffectInfoVector GetEffectsForDifficulty(uint32 difficulty) const; + SpellEffectInfo const* GetEffect(uint32 difficulty, uint32 index) const; + SpellEffectInfo const* GetEffect(uint32 index) const { return GetEffect(DIFFICULTY_NONE, index); } + + // spell diminishing returns + DiminishingGroup GetDiminishingReturnsGroupForSpell(bool triggered) const; + DiminishingReturnsType GetDiminishingReturnsGroupType(bool triggered) const; + DiminishingLevels GetDiminishingReturnsMaxLevel(bool triggered) const; + int32 GetDiminishingReturnsLimitDuration(bool triggered) const; + + private: + // loading helpers + void _InitializeExplicitTargetMask(); + bool _IsPositiveEffect(uint32 effIndex, bool deep) const; + bool _IsPositiveSpell() const; + static bool _IsPositiveTarget(uint32 targetA, uint32 targetB); + void _LoadSpellSpecific(); + void _LoadAuraState(); + void _LoadSpellDiminishInfo(); + + // unloading helpers + void _UnloadImplicitTargetConditionLists(); + void _UnloadSpellEffects(); + + private: + SpellEffectInfoMap _effects; + SpellVisualMap _visuals; + bool _hasPowerDifficultyData; + SpellSpecificType _spellSpecific; + AuraStateType _auraState; + + SpellDiminishInfo _diminishInfoNonTriggered; + SpellDiminishInfo _diminishInfoTriggered; }; #endif // _SPELLINFO_H diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index f1bf941759e..ae6f9a26850 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -57,385 +57,6 @@ bool IsPartOfSkillLine(uint32 skillId, uint32 spellId) return false; } -DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto) -{ - if (spellproto->IsPositive()) - return DIMINISHING_NONE; - - if (spellproto->HasAura(DIFFICULTY_NONE, SPELL_AURA_MOD_TAUNT)) - return DIMINISHING_TAUNT; - - switch (spellproto->Id) - { - case 64803: // Entrapment - case 135373: // Entrapment - return DIMINISHING_ROOT; - case 24394: // Intimidation - return DIMINISHING_STUN; - case 118345: // Pulverize (Primal Earth Elemental) - return DIMINISHING_STUN; - case 118905: // Static Charge (Capacitor Totem) - return DIMINISHING_STUN; - case 108199: // Gorefiend's Grasp - return DIMINISHING_AOE_KNOCKBACK; - default: - break; - } - - // Explicit Diminishing Groups - switch (spellproto->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - break; - case SPELLFAMILY_MAGE: - { - // Frostjaw -- 102051 - if (spellproto->SpellFamilyFlags[2] & 0x40000) - return DIMINISHING_SILENCE; - - // Frost Nova -- 122 - if (spellproto->SpellFamilyFlags[0] & 0x40) - return DIMINISHING_ROOT; - // Ice Ward -- 111340 - if (spellproto->SpellFamilyFlags[0] & 0x80000 && spellproto->SpellFamilyFlags[2] & 0x2000) - return DIMINISHING_ROOT; - // Freeze (Water Elemental) -- 33395 - if (spellproto->SpellFamilyFlags[2] & 0x200) - return DIMINISHING_ROOT; - - // Deep Freeze -- 44572 - if (spellproto->SpellFamilyFlags[1] & 0x100000) - return DIMINISHING_STUN; - - // Dragon's Breath -- 31661 - if (spellproto->SpellFamilyFlags[0] & 0x800000) - return DIMINISHING_INCAPACITATE; - // Polymorph -- 118 - if (spellproto->SpellFamilyFlags[0] & 0x1000000) - return DIMINISHING_INCAPACITATE; - // Ring of Frost -- 82691 - if (spellproto->SpellFamilyFlags[2] & 0x40) - return DIMINISHING_INCAPACITATE; - // Ice Nova -- 157997 - if (spellproto->SpellFamilyFlags[2] & 0x800000) - return DIMINISHING_INCAPACITATE; - break; - } - case SPELLFAMILY_WARRIOR: - { - // Shockwave -- 132168 - if (spellproto->SpellFamilyFlags[1] & 0x8000) - return DIMINISHING_STUN; - // Storm Bolt -- 132169 - if (spellproto->SpellFamilyFlags[2] & 0x1000) - return DIMINISHING_STUN; - - // Intimidating Shout -- 5246 - if (spellproto->SpellFamilyFlags[0] & 0x40000) - return DIMINISHING_DISORIENT; - - // Hamstring -- 1715, 8 seconds in PvP (6.0) - if (spellproto->SpellFamilyFlags[0] & 0x2) - return DIMINISHING_LIMITONLY; - break; - } - case SPELLFAMILY_WARLOCK: - { - // Mortal Coil -- 6789 - if (spellproto->SpellFamilyFlags[0] & 0x80000) - return DIMINISHING_INCAPACITATE; - // Banish -- 710 - if (spellproto->SpellFamilyFlags[1] & 0x8000000) - return DIMINISHING_INCAPACITATE; - - // Fear -- 118699 - if (spellproto->SpellFamilyFlags[1] & 0x400) - return DIMINISHING_DISORIENT; - // Howl of Terror -- 5484 - if (spellproto->SpellFamilyFlags[1] & 0x8) - return DIMINISHING_DISORIENT; - - // Shadowfury -- 30283 - if (spellproto->SpellFamilyFlags[1] & 0x1000) - return DIMINISHING_STUN; - // Summon Infernal -- 22703 - if (spellproto->SpellFamilyFlags[0] & 0x1000) - return DIMINISHING_STUN; - break; - } - case SPELLFAMILY_WARLOCK_PET: - { - // Fellash -- 115770 - // Whiplash -- 6360 - if (spellproto->SpellFamilyFlags[0] & 0x8000000) - return DIMINISHING_AOE_KNOCKBACK; - - // Mesmerize (Shivarra pet) -- 115268 - // Seduction (Succubus pet) -- 6358 - if (spellproto->SpellFamilyFlags[0] & 0x2000000) - return DIMINISHING_DISORIENT; - - // Axe Toss (Felguard pet) -- 89766 - if (spellproto->SpellFamilyFlags[1] & 0x4) - return DIMINISHING_STUN; - break; - } - case SPELLFAMILY_DRUID: - { - // Maim -- 22570 - if (spellproto->SpellFamilyFlags[1] & 0x80) - return DIMINISHING_STUN; - // Mighty Bash -- 5211 - if (spellproto->SpellFamilyFlags[0] & 0x2000) - return DIMINISHING_STUN; - // Rake -- 163505 -- no flags on the stun - if (spellproto->Id == 163505) - return DIMINISHING_STUN; - - // Incapacitating Roar -- 99, no flags on the stun, 14 - if (spellproto->SpellFamilyFlags[1] & 0x1) - return DIMINISHING_INCAPACITATE; - - // Cyclone -- 33786 - if (spellproto->SpellFamilyFlags[1] & 0x20) - return DIMINISHING_DISORIENT; - - // Typhoon -- 61391 - if (spellproto->SpellFamilyFlags[1] & 0x1000000) - return DIMINISHING_AOE_KNOCKBACK; - // Ursol's Vortex -- 118283, no family flags - if (spellproto->Id == 118283) - return DIMINISHING_AOE_KNOCKBACK; - - // Entangling Roots -- 339 - if (spellproto->SpellFamilyFlags[0] & 0x200) - return DIMINISHING_ROOT; - // Mass Entanglement -- 102359 - if (spellproto->SpellFamilyFlags[2] & 0x4) - return DIMINISHING_ROOT; - - // Faerie Fire -- 770, 20 seconds in PvP (6.0) - if (spellproto->SpellFamilyFlags[0] & 0x400) - return DIMINISHING_LIMITONLY; - break; - } - case SPELLFAMILY_ROGUE: - { - // Cheap Shot -- 1833 - if (spellproto->SpellFamilyFlags[0] & 0x400) - return DIMINISHING_STUN; - // Kidney Shot -- 408 - if (spellproto->SpellFamilyFlags[0] & 0x200000) - return DIMINISHING_STUN; - - // Gouge -- 1776 - if (spellproto->SpellFamilyFlags[0] & 0x8) - return DIMINISHING_INCAPACITATE; - // Sap -- 6770 - if (spellproto->SpellFamilyFlags[0] & 0x80) - return DIMINISHING_INCAPACITATE; - - // Blind -- 2094 - if (spellproto->SpellFamilyFlags[0] & 0x1000000) - return DIMINISHING_DISORIENT; - - // Garrote -- 1330 - if (spellproto->SpellFamilyFlags[1] & 0x20000000) - return DIMINISHING_SILENCE; - break; - } - case SPELLFAMILY_HUNTER: - { - // Charge (Tenacity pet) -- 53148, no flags - if (spellproto->Id == 53148) - return DIMINISHING_ROOT; - // Narrow Escape -- 136634, no flags - if (spellproto->Id == 136634) - return DIMINISHING_ROOT; - - // Binding Shot -- 117526, no flags - if (spellproto->Id == 117526) - return DIMINISHING_STUN; - - // Freezing Trap -- 3355 - if (spellproto->SpellFamilyFlags[0] & 0x8) - return DIMINISHING_INCAPACITATE; - // Wyvern Sting -- 19386 - if (spellproto->SpellFamilyFlags[1] & 0x1000) - return DIMINISHING_INCAPACITATE; - break; - } - case SPELLFAMILY_PALADIN: - { - // Repentance -- 20066 - if (spellproto->SpellFamilyFlags[0] & 0x4) - return DIMINISHING_INCAPACITATE; - - // Turn Evil -- 10326 - if (spellproto->SpellFamilyFlags[1] & 0x800000) - return DIMINISHING_DISORIENT; - - // Avenger's Shield -- 31935 - if (spellproto->SpellFamilyFlags[0] & 0x4000) - return DIMINISHING_SILENCE; - - // Fist of Justice -- 105593 - // Hammer of Justice -- 853 - if (spellproto->SpellFamilyFlags[0] & 0x800) - return DIMINISHING_STUN; - // Holy Wrath -- 119072 - if (spellproto->SpellFamilyFlags[1] & 0x200000) - return DIMINISHING_STUN; - break; - } - case SPELLFAMILY_SHAMAN: - { - // Hex -- 51514 - if (spellproto->SpellFamilyFlags[1] & 0x8000) - return DIMINISHING_INCAPACITATE; - - // Thunderstorm -- 51490 - if (spellproto->SpellFamilyFlags[1] & 0x2000) - return DIMINISHING_AOE_KNOCKBACK; - - // Earthgrab Totem -- 64695 - if (spellproto->SpellFamilyFlags[2] & 0x4000) - return DIMINISHING_ROOT; - break; - } - case SPELLFAMILY_DEATHKNIGHT: - { - // Strangulate -- 47476 - if (spellproto->SpellFamilyFlags[0] & 0x200) - return DIMINISHING_SILENCE; - - // Asphyxiate -- 108194 - if (spellproto->SpellFamilyFlags[2] & 0x100000) - return DIMINISHING_STUN; - // Gnaw (Ghoul) -- 91800, no flags - if (spellproto->Id == 91800) - return DIMINISHING_STUN; - // Monstrous Blow (Ghoul w/ Dark Transformation active) -- 91797 - if (spellproto->Id == 91797) - return DIMINISHING_STUN; - break; - } - case SPELLFAMILY_PRIEST: - { - // Dominate Mind -- 605 - if (spellproto->SpellFamilyFlags[0] & 0x20000 && spellproto->GetSpellVisual() == 39068) - return DIMINISHING_INCAPACITATE; - // Holy Word: Chastise -- 88625 - if (spellproto->SpellFamilyFlags[2] & 0x20) - return DIMINISHING_INCAPACITATE; - // Psychic Horror -- 64044 - if (spellproto->SpellFamilyFlags[2] & 0x2000) - return DIMINISHING_INCAPACITATE; - - // Psychic Scream -- 8122 - if (spellproto->SpellFamilyFlags[0] & 0x10000) - return DIMINISHING_DISORIENT; - - // Silence -- 15487 - if (spellproto->SpellFamilyFlags[1] & 0x200000 && spellproto->SchoolMask == 32) - return DIMINISHING_SILENCE; - break; - } - case SPELLFAMILY_MONK: - { - // Disable -- 116706, no flags - if (spellproto->Id == 116706) - return DIMINISHING_ROOT; - - // Charging Ox Wave -- 119392 - if (spellproto->SpellFamilyFlags[1] & 0x10000) - return DIMINISHING_STUN; - // Fists of Fury -- 120086 - if (spellproto->SpellFamilyFlags[1] & 0x800000 && !(spellproto->SpellFamilyFlags[2] & 0x8)) - return DIMINISHING_STUN; - // Leg Sweep -- 119381 - if (spellproto->SpellFamilyFlags[1] & 0x200) - return DIMINISHING_STUN; - - // Incendiary Breath (honor talent) -- 202274, no flags - if (spellproto->Id == 202274) - return DIMINISHING_INCAPACITATE; - // Paralysis -- 115078 - if (spellproto->SpellFamilyFlags[2] & 0x800000) - return DIMINISHING_INCAPACITATE; - break; - } - default: - break; - } - - return DIMINISHING_NONE; -} - -DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group) -{ - switch (group) - { - case DIMINISHING_TAUNT: - case DIMINISHING_STUN: - return DRTYPE_ALL; - case DIMINISHING_LIMITONLY: - case DIMINISHING_NONE: - return DRTYPE_NONE; - default: - return DRTYPE_PLAYER; - } -} - -DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group) -{ - switch (group) - { - case DIMINISHING_TAUNT: - return DIMINISHING_LEVEL_TAUNT_IMMUNE; - case DIMINISHING_AOE_KNOCKBACK: - return DIMINISHING_LEVEL_2; - default: - return DIMINISHING_LEVEL_IMMUNE; - } -} - -int32 GetDiminishingReturnsLimitDuration(SpellInfo const* spellproto) -{ - // Explicit diminishing duration - switch (spellproto->SpellFamilyName) - { - case SPELLFAMILY_DRUID: - { - // Faerie Fire - 20 seconds in PvP (6.0) - if (spellproto->SpellFamilyFlags[0] & 0x400) - return 20 * IN_MILLISECONDS; - break; - } - case SPELLFAMILY_HUNTER: - { - // Binding Shot - 3 seconds in PvP (6.0) - if (spellproto->Id == 117526) - return 3 * IN_MILLISECONDS; - // Wyvern Sting - 6 seconds in PvP (6.0) - if (spellproto->SpellFamilyFlags[1] & 0x1000) - return 6 * IN_MILLISECONDS; - break; - } - case SPELLFAMILY_MONK: - { - // Paralysis - 4 seconds in PvP regardless of if they are facing you (6.0) - if (spellproto->SpellFamilyFlags[2] & 0x800000) - return 4 * IN_MILLISECONDS; - break; - } - default: - break; - } - - return 8 * IN_MILLISECONDS; -} - SpellMgr::SpellMgr() { } SpellMgr::~SpellMgr() @@ -3779,6 +3400,21 @@ void SpellMgr::LoadSpellInfoSpellSpecificAndAuraState() TC_LOG_INFO("server.loading", ">> Loaded SpellInfo SpellSpecific and AuraState in %u ms", GetMSTimeDiffToNow(oldMSTime)); } +void SpellMgr::LoadSpellInfoDiminishing() +{ + uint32 oldMSTime = getMSTime(); + + for (SpellInfo* spellInfo : mSpellInfoMap) + { + if (!spellInfo) + continue; + + spellInfo->_LoadSpellDiminishInfo(); + } + + TC_LOG_INFO("server.loading", ">> Loaded SpellInfo diminishing infos in %u ms", GetMSTimeDiffToNow(oldMSTime)); +} + void SpellMgr::LoadPetFamilySpellsStore() { std::unordered_map<uint32, SpellLevelsEntry const*> levelsBySpell; diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 02c7d0bbd0f..c59c3495a9b 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -564,12 +564,6 @@ inline bool IsProfessionOrRidingSkill(uint32 skill) bool IsPartOfSkillLine(uint32 skillId, uint32 spellId); -// spell diminishing returns -TC_GAME_API DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto); -TC_GAME_API DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); -TC_GAME_API DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group); -TC_GAME_API int32 GetDiminishingReturnsLimitDuration(SpellInfo const* spellproto); - TC_GAME_API extern PetFamilySpellsStore sPetFamilySpellsStore; struct SpellInfoLoadHelper @@ -716,6 +710,7 @@ class TC_GAME_API SpellMgr void LoadSpellInfoCustomAttributes(); void LoadSpellInfoCorrections(); void LoadSpellInfoSpellSpecificAndAuraState(); + void LoadSpellInfoDiminishing(); private: SpellDifficultySearcherMap mSpellDifficultySearcherMap; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 8014ee90347..4d549d47fe5 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1606,6 +1606,9 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading SpellInfo SpellSpecific and AuraState..."); sSpellMgr->LoadSpellInfoSpellSpecificAndAuraState(); + TC_LOG_INFO("server.loading", "Loading SpellInfo diminishing infos..."); + sSpellMgr->LoadSpellInfoDiminishing(); + TC_LOG_INFO("server.loading", "Loading PetFamilySpellsStore Data..."); sSpellMgr->LoadPetFamilySpellsStore(); |