diff options
| author | ariel- <ariel-@users.noreply.github.com> | 2016-10-17 01:52:40 -0300 |
|---|---|---|
| committer | ariel- <ariel-@users.noreply.github.com> | 2016-10-17 01:52:40 -0300 |
| commit | 9b0fa51022fba3d5ece96dd0ac8399be01ea5b0f (patch) | |
| tree | aec7c19fea709094e28d287154dff6ae6168b6ef | |
| parent | f4a10571f74450daf26a5b0c5bd0f3114c231120 (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
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 99 | ||||
| -rw-r--r-- | src/server/game/Entities/Unit/Unit.h | 24 | ||||
| -rw-r--r-- | src/server/game/Miscellaneous/SharedDefines.h | 4 | ||||
| -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 | 333 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellInfo.h | 419 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.cpp | 311 | ||||
| -rw-r--r-- | src/server/game/Spells/SpellMgr.h | 8 | ||||
| -rw-r--r-- | src/server/game/World/World.cpp | 3 |
10 files changed, 648 insertions, 584 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 95f16a88c80..370600861ef 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9756,63 +9756,56 @@ 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 15 seconds ago - reset the count. - if (i->stack == 0 && getMSTimeDiff(i->hitTime, getMSTime()) > 15000) - { - 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 15 seconds ago - reset the count. + if (!diminish.stack && GetMSTimeDiffToNow(diminish.hitTime) > 15000) + { + 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* targetOwner = GetCharmerOrOwner(); Unit const* casterOwner = caster->GetCharmerOrOwner(); // Duration of crowd control abilities on pvp target is limited by 10 sec. (2.2.0) - if (limitduration > 0 && duration > limitduration) + if (limitDuration > 0 && duration > limitDuration) { - Unit const* target = tarGetOwner ? tarGetOwner : this; + Unit const* target = targetOwner ? targetOwner : this; Unit const* source = casterOwner ? casterOwner : caster; 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; @@ -9821,7 +9814,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; @@ -9834,12 +9827,12 @@ float Unit::ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, } } // Some diminishings applies to mobs too (for example, Stun) - else if ((GetDiminishingReturnsGroupType(group) == DRTYPE_PLAYER - && ((tarGetOwner ? (tarGetOwner->GetTypeId() == TYPEID_PLAYER) : (GetTypeId() == TYPEID_PLAYER)) + else if ((auraSpellInfo->GetDiminishingReturnsGroupType(triggered) == DRTYPE_PLAYER + && ((targetOwner ? (targetOwner->GetTypeId() == TYPEID_PLAYER) : (GetTypeId() == TYPEID_PLAYER)) || (GetTypeId() == TYPEID_UNIT && 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; @@ -9857,24 +9850,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 06aa2db8e0b..92c9554800a 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -802,11 +802,15 @@ namespace Movement{ 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; @@ -1256,7 +1260,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<uint8 /*procEffectMask*/, AuraApplication*>> AuraApplicationProcContainer; @@ -1273,11 +1277,11 @@ class TC_GAME_API Unit : public WorldObject void CleanupBeforeRemoveFromMap(bool finalCleanup); void CleanupsBeforeDelete(bool finalCleanup = true) override; // used in ~Creature/~Player (or before mass creature delete to remove cross-references to already deleted units) - 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 f7c440ce8bc..ce0c749c294 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -3136,7 +3136,9 @@ enum DiminishingGroup : uint16 DIMINISHING_SLEEP = 17, DIMINISHING_TAUNT = 18, DIMINISHING_LIMITONLY = 19, - DIMINISHING_DRAGONS_BREATH = 20 + DIMINISHING_DRAGONS_BREATH = 20, + + DIMINISHING_MAX }; enum SummonCategory diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 22456c90d7f..3e7783cfc62 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -586,8 +586,6 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO destTarget = NULL; damage = 0; effectHandleMode = SPELL_EFFECT_HANDLE_LAUNCH; - m_diminishLevel = DIMINISHING_LEVEL_1; - m_diminishGroup = DIMINISHING_NONE; m_damage = 0; m_healing = 0; m_procAttacker = 0; @@ -2588,16 +2586,19 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA aura_effmask |= 1 << i; // 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, m_triggeredByAuraSpell != nullptr); - 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) @@ -2640,8 +2641,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 = GetDiminishingReturnsLimitDuration(m_diminishGroup, aurSpellInfo); - 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) @@ -2656,7 +2656,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())) @@ -3457,9 +3457,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(); @@ -4692,7 +4689,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 @@ -4703,7 +4700,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 5823ea72dbd..5087ececa09 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -561,10 +561,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 ff5cd925c8c..8589a8bc98e 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -2108,6 +2108,339 @@ void SpellInfo::_LoadSpellSpecific() }(); } +void SpellInfo::_LoadSpellDiminishInfo() +{ + auto diminishingGroupCompute = [this](bool triggered) -> DiminishingGroup + { + if (IsPositive()) + return DIMINISHING_NONE; + + for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) + { + if (Effects[i].ApplyAuraName == SPELL_AURA_MOD_TAUNT) + return DIMINISHING_TAUNT; + } + + // Explicit Diminishing Groups + switch (SpellFamilyName) + { + case SPELLFAMILY_GENERIC: + { + // Pet charge effects (Infernal Awakening, Demon Charge) + if (SpellVisual[0] == 2816 && SpellIconID == 15) + return DIMINISHING_CONTROLLED_STUN; + // Frost Tomb + else if (Id == 48400) + return DIMINISHING_NONE; + // Gnaw + else if (Id == 47481) + return DIMINISHING_CONTROLLED_STUN; + // ToC Icehowl Arctic Breath + else if (SpellVisual[0] == 14153) + return DIMINISHING_NONE; + // Black Plague + else if (Id == 64155) + return DIMINISHING_NONE; + // Screams of the Dead (King Ymiron) + else if (Id == 51750) + return DIMINISHING_NONE; + break; + } + // Event spells + case SPELLFAMILY_UNK1: + return DIMINISHING_NONE; + case SPELLFAMILY_MAGE: + { + // Frostbite + if (SpellFamilyFlags[1] & 0x80000000) + return DIMINISHING_ROOT; + // Shattered Barrier + else if (SpellVisual[0] == 12297) + return DIMINISHING_ROOT; + // Deep Freeze + else if (SpellIconID == 2939 && SpellVisual[0] == 9963) + return DIMINISHING_CONTROLLED_STUN; + // Frost Nova / Freeze (Water Elemental) + else if (SpellIconID == 193) + return DIMINISHING_CONTROLLED_ROOT; + // Dragon's Breath + else if (SpellFamilyFlags[0] & 0x800000) + return DIMINISHING_DRAGONS_BREATH; + break; + } + case SPELLFAMILY_WARRIOR: + { + // Hamstring - limit duration to 10s in PvP + if (SpellFamilyFlags[0] & 0x2) + return DIMINISHING_LIMITONLY; + // Charge Stun (own diminishing) + else if (SpellFamilyFlags[0] & 0x01000000) + return DIMINISHING_CHARGE; + break; + } + case SPELLFAMILY_WARLOCK: + { + // Curses/etc + if ((SpellFamilyFlags[0] & 0x80000000) || (SpellFamilyFlags[1] & 0x200)) + return DIMINISHING_LIMITONLY; + // Seduction + else if (SpellFamilyFlags[1] & 0x10000000) + return DIMINISHING_FEAR; + break; + } + case SPELLFAMILY_DRUID: + { + // Pounce + if (SpellFamilyFlags[0] & 0x20000) + return DIMINISHING_OPENING_STUN; + // Cyclone + else if (SpellFamilyFlags[1] & 0x20) + return DIMINISHING_CYCLONE; + // Entangling Roots + // Nature's Grasp + else if (SpellFamilyFlags[0] & 0x00000200) + return DIMINISHING_CONTROLLED_ROOT; + // Faerie Fire + else if (SpellFamilyFlags[0] & 0x400) + return DIMINISHING_LIMITONLY; + break; + } + case SPELLFAMILY_ROGUE: + { + // Gouge + if (SpellFamilyFlags[0] & 0x8) + return DIMINISHING_DISORIENT; + // Blind + else if (SpellFamilyFlags[0] & 0x1000000) + return DIMINISHING_FEAR; + // Cheap Shot + else if (SpellFamilyFlags[0] & 0x400) + return DIMINISHING_OPENING_STUN; + // Crippling poison - Limit to 10 seconds in PvP (No SpellFamilyFlags) + else if (SpellIconID == 163) + return DIMINISHING_LIMITONLY; + break; + } + case SPELLFAMILY_HUNTER: + { + // Hunter's Mark + if ((SpellFamilyFlags[0] & 0x400) && SpellIconID == 538) + return DIMINISHING_LIMITONLY; + // Scatter Shot (own diminishing) + else if ((SpellFamilyFlags[0] & 0x40000) && SpellIconID == 132) + return DIMINISHING_SCATTER_SHOT; + // Entrapment (own diminishing) + else if (SpellVisual[0] == 7484 && SpellIconID == 20) + return DIMINISHING_ENTRAPMENT; + // Wyvern Sting mechanic is MECHANIC_SLEEP but the diminishing is DIMINISHING_DISORIENT + else if ((SpellFamilyFlags[1] & 0x1000) && SpellIconID == 1721) + return DIMINISHING_DISORIENT; + // Freezing Arrow + else if (SpellFamilyFlags[0] & 0x8) + return DIMINISHING_DISORIENT; + break; + } + case SPELLFAMILY_PALADIN: + { + // Judgement of Justice - limit duration to 10s in PvP + if (SpellFamilyFlags[0] & 0x100000) + return DIMINISHING_LIMITONLY; + // Turn Evil + else if ((SpellFamilyFlags[1] & 0x804000) && SpellIconID == 309) + return DIMINISHING_FEAR; + break; + } + case SPELLFAMILY_SHAMAN: + { + // Storm, Earth and Fire - Earthgrab + if (SpellFamilyFlags[2] & 0x4000) + return DIMINISHING_NONE; + break; + } + case SPELLFAMILY_DEATHKNIGHT: + { + // Hungering Cold (no flags) + if (SpellIconID == 2797) + return DIMINISHING_DISORIENT; + // Mark of Blood + else if ((SpellFamilyFlags[0] & 0x10000000) && SpellIconID == 2285) + return DIMINISHING_LIMITONLY; + break; + } + default: + break; + } + + // Lastly - Set diminishing depending on mechanic + uint32 mechanic = GetAllEffectsMechanicMask(); + if (mechanic & (1 << MECHANIC_CHARM)) + return DIMINISHING_MIND_CONTROL; + if (mechanic & (1 << MECHANIC_SILENCE)) + return DIMINISHING_SILENCE; + if (mechanic & (1 << MECHANIC_SLEEP)) + return DIMINISHING_SLEEP; + if (mechanic & ((1 << MECHANIC_SAPPED) | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_SHACKLE))) + return DIMINISHING_DISORIENT; + // Mechanic Knockout, except Blast Wave + if (mechanic & (1 << MECHANIC_KNOCKOUT) && SpellIconID != 292) + return DIMINISHING_DISORIENT; + if (mechanic & (1 << MECHANIC_DISARM)) + return DIMINISHING_DISARM; + if (mechanic & (1 << MECHANIC_FEAR)) + return DIMINISHING_FEAR; + if (mechanic & (1 << MECHANIC_STUN)) + return triggered ? DIMINISHING_STUN : DIMINISHING_CONTROLLED_STUN; + if (mechanic & (1 << MECHANIC_BANISH)) + return DIMINISHING_BANISH; + if (mechanic & (1 << MECHANIC_ROOT)) + return triggered ? DIMINISHING_ROOT : DIMINISHING_CONTROLLED_ROOT; + if (mechanic & (1 << MECHANIC_HORROR)) + return DIMINISHING_HORROR; + + return DIMINISHING_NONE; + }; + + auto diminishingTypeCompute = [](DiminishingGroup group) -> DiminishingReturnsType + { + switch (group) + { + case DIMINISHING_TAUNT: + case DIMINISHING_CONTROLLED_STUN: + case DIMINISHING_STUN: + case DIMINISHING_OPENING_STUN: + case DIMINISHING_CYCLONE: + case DIMINISHING_CHARGE: + 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; + default: + return DIMINISHING_LEVEL_IMMUNE; + } + }; + + auto diminishingLimitDurationCompute = [this](DiminishingGroup group) -> int32 + { + auto isGroupDurationLimited = [group]() -> bool + { + switch (group) + { + case DIMINISHING_BANISH: + case DIMINISHING_CONTROLLED_STUN: + case DIMINISHING_CONTROLLED_ROOT: + case DIMINISHING_CYCLONE: + case DIMINISHING_DISORIENT: + case DIMINISHING_ENTRAPMENT: + case DIMINISHING_FEAR: + case DIMINISHING_HORROR: + case DIMINISHING_MIND_CONTROL: + case DIMINISHING_OPENING_STUN: + case DIMINISHING_ROOT: + case DIMINISHING_STUN: + case DIMINISHING_SLEEP: + case DIMINISHING_LIMITONLY: + return true; + default: + return false; + } + }; + + if (!isGroupDurationLimited()) + return 0; + + // Explicit diminishing duration + switch (SpellFamilyName) + { + case SPELLFAMILY_DRUID: + { + // Faerie Fire - limit to 40 seconds in PvP (3.1) + if (SpellFamilyFlags[0] & 0x400) + return 40 * IN_MILLISECONDS; + break; + } + case SPELLFAMILY_HUNTER: + { + // Wyvern Sting + if (SpellFamilyFlags[1] & 0x1000) + return 6 * IN_MILLISECONDS; + // Hunter's Mark + if (SpellFamilyFlags[0] & 0x400) + return 120 * IN_MILLISECONDS; + break; + } + case SPELLFAMILY_PALADIN: + { + // Repentance - limit to 6 seconds in PvP + if (SpellFamilyFlags[0] & 0x4) + return 6 * IN_MILLISECONDS; + break; + } + case SPELLFAMILY_WARLOCK: + { + // Banish - limit to 6 seconds in PvP + if (SpellFamilyFlags[1] & 0x8000000) + return 6 * IN_MILLISECONDS; + // Curse of Tongues - limit to 12 seconds in PvP + else if (SpellFamilyFlags[2] & 0x800) + return 12 * IN_MILLISECONDS; + // Curse of Elements - limit to 120 seconds in PvP + else if (SpellFamilyFlags[1] & 0x200) + return 120 * IN_MILLISECONDS; + break; + } + default: + break; + } + + return 10 * 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 2f94555e493..b2566ecf533 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; struct SpellChainNode; struct SpellTargetPosition; @@ -291,207 +292,227 @@ private: static StaticData _data[TOTAL_SPELL_EFFECTS]; }; -class TC_GAME_API SpellInfo +struct TC_GAME_API SpellDiminishInfo { -public: - uint32 Id; - SpellCategoryEntry const* CategoryEntry; - uint32 Dispel; - uint32 Mechanic; - uint32 Attributes; - uint32 AttributesEx; - uint32 AttributesEx2; - uint32 AttributesEx3; - uint32 AttributesEx4; - uint32 AttributesEx5; - uint32 AttributesEx6; - uint32 AttributesEx7; - uint32 AttributesCu; - uint64 Stances; - uint64 StancesNot; - uint32 Targets; - uint32 TargetCreatureType; - uint32 RequiresSpellFocus; - uint32 FacingCasterFlags; - uint32 CasterAuraState; - uint32 TargetAuraState; - uint32 CasterAuraStateNot; - uint32 TargetAuraStateNot; - 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 MaxLevel; - uint32 BaseLevel; - uint32 SpellLevel; - SpellDurationEntry const* DurationEntry; - uint32 PowerType; - uint32 ManaCost; - uint32 ManaCostPerlevel; - uint32 ManaPerSecond; - uint32 ManaPerSecondPerLevel; - uint32 ManaCostPercentage; - uint32 RuneCostID; - SpellRangeEntry const* RangeEntry; - float Speed; - uint32 StackAmount; - uint32 Totem[2]; - int32 Reagent[MAX_SPELL_REAGENTS]; - uint32 ReagentCount[MAX_SPELL_REAGENTS]; - int32 EquippedItemClass; - int32 EquippedItemSubClassMask; - int32 EquippedItemInventoryTypeMask; - uint32 TotemCategory[2]; - uint32 SpellVisual[2]; - uint32 SpellIconID; - uint32 ActiveIconID; - char* SpellName[16]; - char* Rank[16]; - uint32 MaxTargetLevel; - uint32 MaxAffectedTargets; - uint32 SpellFamilyName; - flag96 SpellFamilyFlags; - uint32 DmgClass; - uint32 PreventionType; - int32 AreaGroupId; - uint32 SchoolMask; - SpellEffectInfo Effects[MAX_SPELL_EFFECTS]; - uint32 ExplicitTargetMask; - SpellChainNode const* ChainEntry; - - SpellInfo(SpellEntry const* spellEntry); - ~SpellInfo(); - - uint32 GetCategory() const; - bool HasEffect(SpellEffects effect) const; - bool HasAura(AuraType aura) 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(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } - - bool IsExplicitDiscovery() const; - bool IsLootCrafting() const; - bool IsQuestTame() const; - bool IsProfessionOrRiding() const; - bool IsProfession() const; - bool IsPrimaryProfession() const; - bool IsPrimaryProfessionFirstRank() const; - bool IsAbilityLearnedWithProfession() const; - bool IsAbilityOfSkillType(uint32 skillType) const; - - bool IsAffectingArea() const; - bool IsTargetingArea() const; - bool NeedsExplicitUnitTarget() const; - bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const; - - bool IsPassive() const; - bool IsAutocastable() const; - bool IsStackableWithRanks() const; - bool IsPassiveStackableWithRanks() 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(uint8 effIndex) const; - uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; - Mechanics GetEffectMechanic(uint8 effIndex) 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 GetDuration() const; - int32 GetMaxDuration() const; - - uint32 GetMaxTicks() const; - - uint32 CalcCastTime(Spell* spell = NULL) const; - uint32 GetRecoveryTime() const; - - int32 CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) 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; - - // loading helpers - void _InitializeExplicitTargetMask(); - bool _IsPositiveEffect(uint8 effIndex, bool deep) const; - bool _IsPositiveSpell() const; - static bool _IsPositiveTarget(uint32 targetA, uint32 targetB); - void _LoadSpellSpecific(); - void _LoadAuraState(); - - // unloading helpers - void _UnloadImplicitTargetConditionLists(); + DiminishingGroup DiminishGroup = DIMINISHING_NONE; + DiminishingReturnsType DiminishReturnType = DRTYPE_NONE; + DiminishingLevels DiminishMaxLevel = DIMINISHING_LEVEL_IMMUNE; + int32 DiminishDurationLimit = 0; +}; -private: - SpellSpecificType _spellSpecific; - AuraStateType _auraState; +class TC_GAME_API SpellInfo +{ + friend class SpellMgr; + + public: + uint32 Id; + SpellCategoryEntry const* CategoryEntry; + uint32 Dispel; + uint32 Mechanic; + uint32 Attributes; + uint32 AttributesEx; + uint32 AttributesEx2; + uint32 AttributesEx3; + uint32 AttributesEx4; + uint32 AttributesEx5; + uint32 AttributesEx6; + uint32 AttributesEx7; + uint32 AttributesCu; + uint64 Stances; + uint64 StancesNot; + uint32 Targets; + uint32 TargetCreatureType; + uint32 RequiresSpellFocus; + uint32 FacingCasterFlags; + uint32 CasterAuraState; + uint32 TargetAuraState; + uint32 CasterAuraStateNot; + uint32 TargetAuraStateNot; + 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 MaxLevel; + uint32 BaseLevel; + uint32 SpellLevel; + SpellDurationEntry const* DurationEntry; + uint32 PowerType; + uint32 ManaCost; + uint32 ManaCostPerlevel; + uint32 ManaPerSecond; + uint32 ManaPerSecondPerLevel; + uint32 ManaCostPercentage; + uint32 RuneCostID; + SpellRangeEntry const* RangeEntry; + float Speed; + uint32 StackAmount; + uint32 Totem[2]; + int32 Reagent[MAX_SPELL_REAGENTS]; + uint32 ReagentCount[MAX_SPELL_REAGENTS]; + int32 EquippedItemClass; + int32 EquippedItemSubClassMask; + int32 EquippedItemInventoryTypeMask; + uint32 TotemCategory[2]; + uint32 SpellVisual[2]; + uint32 SpellIconID; + uint32 ActiveIconID; + char* SpellName[16]; + char* Rank[16]; + uint32 MaxTargetLevel; + uint32 MaxAffectedTargets; + uint32 SpellFamilyName; + flag96 SpellFamilyFlags; + uint32 DmgClass; + uint32 PreventionType; + int32 AreaGroupId; + uint32 SchoolMask; + SpellEffectInfo Effects[MAX_SPELL_EFFECTS]; + uint32 ExplicitTargetMask; + SpellChainNode const* ChainEntry; + + SpellInfo(SpellEntry const* spellEntry); + ~SpellInfo(); + + uint32 GetCategory() const; + bool HasEffect(SpellEffects effect) const; + bool HasAura(AuraType aura) 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(SpellCustomAttributes customAttribute) const { return !!(AttributesCu & customAttribute); } + + bool IsExplicitDiscovery() const; + bool IsLootCrafting() const; + bool IsQuestTame() const; + bool IsProfessionOrRiding() const; + bool IsProfession() const; + bool IsPrimaryProfession() const; + bool IsPrimaryProfessionFirstRank() const; + bool IsAbilityLearnedWithProfession() const; + bool IsAbilityOfSkillType(uint32 skillType) const; + + bool IsAffectingArea() const; + bool IsTargetingArea() const; + bool NeedsExplicitUnitTarget() const; + bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell) const; + + bool IsPassive() const; + bool IsAutocastable() const; + bool IsStackableWithRanks() const; + bool IsPassiveStackableWithRanks() 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(uint8 effIndex) const; + uint32 GetSpellMechanicMaskByEffectMask(uint32 effectMask) const; + Mechanics GetEffectMechanic(uint8 effIndex) 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 GetDuration() const; + int32 GetMaxDuration() const; + + uint32 GetMaxTicks() const; + + uint32 CalcCastTime(Spell* spell = NULL) const; + uint32 GetRecoveryTime() const; + + int32 CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) 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; + + // 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(uint8 effIndex, bool deep) const; + bool _IsPositiveSpell() const; + static bool _IsPositiveTarget(uint32 targetA, uint32 targetB); + void _LoadSpellSpecific(); + void _LoadAuraState(); + void _LoadSpellDiminishInfo(); + + // unloading helpers + void _UnloadImplicitTargetConditionLists(); + + 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 badb5fc4997..3e42b62f9bb 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -51,302 +51,6 @@ bool IsPartOfSkillLine(uint32 skillId, uint32 spellId) return false; } -DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, bool triggered) -{ - if (spellproto->IsPositive()) - return DIMINISHING_NONE; - - for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i) - { - if (spellproto->Effects[i].ApplyAuraName == SPELL_AURA_MOD_TAUNT) - return DIMINISHING_TAUNT; - } - - // Explicit Diminishing Groups - switch (spellproto->SpellFamilyName) - { - case SPELLFAMILY_GENERIC: - { - // Pet charge effects (Infernal Awakening, Demon Charge) - if (spellproto->SpellVisual[0] == 2816 && spellproto->SpellIconID == 15) - return DIMINISHING_CONTROLLED_STUN; - // Frost Tomb - else if (spellproto->Id == 48400) - return DIMINISHING_NONE; - // Gnaw - else if (spellproto->Id == 47481) - return DIMINISHING_CONTROLLED_STUN; - // ToC Icehowl Arctic Breath - else if (spellproto->SpellVisual[0] == 14153) - return DIMINISHING_NONE; - // Black Plague - else if (spellproto->Id == 64155) - return DIMINISHING_NONE; - // Screams of the Dead (King Ymiron) - else if (spellproto->Id == 51750) - return DIMINISHING_NONE; - break; - } - // Event spells - case SPELLFAMILY_UNK1: - return DIMINISHING_NONE; - case SPELLFAMILY_MAGE: - { - // Frostbite - if (spellproto->SpellFamilyFlags[1] & 0x80000000) - return DIMINISHING_ROOT; - // Shattered Barrier - else if (spellproto->SpellVisual[0] == 12297) - return DIMINISHING_ROOT; - // Deep Freeze - else if (spellproto->SpellIconID == 2939 && spellproto->SpellVisual[0] == 9963) - return DIMINISHING_CONTROLLED_STUN; - // Frost Nova / Freeze (Water Elemental) - else if (spellproto->SpellIconID == 193) - return DIMINISHING_CONTROLLED_ROOT; - // Dragon's Breath - else if (spellproto->SpellFamilyFlags[0] & 0x800000) - return DIMINISHING_DRAGONS_BREATH; - break; - } - case SPELLFAMILY_WARRIOR: - { - // Hamstring - limit duration to 10s in PvP - if (spellproto->SpellFamilyFlags[0] & 0x2) - return DIMINISHING_LIMITONLY; - // Charge Stun (own diminishing) - else if (spellproto->SpellFamilyFlags[0] & 0x01000000) - return DIMINISHING_CHARGE; - break; - } - case SPELLFAMILY_WARLOCK: - { - // Curses/etc - if ((spellproto->SpellFamilyFlags[0] & 0x80000000) || (spellproto->SpellFamilyFlags[1] & 0x200)) - return DIMINISHING_LIMITONLY; - // Seduction - else if (spellproto->SpellFamilyFlags[1] & 0x10000000) - return DIMINISHING_FEAR; - break; - } - case SPELLFAMILY_DRUID: - { - // Pounce - if (spellproto->SpellFamilyFlags[0] & 0x20000) - return DIMINISHING_OPENING_STUN; - // Cyclone - else if (spellproto->SpellFamilyFlags[1] & 0x20) - return DIMINISHING_CYCLONE; - // Entangling Roots - // Nature's Grasp - else if (spellproto->SpellFamilyFlags[0] & 0x00000200) - return DIMINISHING_CONTROLLED_ROOT; - // Faerie Fire - else if (spellproto->SpellFamilyFlags[0] & 0x400) - return DIMINISHING_LIMITONLY; - break; - } - case SPELLFAMILY_ROGUE: - { - // Gouge - if (spellproto->SpellFamilyFlags[0] & 0x8) - return DIMINISHING_DISORIENT; - // Blind - else if (spellproto->SpellFamilyFlags[0] & 0x1000000) - return DIMINISHING_FEAR; - // Cheap Shot - else if (spellproto->SpellFamilyFlags[0] & 0x400) - return DIMINISHING_OPENING_STUN; - // Crippling poison - Limit to 10 seconds in PvP (No SpellFamilyFlags) - else if (spellproto->SpellIconID == 163) - return DIMINISHING_LIMITONLY; - break; - } - case SPELLFAMILY_HUNTER: - { - // Hunter's Mark - if ((spellproto->SpellFamilyFlags[0] & 0x400) && spellproto->SpellIconID == 538) - return DIMINISHING_LIMITONLY; - // Scatter Shot (own diminishing) - else if ((spellproto->SpellFamilyFlags[0] & 0x40000) && spellproto->SpellIconID == 132) - return DIMINISHING_SCATTER_SHOT; - // Entrapment (own diminishing) - else if (spellproto->SpellVisual[0] == 7484 && spellproto->SpellIconID == 20) - return DIMINISHING_ENTRAPMENT; - // Wyvern Sting mechanic is MECHANIC_SLEEP but the diminishing is DIMINISHING_DISORIENT - else if ((spellproto->SpellFamilyFlags[1] & 0x1000) && spellproto->SpellIconID == 1721) - return DIMINISHING_DISORIENT; - // Freezing Arrow - else if (spellproto->SpellFamilyFlags[0] & 0x8) - return DIMINISHING_DISORIENT; - break; - } - case SPELLFAMILY_PALADIN: - { - // Judgement of Justice - limit duration to 10s in PvP - if (spellproto->SpellFamilyFlags[0] & 0x100000) - return DIMINISHING_LIMITONLY; - // Turn Evil - else if ((spellproto->SpellFamilyFlags[1] & 0x804000) && spellproto->SpellIconID == 309) - return DIMINISHING_FEAR; - break; - } - case SPELLFAMILY_SHAMAN: - { - // Storm, Earth and Fire - Earthgrab - if (spellproto->SpellFamilyFlags[2] & 0x4000) - return DIMINISHING_NONE; - break; - } - case SPELLFAMILY_DEATHKNIGHT: - { - // Hungering Cold (no flags) - if (spellproto->SpellIconID == 2797) - return DIMINISHING_DISORIENT; - // Mark of Blood - else if ((spellproto->SpellFamilyFlags[0] & 0x10000000) && spellproto->SpellIconID == 2285) - return DIMINISHING_LIMITONLY; - break; - } - default: - break; - } - - // Lastly - Set diminishing depending on mechanic - uint32 mechanic = spellproto->GetAllEffectsMechanicMask(); - if (mechanic & (1 << MECHANIC_CHARM)) - return DIMINISHING_MIND_CONTROL; - if (mechanic & (1 << MECHANIC_SILENCE)) - return DIMINISHING_SILENCE; - if (mechanic & (1 << MECHANIC_SLEEP)) - return DIMINISHING_SLEEP; - if (mechanic & ((1 << MECHANIC_SAPPED) | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_SHACKLE))) - return DIMINISHING_DISORIENT; - // Mechanic Knockout, except Blast Wave - if (mechanic & (1 << MECHANIC_KNOCKOUT) && spellproto->SpellIconID != 292) - return DIMINISHING_DISORIENT; - if (mechanic & (1 << MECHANIC_DISARM)) - return DIMINISHING_DISARM; - if (mechanic & (1 << MECHANIC_FEAR)) - return DIMINISHING_FEAR; - if (mechanic & (1 << MECHANIC_STUN)) - return triggered ? DIMINISHING_STUN : DIMINISHING_CONTROLLED_STUN; - if (mechanic & (1 << MECHANIC_BANISH)) - return DIMINISHING_BANISH; - if (mechanic & (1 << MECHANIC_ROOT)) - return triggered ? DIMINISHING_ROOT : DIMINISHING_CONTROLLED_ROOT; - if (mechanic & (1 << MECHANIC_HORROR)) - return DIMINISHING_HORROR; - - return DIMINISHING_NONE; -} - -DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group) -{ - switch (group) - { - case DIMINISHING_TAUNT: - case DIMINISHING_CONTROLLED_STUN: - case DIMINISHING_STUN: - case DIMINISHING_OPENING_STUN: - case DIMINISHING_CYCLONE: - case DIMINISHING_CHARGE: - 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; - default: - return DIMINISHING_LEVEL_IMMUNE; - } -} - -int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const* spellproto) -{ - if (!IsDiminishingReturnsGroupDurationLimited(group)) - return 0; - - // Explicit diminishing duration - switch (spellproto->SpellFamilyName) - { - case SPELLFAMILY_DRUID: - { - // Faerie Fire - limit to 40 seconds in PvP (3.1) - if (spellproto->SpellFamilyFlags[0] & 0x400) - return 40 * IN_MILLISECONDS; - break; - } - case SPELLFAMILY_HUNTER: - { - // Wyvern Sting - if (spellproto->SpellFamilyFlags[1] & 0x1000) - return 6 * IN_MILLISECONDS; - // Hunter's Mark - if (spellproto->SpellFamilyFlags[0] & 0x400) - return 120 * IN_MILLISECONDS; - break; - } - case SPELLFAMILY_PALADIN: - { - // Repentance - limit to 6 seconds in PvP - if (spellproto->SpellFamilyFlags[0] & 0x4) - return 6 * IN_MILLISECONDS; - break; - } - case SPELLFAMILY_WARLOCK: - { - // Banish - limit to 6 seconds in PvP - if (spellproto->SpellFamilyFlags[1] & 0x8000000) - return 6 * IN_MILLISECONDS; - // Curse of Tongues - limit to 12 seconds in PvP - else if (spellproto->SpellFamilyFlags[2] & 0x800) - return 12 * IN_MILLISECONDS; - // Curse of Elements - limit to 120 seconds in PvP - else if (spellproto->SpellFamilyFlags[1] & 0x200) - return 120 * IN_MILLISECONDS; - break; - } - default: - break; - } - - return 10 * IN_MILLISECONDS; -} - -bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group) -{ - switch (group) - { - case DIMINISHING_BANISH: - case DIMINISHING_CONTROLLED_STUN: - case DIMINISHING_CONTROLLED_ROOT: - case DIMINISHING_CYCLONE: - case DIMINISHING_DISORIENT: - case DIMINISHING_ENTRAPMENT: - case DIMINISHING_FEAR: - case DIMINISHING_HORROR: - case DIMINISHING_MIND_CONTROL: - case DIMINISHING_OPENING_STUN: - case DIMINISHING_ROOT: - case DIMINISHING_STUN: - case DIMINISHING_SLEEP: - case DIMINISHING_LIMITONLY: - return true; - default: - return false; - } -} - SpellMgr::SpellMgr() { } SpellMgr::~SpellMgr() @@ -3769,3 +3473,18 @@ 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)); +} diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 60af9bd94bf..f119d164789 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -547,13 +547,6 @@ inline bool IsProfessionOrRidingSkill(uint32 skill) bool IsPartOfSkillLine(uint32 skillId, uint32 spellId); -// spell diminishing returns -TC_GAME_API DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, bool triggered); -TC_GAME_API DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group); -TC_GAME_API DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group); -TC_GAME_API int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const* spellproto); -TC_GAME_API bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group); - class TC_GAME_API SpellMgr { // Constructors @@ -686,6 +679,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 443d0c63efa..59a1e757183 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1452,6 +1452,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 GameObject models..."); LoadGameObjectModelList(m_dataPath); |
