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)
This commit is contained in:
ariel-
2017-10-03 20:53:49 +02:00
committed by joschiwald
parent 4d5eacd3af
commit 2d75d8071b
10 changed files with 744 additions and 676 deletions
+49 -54
View File
@@ -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)
DiminishingReturn& diminish = m_Diminishing[group];
if (!diminish.hitCount)
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 (!diminish.stack && GetMSTimeDiffToNow(diminish.hitTime) > 18 * IN_MILLISECONDS)
{
if (i->DRGroup != group)
continue;
if (!i->hitCount)
return DIMINISHING_LEVEL_1;
if (!i->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);
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)
{
if (i->DRGroup != group)
continue;
DiminishingReturn& diminish = m_Diminishing[group];
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;
if (apply)
++diminish.stack;
else if (diminish.stack)
{
--diminish.stack;
// 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)
+15 -10
View File
@@ -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;
@@ -4597,6 +4597,8 @@ enum DiminishingGroup : uint16
DIMINISHING_AOE_KNOCKBACK = 6,
DIMINISHING_TAUNT = 7,
DIMINISHING_LIMITONLY = 8,
DIMINISHING_MAX
};
enum SummonCategory
+12 -15
View File
@@ -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)
-4
View File
@@ -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;
+416
View File
@@ -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)
+231 -208
View File
@@ -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;
friend class SpellMgr;
uint32 ExplicitTargetMask;
SpellChainNode const* ChainEntry;
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;
SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const& effectsMap, SpellVisualMap&& visuals,
std::unordered_map<uint32, SpellEffectScalingEntry const*> const& effectScaling);
~SpellInfo();
// SpellScalingEntry
struct ScalingInfo
{
int32 Class;
uint32 MinScalingLevel;
uint32 MaxScalingLevel;
uint32 ScalesFromItemLevel;
} Scaling;
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;
uint32 ExplicitTargetMask;
SpellChainNode const* ChainEntry;
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); }
SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const& effectsMap, SpellVisualMap&& visuals,
std::unordered_map<uint32, SpellEffectScalingEntry const*> const& effectScaling);
~SpellInfo();
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;
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;
bool IsAffectingArea(uint32 difficulty) const;
bool IsTargetingArea(uint32 difficulty) const;
bool NeedsExplicitUnitTarget() const;
bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) 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 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 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 IsAffectedBySpellMods() const;
bool IsAffectedBySpellMod(SpellModifier const* mod) const;
bool IsAffectingArea(uint32 difficulty) const;
bool IsTargetingArea(uint32 difficulty) const;
bool NeedsExplicitUnitTarget() const;
bool NeedsToBeTriggeredByCaster(SpellInfo const* triggeringSpell, uint32 difficulty) const;
bool CanPierceImmuneAura(SpellInfo const* aura) const;
bool CanDispelAura(SpellInfo const* aura) 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 IsSingleTarget() const;
bool IsAuraExclusiveBySpecificWith(SpellInfo const* spellInfo) const;
bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const* spellInfo) const;
bool IsAffectedBySpellMods() const;
bool IsAffectedBySpellMod(SpellModifier const* mod) 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;
bool CanPierceImmuneAura(SpellInfo const* aura) const;
bool CanDispelAura(SpellInfo const* aura) 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;
bool IsSingleTarget() const;
bool IsAuraExclusiveBySpecificWith(SpellInfo const* spellInfo) const;
bool IsAuraExclusiveBySpecificPerCasterWith(SpellInfo const* spellInfo) const;
AuraStateType GetAuraState() const;
SpellSpecificType GetSpellSpecific() 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;
float GetMinRange(bool positive = false) const;
float GetMaxRange(bool positive = false, Unit* caster = NULL, Spell* spell = NULL) 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;
int32 CalcDuration(Unit* caster = nullptr) const;
int32 GetDuration() const;
int32 GetMaxDuration() const;
AuraStateType GetAuraState() const;
SpellSpecificType GetSpellSpecific() const;
uint32 GetMaxTicks(uint32 difficulty) const;
float GetMinRange(bool positive = false) const;
float GetMaxRange(bool positive = false, Unit* caster = NULL, Spell* spell = NULL) const;
uint32 CalcCastTime(uint8 level = 0, Spell* spell = NULL) const;
uint32 GetRecoveryTime() const;
int32 CalcDuration(Unit* caster = nullptr) const;
int32 GetDuration() const;
int32 GetMaxDuration() const;
std::vector<SpellPowerCost> CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) const;
uint32 GetMaxTicks(uint32 difficulty) const;
float CalcProcPPM(Unit* caster, int32 itemLevel) const;
uint32 CalcCastTime(uint8 level = 0, Spell* spell = NULL) const;
uint32 GetRecoveryTime() 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;
std::vector<SpellPowerCost> CalcPowerCost(Unit const* caster, SpellSchoolMask schoolMask) const;
uint32 GetSpellXSpellVisualId(Unit const* caster = nullptr) const;
uint32 GetSpellVisual(Unit const* caster = nullptr) const;
float CalcProcPPM(Unit* caster, int32 itemLevel) 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();
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;
// unloading helpers
void _UnloadImplicitTargetConditionLists();
void _UnloadSpellEffects();
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); }
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;
// 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
+15 -379
View File
@@ -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;
+1 -6
View File
@@ -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;
+3
View File
@@ -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();