2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "ObjectMgr.h"
21 #include "SpellAuraDefines.h"
22 #include "ProgressBar.h"
23 #include "Database/DBCStores.h"
27 #include "BattleGroundMgr.h"
37 SpellMgr
& SpellMgr::Instance()
39 static SpellMgr spellMgr
;
43 int32
GetSpellDuration(SpellEntry
const *spellInfo
)
47 SpellDurationEntry
const *du
= sSpellDurationStore
.LookupEntry(spellInfo
->DurationIndex
);
50 return (du
->Duration
[0] == -1) ? -1 : abs(du
->Duration
[0]);
53 int32
GetSpellMaxDuration(SpellEntry
const *spellInfo
)
57 SpellDurationEntry
const *du
= sSpellDurationStore
.LookupEntry(spellInfo
->DurationIndex
);
60 return (du
->Duration
[2] == -1) ? -1 : abs(du
->Duration
[2]);
63 uint32
GetSpellCastTime(SpellEntry
const* spellInfo
, Spell
const* spell
)
65 SpellCastTimesEntry
const *spellCastTimeEntry
= sSpellCastTimesStore
.LookupEntry(spellInfo
->CastingTimeIndex
);
67 // not all spells have cast time index and this is all is pasiive abilities
68 if(!spellCastTimeEntry
)
71 int32 castTime
= spellCastTimeEntry
->CastTime
;
75 if(Player
* modOwner
= spell
->GetCaster()->GetSpellModOwner())
76 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_CASTING_TIME
, castTime
, spell
);
78 if( !(spellInfo
->Attributes
& (SPELL_ATTR_UNK4
|SPELL_ATTR_UNK5
)) )
79 castTime
= int32(castTime
* spell
->GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED
));
82 if (spell
->IsRangedSpell() && !spell
->IsAutoRepeat())
83 castTime
= int32(castTime
* spell
->GetCaster()->m_modAttackSpeedPct
[RANGED_ATTACK
]);
87 if (spellInfo
->Attributes
& SPELL_ATTR_RANGED
&& (!spell
|| !(spell
->IsAutoRepeat())))
90 return (castTime
> 0) ? uint32(castTime
) : 0;
93 bool IsPassiveSpell(uint32 spellId
)
95 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
98 return (spellInfo
->Attributes
& SPELL_ATTR_PASSIVE
) != 0;
101 bool IsNoStackAuraDueToAura(uint32 spellId_1
, uint32 effIndex_1
, uint32 spellId_2
, uint32 effIndex_2
)
103 SpellEntry
const *spellInfo_1
= sSpellStore
.LookupEntry(spellId_1
);
104 SpellEntry
const *spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
105 if(!spellInfo_1
|| !spellInfo_2
) return false;
106 if(spellInfo_1
->Id
== spellId_2
) return false;
108 if (spellInfo_1
->Effect
[effIndex_1
] != spellInfo_2
->Effect
[effIndex_2
] ||
109 spellInfo_1
->EffectItemType
[effIndex_1
] != spellInfo_2
->EffectItemType
[effIndex_2
] ||
110 spellInfo_1
->EffectMiscValue
[effIndex_1
] != spellInfo_2
->EffectMiscValue
[effIndex_2
] ||
111 spellInfo_1
->EffectApplyAuraName
[effIndex_1
] != spellInfo_2
->EffectApplyAuraName
[effIndex_2
])
117 int32
CompareAuraRanks(uint32 spellId_1
, uint32 effIndex_1
, uint32 spellId_2
, uint32 effIndex_2
)
119 SpellEntry
const*spellInfo_1
= sSpellStore
.LookupEntry(spellId_1
);
120 SpellEntry
const*spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
121 if(!spellInfo_1
|| !spellInfo_2
) return 0;
122 if (spellId_1
== spellId_2
) return 0;
124 int32 diff
= spellInfo_1
->EffectBasePoints
[effIndex_1
] - spellInfo_2
->EffectBasePoints
[effIndex_2
];
125 if (spellInfo_1
->EffectBasePoints
[effIndex_1
]+1 < 0 && spellInfo_2
->EffectBasePoints
[effIndex_2
]+1 < 0) return -diff
;
129 SpellSpecific
GetSpellSpecific(uint32 spellId
)
131 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
135 switch(spellInfo
->SpellFamilyName
)
137 case SPELLFAMILY_MAGE
:
139 // family flags 18(Molten), 25(Frost/Ice), 28(Mage)
140 if (spellInfo
->SpellFamilyFlags
& 0x12040000)
141 return SPELL_MAGE_ARMOR
;
143 if ((spellInfo
->SpellFamilyFlags
& 0x1000000) && spellInfo
->EffectApplyAuraName
[0]==SPELL_AURA_MOD_CONFUSE
)
144 return SPELL_MAGE_POLYMORPH
;
148 case SPELLFAMILY_WARRIOR
:
150 if (spellInfo
->SpellFamilyFlags
& 0x00008000010000LL
)
151 return SPELL_POSITIVE_SHOUT
;
155 case SPELLFAMILY_WARLOCK
:
157 // only warlock curses have this
158 if (spellInfo
->Dispel
== DISPEL_CURSE
)
161 // Warlock (Demon Armor | Demon Skin | Fel Armor)
162 if (spellInfo
->SpellFamilyFlags
& 0x2000002000000000LL
|| spellInfo
->SpellFamilyFlags2
& 0x00000010)
163 return SPELL_WARLOCK_ARMOR
;
167 case SPELLFAMILY_HUNTER
:
169 // only hunter stings have this
170 if (spellInfo
->Dispel
== DISPEL_POISON
)
173 // only hunter aspects have this (but not all aspects in hunter family)
174 if( spellInfo
->SpellFamilyFlags
& 0x0044000000380000LL
|| spellInfo
->SpellFamilyFlags2
& 0x00003010)
177 if( spellInfo
->SpellFamilyFlags2
& 0x00000002 )
178 return SPELL_TRACKER
;
182 case SPELLFAMILY_PALADIN
:
184 if (IsSealSpell(spellInfo
))
187 if (spellInfo
->SpellFamilyFlags
& 0x0000000011010002LL
)
188 return SPELL_BLESSING
;
190 if ((spellInfo
->SpellFamilyFlags
& 0x00000820180400LL
) && (spellInfo
->AttributesEx3
& 0x200))
191 return SPELL_JUDGEMENT
;
193 for (int i
= 0; i
< 3; i
++)
195 // only paladin auras have this (for palaldin class family)
196 if (spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AREA_AURA_RAID
)
201 case SPELLFAMILY_SHAMAN
:
203 if (IsElementalShield(spellInfo
))
204 return SPELL_ELEMENTAL_SHIELD
;
209 case SPELLFAMILY_POTION
:
210 return spellmgr
.GetSpellElixirSpecific(spellInfo
->Id
);
212 case SPELLFAMILY_DEATHKNIGHT
:
213 if ((spellInfo
->Attributes
& 0x10) && (spellInfo
->AttributesEx2
& 0x10) && (spellInfo
->AttributesEx4
& 0x200000))
214 return SPELL_PRESENCE
;
218 // elixirs can have different families, but potion most ofc.
219 if(SpellSpecific sp
= spellmgr
.GetSpellElixirSpecific(spellInfo
->Id
))
225 bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1
,uint32 spellSpec2
)
236 case SPELL_WARLOCK_ARMOR
:
237 case SPELL_MAGE_ARMOR
:
238 case SPELL_MAGE_POLYMORPH
:
239 case SPELL_POSITIVE_SHOUT
:
240 case SPELL_JUDGEMENT
:
242 return spellSpec1
==spellSpec2
;
243 case SPELL_BATTLE_ELIXIR
:
244 return spellSpec2
==SPELL_BATTLE_ELIXIR
245 || spellSpec2
==SPELL_FLASK_ELIXIR
;
246 case SPELL_GUARDIAN_ELIXIR
:
247 return spellSpec2
==SPELL_GUARDIAN_ELIXIR
248 || spellSpec2
==SPELL_FLASK_ELIXIR
;
249 case SPELL_FLASK_ELIXIR
:
250 return spellSpec2
==SPELL_BATTLE_ELIXIR
251 || spellSpec2
==SPELL_GUARDIAN_ELIXIR
252 || spellSpec2
==SPELL_FLASK_ELIXIR
;
258 bool IsPositiveTarget(uint32 targetA
, uint32 targetB
)
260 // non-positive targets
263 case TARGET_CHAIN_DAMAGE
:
264 case TARGET_ALL_ENEMY_IN_AREA
:
265 case TARGET_ALL_ENEMY_IN_AREA_INSTANT
:
266 case TARGET_IN_FRONT_OF_CASTER
:
267 case TARGET_ALL_ENEMY_IN_AREA_CHANNELED
:
268 case TARGET_CURRENT_ENEMY_COORDINATES
:
269 case TARGET_SINGLE_ENEMY
:
271 case TARGET_CASTER_COORDINATES
:
272 return (targetB
== TARGET_ALL_PARTY
|| targetB
== TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER
);
277 return IsPositiveTarget(targetB
, 0);
281 bool IsPositiveEffect(uint32 spellId
, uint32 effIndex
)
283 SpellEntry
const *spellproto
= sSpellStore
.LookupEntry(spellId
);
284 if (!spellproto
) return false;
288 case 23333: // BG spell
289 case 23335: // BG spell
290 case 34976: // BG spell
292 case 28441: // not positive dummy spell
293 case 37675: // Chaos Blast
297 switch(spellproto
->Effect
[effIndex
])
299 // always positive effects (check before target checks that provided non-positive result in some case for positive effects)
300 case SPELL_EFFECT_HEAL
:
301 case SPELL_EFFECT_LEARN_SPELL
:
302 case SPELL_EFFECT_SKILL_STEP
:
303 case SPELL_EFFECT_HEAL_PCT
:
304 case SPELL_EFFECT_ENERGIZE_PCT
:
307 // non-positive aura use
308 case SPELL_EFFECT_APPLY_AURA
:
309 case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
:
311 switch(spellproto
->EffectApplyAuraName
[effIndex
])
313 case SPELL_AURA_DUMMY
:
315 // dummy aura can be positive or negative dependent from casted spell
316 switch(spellproto
->Id
)
318 case 13139: // net-o-matic special effect
319 case 23445: // evil twin
320 case 38637: // Nether Exhaustion (red)
321 case 38638: // Nether Exhaustion (green)
322 case 38639: // Nether Exhaustion (blue)
328 case SPELL_AURA_MOD_STAT
:
329 case SPELL_AURA_MOD_DAMAGE_DONE
: // dependent from bas point sign (negative -> negative)
330 case SPELL_AURA_MOD_HEALING_DONE
:
332 if(spellproto
->EffectBasePoints
[effIndex
]+int32(spellproto
->EffectBaseDice
[effIndex
]) < 0)
336 case SPELL_AURA_ADD_TARGET_TRIGGER
:
338 case SPELL_AURA_PERIODIC_TRIGGER_SPELL
:
339 if(spellId
!= spellproto
->EffectTriggerSpell
[effIndex
])
341 uint32 spellTriggeredId
= spellproto
->EffectTriggerSpell
[effIndex
];
342 SpellEntry
const *spellTriggeredProto
= sSpellStore
.LookupEntry(spellTriggeredId
);
344 if(spellTriggeredProto
)
346 // non-positive targets of main spell return early
347 for(int i
= 0; i
< 3; ++i
)
349 // if non-positive trigger cast targeted to positive target this main cast is non-positive
350 // this will place this spell auras as debuffs
351 if(IsPositiveTarget(spellTriggeredProto
->EffectImplicitTargetA
[effIndex
],spellTriggeredProto
->EffectImplicitTargetB
[effIndex
]) && !IsPositiveEffect(spellTriggeredId
,i
))
357 case SPELL_AURA_PROC_TRIGGER_SPELL
:
358 // many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example)
360 case SPELL_AURA_MOD_STUN
: //have positive and negative spells, we can't sort its correctly at this moment.
361 if(effIndex
==0 && spellproto
->Effect
[1]==0 && spellproto
->Effect
[2]==0)
362 return false; // but all single stun aura spells is negative
365 if(spellproto
->Id
== 17624)
368 case SPELL_AURA_MOD_ROOT
:
369 case SPELL_AURA_MOD_SILENCE
:
370 case SPELL_AURA_GHOST
:
371 case SPELL_AURA_PERIODIC_LEECH
:
372 case SPELL_AURA_MOD_PACIFY_SILENCE
:
373 case SPELL_AURA_MOD_STALKED
:
374 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT
:
376 case SPELL_AURA_PERIODIC_DAMAGE
: // used in positive spells also.
377 // part of negative spell if casted at self (prevent cancel)
378 if(spellproto
->EffectImplicitTargetA
[effIndex
] == TARGET_SELF
)
381 case SPELL_AURA_MOD_DECREASE_SPEED
: // used in positive spells also
382 // part of positive spell if casted at self
383 if(spellproto
->EffectImplicitTargetA
[effIndex
] != TARGET_SELF
)
385 // but not this if this first effect (don't found batter check)
386 if(spellproto
->Attributes
& 0x4000000 && effIndex
==0)
389 case SPELL_AURA_TRANSFORM
:
390 // some spells negative
391 switch(spellproto
->Id
)
393 case 36897: // Transporter Malfunction (race mutation to horde)
394 case 36899: // Transporter Malfunction (race mutation to alliance)
398 case SPELL_AURA_MOD_SCALE
:
399 // some spells negative
400 switch(spellproto
->Id
)
402 case 36900: // Soul Split: Evil!
403 case 36901: // Soul Split: Good
404 case 36893: // Transporter Malfunction (decrease size case)
405 case 36895: // Transporter Malfunction (increase size case)
409 case SPELL_AURA_MECHANIC_IMMUNITY
:
411 // non-positive immunities
412 switch(spellproto
->EffectMiscValue
[effIndex
])
414 case MECHANIC_BANDAGE
:
415 case MECHANIC_SHIELD
:
417 case MECHANIC_INVULNERABILITY
:
423 case SPELL_AURA_ADD_FLAT_MODIFIER
: // mods
424 case SPELL_AURA_ADD_PCT_MODIFIER
:
427 switch(spellproto
->EffectMiscValue
[effIndex
])
429 case SPELLMOD_COST
: // dependent from bas point sign (negative -> positive)
430 if(spellproto
->EffectBasePoints
[effIndex
]+int32(spellproto
->EffectBaseDice
[effIndex
]) > 0)
437 case SPELL_AURA_MOD_HEALING_PCT
:
438 if(spellproto
->EffectBasePoints
[effIndex
]+int32(spellproto
->EffectBaseDice
[effIndex
]) < 0)
441 case SPELL_AURA_MOD_SKILL
:
442 if(spellproto
->EffectBasePoints
[effIndex
]+int32(spellproto
->EffectBaseDice
[effIndex
]) < 0)
445 case SPELL_AURA_FORCE_REACTION
:
446 if(spellproto
->Id
==42792) // Recently Dropped Flag (prevent cancel)
458 // non-positive targets
459 if(!IsPositiveTarget(spellproto
->EffectImplicitTargetA
[effIndex
],spellproto
->EffectImplicitTargetB
[effIndex
]))
462 // AttributesEx check
463 if(spellproto
->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)
470 bool IsPositiveSpell(uint32 spellId
)
472 SpellEntry
const *spellproto
= sSpellStore
.LookupEntry(spellId
);
473 if (!spellproto
) return false;
475 // spells with atleast one negative effect are considered negative
476 // some self-applied spells have negative effects but in self casting case negative check ignored.
477 for (int i
= 0; i
< 3; i
++)
478 if (!IsPositiveEffect(spellId
, i
))
483 bool IsSingleTargetSpell(SpellEntry
const *spellInfo
)
485 // all other single target spells have if it has AttributesEx5
486 if ( spellInfo
->AttributesEx5
& SPELL_ATTR_EX5_SINGLE_TARGET_SPELL
)
489 // TODO - need found Judgements rule
490 switch(GetSpellSpecific(spellInfo
->Id
))
492 case SPELL_JUDGEMENT
:
496 // single target triggered spell.
497 // Not real client side single target spell, but it' not triggered until prev. aura expired.
498 // This is allow store it in single target spells list for caster for spell proc checking
499 if(spellInfo
->Id
==38324) // Regeneration (triggered by 38299 (HoTs on Heals))
505 bool IsSingleTargetSpells(SpellEntry
const *spellInfo1
, SpellEntry
const *spellInfo2
)
507 // TODO - need better check
508 // Equal icon and spellfamily
509 if( spellInfo1
->SpellFamilyName
== spellInfo2
->SpellFamilyName
&&
510 spellInfo1
->SpellIconID
== spellInfo2
->SpellIconID
)
513 // TODO - need found Judgements rule
514 SpellSpecific spec1
= GetSpellSpecific(spellInfo1
->Id
);
515 // spell with single target specific types
518 case SPELL_JUDGEMENT
:
519 if(GetSpellSpecific(spellInfo2
->Id
) == spec1
)
527 bool IsAuraAddedBySpell(uint32 auraType
, uint32 spellId
)
529 SpellEntry
const *spellproto
= sSpellStore
.LookupEntry(spellId
);
530 if (!spellproto
) return false;
532 for (int i
= 0; i
< 3; i
++)
533 if (spellproto
->EffectApplyAuraName
[i
] == auraType
)
538 uint8
GetErrorAtShapeshiftedCast (SpellEntry
const *spellInfo
, uint32 form
)
540 // talents that learn spells can have stance requirements that need ignore
541 // (this requirement only for client-side stance show in talent description)
542 if( GetTalentSpellCost(spellInfo
->Id
) > 0 &&
543 (spellInfo
->Effect
[0]==SPELL_EFFECT_LEARN_SPELL
|| spellInfo
->Effect
[1]==SPELL_EFFECT_LEARN_SPELL
|| spellInfo
->Effect
[2]==SPELL_EFFECT_LEARN_SPELL
) )
546 uint32 stanceMask
= (form
? 1 << (form
- 1) : 0);
548 if (stanceMask
& spellInfo
->StancesNot
) // can explicitly not be casted in this stance
549 return SPELL_FAILED_NOT_SHAPESHIFT
;
551 if (stanceMask
& spellInfo
->Stances
) // can explicitly be casted in this stance
554 bool actAsShifted
= false;
557 SpellShapeshiftEntry
const *shapeInfo
= sSpellShapeshiftStore
.LookupEntry(form
);
560 sLog
.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form
);
563 actAsShifted
= !(shapeInfo
->flags1
& 1); // shapeshift acts as normal form for spells
568 if (spellInfo
->Attributes
& SPELL_ATTR_NOT_SHAPESHIFT
) // not while shapeshifted
569 return SPELL_FAILED_NOT_SHAPESHIFT
;
570 else if (spellInfo
->Stances
!= 0) // needs other shapeshift
571 return SPELL_FAILED_ONLY_SHAPESHIFT
;
576 if(!(spellInfo
->AttributesEx2
& SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT
) && spellInfo
->Stances
!= 0)
577 return SPELL_FAILED_ONLY_SHAPESHIFT
;
583 void SpellMgr::LoadSpellTargetPositions()
585 mSpellTargetPositions
.clear(); // need for reload case
590 QueryResult
*result
= WorldDatabase
.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position");
599 sLog
.outString( ">> Loaded %u spell target coordinates", count
);
603 barGoLink
bar( result
->GetRowCount() );
607 Field
*fields
= result
->Fetch();
613 uint32 Spell_ID
= fields
[0].GetUInt32();
615 SpellTargetPosition st
;
617 st
.target_mapId
= fields
[1].GetUInt32();
618 st
.target_X
= fields
[2].GetFloat();
619 st
.target_Y
= fields
[3].GetFloat();
620 st
.target_Z
= fields
[4].GetFloat();
621 st
.target_Orientation
= fields
[5].GetFloat();
623 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(Spell_ID
);
626 sLog
.outErrorDb("Spell (ID:%u) listed in `spell_target_position` does not exist.",Spell_ID
);
631 for(int i
= 0; i
< 3; ++i
)
633 if( spellInfo
->EffectImplicitTargetA
[i
]==TARGET_TABLE_X_Y_Z_COORDINATES
|| spellInfo
->EffectImplicitTargetB
[i
]==TARGET_TABLE_X_Y_Z_COORDINATES
)
641 sLog
.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID
);
645 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(st
.target_mapId
);
648 sLog
.outErrorDb("Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Spell_ID
,st
.target_mapId
);
652 if(st
.target_X
==0 && st
.target_Y
==0 && st
.target_Z
==0)
654 sLog
.outErrorDb("Spell (ID:%u) target coordinates not provided.",Spell_ID
);
658 mSpellTargetPositions
[Spell_ID
] = st
;
660 } while( result
->NextRow() );
665 sLog
.outString( ">> Loaded %u spell teleport coordinates", count
);
668 void SpellMgr::LoadSpellAffects()
670 mSpellAffectMap
.clear(); // need for reload case
675 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, effectId, SpellClassMask0, SpellClassMask1, SpellClassMask2 FROM spell_affect");
684 sLog
.outString( ">> Loaded %u spell affect definitions", count
);
688 barGoLink
bar( result
->GetRowCount() );
692 Field
*fields
= result
->Fetch();
696 uint16 entry
= fields
[0].GetUInt16();
697 uint8 effectId
= fields
[1].GetUInt8();
699 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(entry
);
703 sLog
.outErrorDb("Spell %u listed in `spell_affect` does not exist", entry
);
709 sLog
.outErrorDb("Spell %u listed in `spell_affect` have invalid effect index (%u)", entry
,effectId
);
713 if( spellInfo
->Effect
[effectId
] != SPELL_EFFECT_APPLY_AURA
||
714 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_FLAT_MODIFIER
&&
715 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_PCT_MODIFIER
&&
716 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_TARGET_TRIGGER
)
718 sLog
.outErrorDb("Spell %u listed in `spell_affect` have not SPELL_AURA_ADD_FLAT_MODIFIER (%u) or SPELL_AURA_ADD_PCT_MODIFIER (%u) or SPELL_AURA_ADD_TARGET_TRIGGER (%u) for effect index (%u)", entry
,SPELL_AURA_ADD_FLAT_MODIFIER
,SPELL_AURA_ADD_PCT_MODIFIER
,SPELL_AURA_ADD_TARGET_TRIGGER
,effectId
);
722 SpellAffectEntry affect
;
723 affect
.SpellClassMask
[0] = fields
[2].GetUInt32();
724 affect
.SpellClassMask
[1] = fields
[3].GetUInt32();
725 affect
.SpellClassMask
[2] = fields
[4].GetUInt32();
727 // Spell.dbc have own data
728 uint32
const *ptr
= 0;
731 case 0: ptr
= &spellInfo
->EffectSpellClassMaskA
[0]; break;
732 case 1: ptr
= &spellInfo
->EffectSpellClassMaskB
[0]; break;
733 case 2: ptr
= &spellInfo
->EffectSpellClassMaskC
[0]; break;
737 if(ptr
[0] == affect
.SpellClassMask
[0] || ptr
[1] == affect
.SpellClassMask
[1] || ptr
[2] == affect
.SpellClassMask
[2])
740 sLog
.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectSpellClassMask%c) data for effect index (%u) and not needed, skipped.", entry
, text
[effectId
], effectId
);
744 mSpellAffectMap
[(entry
<<8) + effectId
] = affect
;
747 } while( result
->NextRow() );
752 sLog
.outString( ">> Loaded %u custom spell affect definitions", count
);
754 for (uint32 id
= 0; id
< sSpellStore
.GetNumRows(); ++id
)
756 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(id
);
760 for (int effectId
= 0; effectId
< 3; ++effectId
)
762 if( spellInfo
->Effect
[effectId
] != SPELL_EFFECT_APPLY_AURA
||
763 (spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_FLAT_MODIFIER
&&
764 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_PCT_MODIFIER
&&
765 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_TARGET_TRIGGER
) )
768 uint32
const *ptr
= 0;
771 case 0: ptr
= &spellInfo
->EffectSpellClassMaskA
[0]; break;
772 case 1: ptr
= &spellInfo
->EffectSpellClassMaskB
[0]; break;
773 case 2: ptr
= &spellInfo
->EffectSpellClassMaskC
[0]; break;
777 if(ptr
[0] || ptr
[1] || ptr
[2])
780 if(mSpellAffectMap
.find((id
<<8) + effectId
) != mSpellAffectMap
.end())
783 sLog
.outErrorDb("Spell %u (%s) misses spell_affect for effect %u",id
,spellInfo
->SpellName
[sWorld
.GetDefaultDbcLocale()], effectId
);
788 bool SpellMgr::IsAffectedByMod(SpellEntry
const *spellInfo
, SpellModifier
*mod
) const
790 // false for spellInfo == NULL
791 if (!spellInfo
|| !mod
)
794 SpellEntry
const *affect_spell
= sSpellStore
.LookupEntry(mod
->spellId
);
795 // False if affect_spell == NULL or spellFamily not equal
796 if (!affect_spell
|| affect_spell
->SpellFamilyName
!= spellInfo
->SpellFamilyName
)
800 if (mod
->mask
& spellInfo
->SpellFamilyFlags
||
801 mod
->mask2
& spellInfo
->SpellFamilyFlags2
)
807 void SpellMgr::LoadSpellProcEvents()
809 mSpellProcEventMap
.clear(); // need for reload case
813 // 0 1 2 3 4 5 6 7 8 9 10
814 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
820 sLog
.outString( ">> Loaded %u spell proc event conditions", count
);
824 barGoLink
bar( result
->GetRowCount() );
825 uint32 customProc
= 0;
828 Field
*fields
= result
->Fetch();
832 uint32 entry
= fields
[0].GetUInt32();
834 const SpellEntry
*spell
= sSpellStore
.LookupEntry(entry
);
837 sLog
.outErrorDb("Spell %u listed in `spell_proc_event` does not exist", entry
);
841 SpellProcEventEntry spe
;
843 spe
.schoolMask
= fields
[1].GetUInt32();
844 spe
.spellFamilyName
= fields
[2].GetUInt32();
845 spe
.spellFamilyMask
= (uint64
)fields
[3].GetUInt32()|((uint64
)fields
[4].GetUInt32()<<32);
846 spe
.spellFamilyMask2
= fields
[5].GetUInt32();
847 spe
.procFlags
= fields
[6].GetUInt32();
848 spe
.procEx
= fields
[7].GetUInt32();
849 spe
.ppmRate
= fields
[8].GetFloat();
850 spe
.customChance
= fields
[9].GetFloat();
851 spe
.cooldown
= fields
[10].GetUInt32();
853 mSpellProcEventMap
[entry
] = spe
;
855 if (spell
->procFlags
==0)
857 if (spe
.procFlags
== 0)
859 sLog
.outErrorDb("Spell %u listed in `spell_proc_event` probally not triggered spell", entry
);
865 } while( result
->NextRow() );
871 sLog
.outString( ">> Loaded %u extra spell proc event conditions +%u custom", count
, customProc
);
873 sLog
.outString( ">> Loaded %u extra spell proc event conditions", count
);
876 void SpellMgr::LoadSpellBonusess()
878 mSpellBonusMap
.clear(); // need for reload case
881 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, direct_bonus, dot_bonus, ap_bonus FROM spell_bonus_data");
887 sLog
.outString( ">> Loaded %u spell bonus data", count
);
891 barGoLink
bar( result
->GetRowCount() );
894 Field
*fields
= result
->Fetch();
896 uint32 entry
= fields
[0].GetUInt32();
898 const SpellEntry
*spell
= sSpellStore
.LookupEntry(entry
);
901 sLog
.outErrorDb("Spell %u listed in `spell_bonus_data` does not exist", entry
);
907 sbe
.direct_damage
= fields
[1].GetFloat();
908 sbe
.dot_damage
= fields
[2].GetFloat();
909 sbe
.ap_bonus
= fields
[3].GetFloat();
911 mSpellBonusMap
[entry
] = sbe
;
912 } while( result
->NextRow() );
917 sLog
.outString( ">> Loaded %u extra spell bonus data", count
);
920 bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry
const * spellProcEvent
, uint32 EventProcFlag
, SpellEntry
const * procSpell
, uint32 procFlags
, uint32 procExtra
, bool active
)
923 uint32 procEvent_procEx
= PROC_EX_NONE
;
925 // check prockFlags for condition
926 if((procFlags
& EventProcFlag
) == 0)
929 // Always trigger for this
930 if (EventProcFlag
& (PROC_FLAG_KILLED
| PROC_FLAG_KILL
| PROC_FLAG_ON_TRAP_ACTIVATION
))
933 if (spellProcEvent
) // Exist event data
936 procEvent_procEx
= spellProcEvent
->procEx
;
938 // For melee triggers
939 if (procSpell
== NULL
)
941 // Check (if set) for school (melee attack have Normal school)
942 if(spellProcEvent
->schoolMask
&& (spellProcEvent
->schoolMask
& SPELL_SCHOOL_MASK_NORMAL
) == 0)
945 else // For spells need check school/spell family/family mask
947 // Check (if set) for school
948 if(spellProcEvent
->schoolMask
&& (spellProcEvent
->schoolMask
& procSpell
->SchoolMask
) == 0)
951 // Check (if set) for spellFamilyName
952 if(spellProcEvent
->spellFamilyName
&& (spellProcEvent
->spellFamilyName
!= procSpell
->SpellFamilyName
))
955 // spellFamilyName is Ok need check for spellFamilyMask if present
956 if(spellProcEvent
->spellFamilyMask
|| spellProcEvent
->spellFamilyMask2
)
958 if ((spellProcEvent
->spellFamilyMask
& procSpell
->SpellFamilyFlags
) == 0 &&
959 (spellProcEvent
->spellFamilyMask2
& procSpell
->SpellFamilyFlags2
) == 0)
961 active
= true; // Spell added manualy -> so its active spell
965 // Check for extra req (if none) and hit/crit
966 if (procEvent_procEx
== PROC_EX_NONE
)
968 // No extra req, so can trigger only for active (damage/healing present) and hit/crit
969 if((procExtra
& (PROC_EX_NORMAL_HIT
|PROC_EX_CRITICAL_HIT
)) && active
)
972 else // Passive spells hits here only if resist/reflect/immune/evade
974 // Exist req for PROC_EX_EX_TRIGGER_ALWAYS
975 if (procEvent_procEx
& PROC_EX_EX_TRIGGER_ALWAYS
)
977 // Passive spells can`t trigger if need hit
978 if ((procEvent_procEx
& PROC_EX_NORMAL_HIT
) && !active
)
980 // Check Extra Requirement like (hit/crit/miss/resist/parry/dodge/block/immune/reflect/absorb and other)
981 if (procEvent_procEx
& procExtra
)
987 void SpellMgr::LoadSpellElixirs()
989 mSpellElixirs
.clear(); // need for reload case
994 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, mask FROM spell_elixir");
1003 sLog
.outString( ">> Loaded %u spell elixir definitions", count
);
1007 barGoLink
bar( result
->GetRowCount() );
1011 Field
*fields
= result
->Fetch();
1015 uint16 entry
= fields
[0].GetUInt16();
1016 uint8 mask
= fields
[1].GetUInt8();
1018 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(entry
);
1022 sLog
.outErrorDb("Spell %u listed in `spell_elixir` does not exist", entry
);
1026 mSpellElixirs
[entry
] = mask
;
1029 } while( result
->NextRow() );
1034 sLog
.outString( ">> Loaded %u spell elixir definitions", count
);
1037 void SpellMgr::LoadSpellThreats()
1039 sSpellThreatStore
.Free(); // for reload
1041 sSpellThreatStore
.Load();
1043 sLog
.outString( ">> Loaded %u aggro generating spells", sSpellThreatStore
.RecordCount
);
1047 bool SpellMgr::IsRankSpellDueToSpell(SpellEntry
const *spellInfo_1
,uint32 spellId_2
) const
1049 SpellEntry
const *spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
1050 if(!spellInfo_1
|| !spellInfo_2
) return false;
1051 if(spellInfo_1
->Id
== spellId_2
) return false;
1053 return GetFirstSpellInChain(spellInfo_1
->Id
)==GetFirstSpellInChain(spellId_2
);
1056 bool SpellMgr::canStackSpellRanks(SpellEntry
const *spellInfo
)
1058 if(IsPassiveSpell(spellInfo
->Id
)) // ranked passive spell
1060 if(spellInfo
->powerType
!= POWER_MANA
&& spellInfo
->powerType
!= POWER_HEALTH
)
1062 if(IsProfessionOrRidingSpell(spellInfo
->Id
))
1065 if(spellmgr
.IsSkillBonusSpell(spellInfo
->Id
))
1068 // All stance spells. if any better way, change it.
1069 for (int i
= 0; i
< 3; i
++)
1071 switch(spellInfo
->SpellFamilyName
)
1073 case SPELLFAMILY_PALADIN
:
1074 // Paladin aura Spell
1075 if (spellInfo
->Effect
[i
]==SPELL_EFFECT_APPLY_AREA_AURA_RAID
)
1078 case SPELLFAMILY_DRUID
:
1080 if (spellInfo
->Effect
[i
]==SPELL_EFFECT_APPLY_AURA
&&
1081 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_MOD_SHAPESHIFT
)
1084 case SPELLFAMILY_ROGUE
:
1086 if (spellInfo
->Effect
[i
]==SPELL_EFFECT_APPLY_AURA
&&
1087 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_MOD_SHAPESHIFT
)
1094 bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1
, uint32 spellId_2
) const
1096 SpellEntry
const *spellInfo_1
= sSpellStore
.LookupEntry(spellId_1
);
1097 SpellEntry
const *spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
1099 if(!spellInfo_1
|| !spellInfo_2
)
1102 if(spellInfo_1
->Id
== spellId_2
)
1105 //I think we don't check this correctly because i need a exception for spell:
1106 //72,11327,18461...(called from 1856,1857...) Call Aura 16,31, after trigger another spell who call aura 77 and 77 remove 16 and 31, this should not happen.
1107 if(spellInfo_2
->SpellFamilyFlags
== 2048)
1110 // Resurrection sickness
1111 if((spellInfo_1
->Id
== SPELL_ID_PASSIVE_RESURRECTION_SICKNESS
) != (spellInfo_2
->Id
==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS
))
1114 // Allow stack passive and not passive spells
1115 if ((spellInfo_1
->Attributes
& SPELL_ATTR_PASSIVE
)!=(spellInfo_2
->Attributes
& SPELL_ATTR_PASSIVE
))
1118 // Specific spell family spells
1119 switch(spellInfo_1
->SpellFamilyName
)
1121 case SPELLFAMILY_GENERIC
:
1122 switch(spellInfo_2
->SpellFamilyName
)
1124 case SPELLFAMILY_GENERIC
: // same family case
1127 if( spellInfo_1
->Id
== 21992 && spellInfo_2
->Id
== 27648 || spellInfo_2
->Id
== 21992 && spellInfo_1
->Id
== 27648 )
1130 // Lightning Speed (Mongoose) and Fury of the Crashing Waves (Tsunami Talisman)
1131 if( spellInfo_1
->Id
== 28093 && spellInfo_2
->Id
== 42084 ||
1132 spellInfo_2
->Id
== 28093 && spellInfo_1
->Id
== 42084 )
1135 // Soulstone Resurrection and Twisting Nether (resurrector)
1136 if( spellInfo_1
->SpellIconID
== 92 && spellInfo_2
->SpellIconID
== 92 && (
1137 spellInfo_1
->SpellVisual
[0] == 99 && spellInfo_2
->SpellVisual
[0] == 0 ||
1138 spellInfo_2
->SpellVisual
[0] == 99 && spellInfo_1
->SpellVisual
[0] == 0 ) )
1141 // Heart of the Wild and (Primal Instinct (Idol of Terror) triggering spell or Agility)
1142 if( spellInfo_1
->SpellIconID
== 240 && spellInfo_2
->SpellIconID
== 240 && (
1143 spellInfo_1
->SpellVisual
[0] == 0 && spellInfo_2
->SpellVisual
[0] == 78 ||
1144 spellInfo_2
->SpellVisual
[0] == 0 && spellInfo_1
->SpellVisual
[0] == 78 ) )
1147 // Personalized Weather (thunder effect should overwrite rainy aura)
1148 if(spellInfo_1
->SpellIconID
== 2606 && spellInfo_2
->SpellIconID
== 2606)
1151 // Brood Affliction: Bronze
1152 if( (spellInfo_1
->Id
== 23170 && spellInfo_2
->Id
== 23171) ||
1153 (spellInfo_2
->Id
== 23170 && spellInfo_1
->Id
== 23171) )
1158 case SPELLFAMILY_WARRIOR
:
1160 // Scroll of Protection and Defensive Stance (multi-family check)
1161 if( spellInfo_1
->SpellIconID
== 276 && spellInfo_1
->SpellVisual
[0] == 196 && spellInfo_2
->Id
== 71)
1164 // Improved Hamstring -> Hamstring (multi-family check)
1165 if( (spellInfo_2
->SpellFamilyFlags
& 2) && spellInfo_1
->Id
== 23694 )
1170 case SPELLFAMILY_DRUID
:
1172 // Scroll of Stamina and Leader of the Pack (multi-family check)
1173 if( spellInfo_1
->SpellIconID
== 312 && spellInfo_1
->SpellVisual
[0] == 216 && spellInfo_2
->Id
== 24932 )
1176 // Dragonmaw Illusion (multi-family check)
1177 if (spellId_1
== 40216 && spellId_2
== 42016 )
1182 case SPELLFAMILY_ROGUE
:
1184 // Garrote-Silence -> Garrote (multi-family check)
1185 if( spellInfo_1
->SpellIconID
== 498 && spellInfo_1
->SpellVisual
[0] == 0 && spellInfo_2
->SpellIconID
== 498 )
1190 case SPELLFAMILY_HUNTER
:
1192 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1193 if( spellInfo_1
->Id
== 19410 && spellInfo_2
->Id
== 5116 )
1196 // Improved Wing Clip -> Wing Clip (multi-family check)
1197 if( (spellInfo_2
->SpellFamilyFlags
& 0x40) && spellInfo_1
->Id
== 19229 )
1201 case SPELLFAMILY_PALADIN
:
1203 // Unstable Currents and other -> *Sanctity Aura (multi-family check)
1204 if( spellInfo_2
->SpellIconID
==502 && spellInfo_1
->SpellIconID
==502 && spellInfo_1
->SpellVisual
[0]==969 )
1207 // *Band of Eternal Champion and Seal of Command(multi-family check)
1208 if( spellId_1
== 35081 && spellInfo_2
->SpellIconID
==561 && spellInfo_2
->SpellVisual
[0]==7992)
1215 case SPELLFAMILY_MAGE
:
1216 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_MAGE
)
1218 // Blizzard & Chilled (and some other stacked with blizzard spells
1219 if( (spellInfo_1
->SpellFamilyFlags
& 0x80) && (spellInfo_2
->SpellFamilyFlags
& 0x100000) ||
1220 (spellInfo_2
->SpellFamilyFlags
& 0x80) && (spellInfo_1
->SpellFamilyFlags
& 0x100000) )
1223 // Blink & Improved Blink
1224 if( (spellInfo_1
->SpellFamilyFlags
& 0x0000000000010000LL
) && (spellInfo_2
->SpellVisual
[0] == 72 && spellInfo_2
->SpellIconID
== 1499) ||
1225 (spellInfo_2
->SpellFamilyFlags
& 0x0000000000010000LL
) && (spellInfo_1
->SpellVisual
[0] == 72 && spellInfo_1
->SpellIconID
== 1499) )
1228 // Detect Invisibility and Mana Shield (multi-family check)
1229 if( spellInfo_2
->Id
== 132 && spellInfo_1
->SpellIconID
== 209 && spellInfo_1
->SpellVisual
[0] == 968 )
1232 // Combustion and Fire Protection Aura (multi-family check)
1233 if( spellInfo_1
->Id
== 11129 && spellInfo_2
->SpellIconID
== 33 && spellInfo_2
->SpellVisual
[0] == 321 )
1237 case SPELLFAMILY_WARLOCK
:
1238 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_WARLOCK
)
1240 // Siphon Life and Drain Life
1241 if( spellInfo_1
->SpellIconID
== 152 && spellInfo_2
->SpellIconID
== 546 ||
1242 spellInfo_2
->SpellIconID
== 152 && spellInfo_1
->SpellIconID
== 546 )
1245 //Corruption & Seed of corruption
1246 if( spellInfo_1
->SpellIconID
== 313 && spellInfo_2
->SpellIconID
== 1932 ||
1247 spellInfo_2
->SpellIconID
== 313 && spellInfo_1
->SpellIconID
== 1932 )
1248 if(spellInfo_1
->SpellVisual
[0] != 0 && spellInfo_2
->SpellVisual
[0] != 0)
1249 return true; // can't be stacked
1251 // Corruption and Unstable Affliction
1252 if( spellInfo_1
->SpellIconID
== 313 && spellInfo_2
->SpellIconID
== 2039 ||
1253 spellInfo_2
->SpellIconID
== 313 && spellInfo_1
->SpellIconID
== 2039 )
1256 // (Corruption or Unstable Affliction) and (Curse of Agony or Curse of Doom)
1257 if( (spellInfo_1
->SpellIconID
== 313 || spellInfo_1
->SpellIconID
== 2039) && (spellInfo_2
->SpellIconID
== 544 || spellInfo_2
->SpellIconID
== 91) ||
1258 (spellInfo_2
->SpellIconID
== 313 || spellInfo_2
->SpellIconID
== 2039) && (spellInfo_1
->SpellIconID
== 544 || spellInfo_1
->SpellIconID
== 91) )
1261 // Detect Invisibility and Mana Shield (multi-family check)
1262 if( spellInfo_1
->Id
== 132 && spellInfo_2
->SpellIconID
== 209 && spellInfo_2
->SpellVisual
[0] == 968 )
1265 case SPELLFAMILY_WARRIOR
:
1266 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_WARRIOR
)
1268 // Rend and Deep Wound
1269 if( (spellInfo_1
->SpellFamilyFlags
& 0x20) && (spellInfo_2
->SpellFamilyFlags
& 0x1000000000LL
) ||
1270 (spellInfo_2
->SpellFamilyFlags
& 0x20) && (spellInfo_1
->SpellFamilyFlags
& 0x1000000000LL
) )
1273 // Battle Shout and Rampage
1274 if( (spellInfo_1
->SpellIconID
== 456 && spellInfo_2
->SpellIconID
== 2006) ||
1275 (spellInfo_2
->SpellIconID
== 456 && spellInfo_1
->SpellIconID
== 2006) )
1279 // Hamstring -> Improved Hamstring (multi-family check)
1280 if( (spellInfo_1
->SpellFamilyFlags
& 2) && spellInfo_2
->Id
== 23694 )
1283 // Defensive Stance and Scroll of Protection (multi-family check)
1284 if( spellInfo_1
->Id
== 71 && spellInfo_2
->SpellIconID
== 276 && spellInfo_2
->SpellVisual
[0] == 196 )
1287 // Bloodlust and Bloodthirst (multi-family check)
1288 if( spellInfo_2
->Id
== 2825 && spellInfo_1
->SpellIconID
== 38 && spellInfo_1
->SpellVisual
[0] == 0 )
1292 case SPELLFAMILY_PRIEST
:
1293 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_PRIEST
)
1295 //Devouring Plague and Shadow Vulnerability
1296 if( (spellInfo_1
->SpellFamilyFlags
& 0x2000000) && (spellInfo_2
->SpellFamilyFlags
& 0x800000000LL
) ||
1297 (spellInfo_2
->SpellFamilyFlags
& 0x2000000) && (spellInfo_1
->SpellFamilyFlags
& 0x800000000LL
) )
1300 //StarShards and Shadow Word: Pain
1301 if( (spellInfo_1
->SpellFamilyFlags
& 0x200000) && (spellInfo_2
->SpellFamilyFlags
& 0x8000) ||
1302 (spellInfo_2
->SpellFamilyFlags
& 0x200000) && (spellInfo_1
->SpellFamilyFlags
& 0x8000) )
1305 if( (spellInfo_1
->Id
== 47585 && spellInfo_2
->Id
== 60069) ||
1306 (spellInfo_2
->Id
== 47585 && spellInfo_1
->Id
== 60069) )
1310 case SPELLFAMILY_DRUID
:
1311 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_DRUID
)
1313 //Omen of Clarity and Blood Frenzy
1314 if( (spellInfo_1
->SpellFamilyFlags
== 0x0 && spellInfo_1
->SpellIconID
== 108) && (spellInfo_2
->SpellFamilyFlags
& 0x20000000000000LL
) ||
1315 (spellInfo_2
->SpellFamilyFlags
== 0x0 && spellInfo_2
->SpellIconID
== 108) && (spellInfo_1
->SpellFamilyFlags
& 0x20000000000000LL
) )
1318 // Tree of Life (Shapeshift) and 34123 Tree of Life (Passive)
1319 if ((spellId_1
== 33891 && spellId_2
== 34123) ||
1320 (spellId_2
== 33891 && spellId_1
== 34123))
1323 // Wrath of Elune and Nature's Grace
1324 if( spellInfo_1
->Id
== 16886 && spellInfo_2
->Id
== 46833 || spellInfo_2
->Id
== 16886 && spellInfo_1
->Id
== 46833 )
1327 // Bear Rage (Feral T4 (2)) and Omen of Clarity
1328 if( spellInfo_1
->Id
== 16864 && spellInfo_2
->Id
== 37306 || spellInfo_2
->Id
== 16864 && spellInfo_1
->Id
== 37306 )
1331 // Cat Energy (Feral T4 (2)) and Omen of Clarity
1332 if( spellInfo_1
->Id
== 16864 && spellInfo_2
->Id
== 37311 || spellInfo_2
->Id
== 16864 && spellInfo_1
->Id
== 37311 )
1336 // Leader of the Pack and Scroll of Stamina (multi-family check)
1337 if( spellInfo_1
->Id
== 24932 && spellInfo_2
->SpellIconID
== 312 && spellInfo_2
->SpellVisual
[0] == 216 )
1340 // Dragonmaw Illusion (multi-family check)
1341 if (spellId_1
== 42016 && spellId_2
== 40216 )
1345 case SPELLFAMILY_ROGUE
:
1346 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_ROGUE
)
1348 // Master of Subtlety
1349 if (spellId_1
== 31665 && spellId_2
== 31666 || spellId_1
== 31666 && spellId_2
== 31665 )
1353 // Garrote -> Garrote-Silence (multi-family check)
1354 if( spellInfo_1
->SpellIconID
== 498 && spellInfo_2
->SpellIconID
== 498 && spellInfo_2
->SpellVisual
[0] == 0 )
1357 case SPELLFAMILY_HUNTER
:
1358 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_HUNTER
)
1360 // Rapid Fire & Quick Shots
1361 if( (spellInfo_1
->SpellFamilyFlags
& 0x20) && (spellInfo_2
->SpellFamilyFlags
& 0x20000000000LL
) ||
1362 (spellInfo_2
->SpellFamilyFlags
& 0x20) && (spellInfo_1
->SpellFamilyFlags
& 0x20000000000LL
) )
1365 // Serpent Sting & (Immolation/Explosive Trap Effect)
1366 if( (spellInfo_1
->SpellFamilyFlags
& 0x4) && (spellInfo_2
->SpellFamilyFlags
& 0x00000004000LL
) ||
1367 (spellInfo_2
->SpellFamilyFlags
& 0x4) && (spellInfo_1
->SpellFamilyFlags
& 0x00000004000LL
) )
1371 if( spellInfo_1
->SpellIconID
== 1680 && spellInfo_2
->SpellIconID
== 1680 )
1375 // Wing Clip -> Improved Wing Clip (multi-family check)
1376 if( (spellInfo_1
->SpellFamilyFlags
& 0x40) && spellInfo_2
->Id
== 19229 )
1379 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1380 if( spellInfo_2
->Id
== 19410 && spellInfo_1
->Id
== 5116 )
1383 case SPELLFAMILY_PALADIN
:
1384 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_PALADIN
)
1387 if( IsSealSpell(spellInfo_1
) && IsSealSpell(spellInfo_2
) )
1390 // Combustion and Fire Protection Aura (multi-family check)
1391 if( spellInfo_2
->Id
== 11129 && spellInfo_1
->SpellIconID
== 33 && spellInfo_1
->SpellVisual
[0] == 321 )
1394 // *Sanctity Aura -> Unstable Currents and other (multi-family check)
1395 if( spellInfo_1
->SpellIconID
==502 && spellInfo_2
->SpellFamilyName
== SPELLFAMILY_GENERIC
&& spellInfo_2
->SpellIconID
==502 && spellInfo_2
->SpellVisual
[0]==969 )
1398 // *Seal of Command and Band of Eternal Champion (multi-family check)
1399 if( spellInfo_1
->SpellIconID
==561 && spellInfo_1
->SpellVisual
[0]==7992 && spellId_2
== 35081)
1402 case SPELLFAMILY_SHAMAN
:
1403 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_SHAMAN
)
1406 if( IsElementalShield(spellInfo_1
) && IsElementalShield(spellInfo_2
) )
1410 if( spellInfo_1
->SpellIconID
==220 && spellInfo_2
->SpellIconID
==220 &&
1411 spellInfo_1
->SpellFamilyFlags
!= spellInfo_2
->SpellFamilyFlags
)
1414 // Bloodlust and Bloodthirst (multi-family check)
1415 if( spellInfo_1
->Id
== 2825 && spellInfo_2
->SpellIconID
== 38 && spellInfo_2
->SpellVisual
[0] == 0 )
1422 // more generic checks
1423 if (spellInfo_1
->SpellIconID
== spellInfo_2
->SpellIconID
&&
1424 spellInfo_1
->SpellIconID
!= 0 && spellInfo_2
->SpellIconID
!= 0)
1426 bool isModifier
= false;
1427 for (int i
= 0; i
< 3; i
++)
1429 if (spellInfo_1
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_FLAT_MODIFIER
||
1430 spellInfo_1
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_PCT_MODIFIER
||
1431 spellInfo_2
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_FLAT_MODIFIER
||
1432 spellInfo_2
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_PCT_MODIFIER
)
1440 if (IsRankSpellDueToSpell(spellInfo_1
, spellId_2
))
1443 if (spellInfo_1
->SpellFamilyName
== 0 || spellInfo_2
->SpellFamilyName
== 0)
1446 if (spellInfo_1
->SpellFamilyName
!= spellInfo_2
->SpellFamilyName
)
1449 for (int i
= 0; i
< 3; ++i
)
1450 if (spellInfo_1
->Effect
[i
] != spellInfo_2
->Effect
[i
] ||
1451 spellInfo_1
->EffectItemType
[i
] != spellInfo_2
->EffectItemType
[i
] ||
1452 spellInfo_1
->EffectMiscValue
[i
] != spellInfo_2
->EffectMiscValue
[i
] ||
1453 spellInfo_1
->EffectApplyAuraName
[i
] != spellInfo_2
->EffectApplyAuraName
[i
])
1459 bool SpellMgr::IsProfessionOrRidingSpell(uint32 spellId
)
1461 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
1465 if(spellInfo
->Effect
[1] != SPELL_EFFECT_SKILL
)
1468 uint32 skill
= spellInfo
->EffectMiscValue
[1];
1470 return IsProfessionOrRidingSkill(skill
);
1473 bool SpellMgr::IsProfessionSpell(uint32 spellId
)
1475 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
1479 if(spellInfo
->Effect
[1] != SPELL_EFFECT_SKILL
)
1482 uint32 skill
= spellInfo
->EffectMiscValue
[1];
1484 return IsProfessionSkill(skill
);
1487 bool SpellMgr::IsPrimaryProfessionSpell(uint32 spellId
)
1489 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
1493 if(spellInfo
->Effect
[1] != SPELL_EFFECT_SKILL
)
1496 uint32 skill
= spellInfo
->EffectMiscValue
[1];
1498 return IsPrimaryProfessionSkill(skill
);
1501 bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId
) const
1503 return IsPrimaryProfessionSpell(spellId
) && GetSpellRank(spellId
)==1;
1506 bool SpellMgr::IsSkillBonusSpell(uint32 spellId
) const
1508 SkillLineAbilityMap::const_iterator lower
= GetBeginSkillLineAbilityMap(spellId
);
1509 SkillLineAbilityMap::const_iterator upper
= GetEndSkillLineAbilityMap(spellId
);
1511 for(SkillLineAbilityMap::const_iterator _spell_idx
= lower
; _spell_idx
!= upper
; ++_spell_idx
)
1513 SkillLineAbilityEntry
const *pAbility
= _spell_idx
->second
;
1514 if (!pAbility
|| pAbility
->learnOnGetSkill
!= ABILITY_LEARNED_ON_GET_PROFESSION_SKILL
)
1517 if(pAbility
->req_skill_value
> 0)
1524 SpellEntry
const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry
const* spellInfo
, uint32 playerLevel
) const
1526 // ignore passive spells
1527 if(IsPassiveSpell(spellInfo
->Id
))
1530 bool needRankSelection
= false;
1531 for(int i
=0;i
<3;i
++)
1533 if( IsPositiveEffect(spellInfo
->Id
, i
) && (
1534 spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AURA
||
1535 spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY
||
1536 spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AREA_AURA_RAID
1539 needRankSelection
= true;
1545 if(!needRankSelection
)
1548 for(uint32 nextSpellId
= spellInfo
->Id
; nextSpellId
!= 0; nextSpellId
= GetPrevSpellInChain(nextSpellId
))
1550 SpellEntry
const *nextSpellInfo
= sSpellStore
.LookupEntry(nextSpellId
);
1554 // if found appropriate level
1555 if(playerLevel
+ 10 >= nextSpellInfo
->spellLevel
)
1556 return nextSpellInfo
;
1558 // one rank less then
1565 void SpellMgr::LoadSpellChains()
1567 mSpellChains
.clear(); // need for reload case
1568 mSpellChainsNext
.clear(); // need for reload case
1570 QueryResult
*result
= WorldDatabase
.Query("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain");
1577 sLog
.outString( ">> Loaded 0 spell chain records" );
1578 sLog
.outErrorDb("`spell_chains` table is empty!");
1584 barGoLink
bar( result
->GetRowCount() );
1588 Field
*fields
= result
->Fetch();
1590 uint32 spell_id
= fields
[0].GetUInt32();
1592 SpellChainNode node
;
1593 node
.prev
= fields
[1].GetUInt32();
1594 node
.first
= fields
[2].GetUInt32();
1595 node
.rank
= fields
[3].GetUInt8();
1596 node
.req
= fields
[4].GetUInt32();
1598 if(!sSpellStore
.LookupEntry(spell_id
))
1600 sLog
.outErrorDb("Spell %u listed in `spell_chain` does not exist",spell_id
);
1604 if(node
.prev
!=0 && !sSpellStore
.LookupEntry(node
.prev
))
1606 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existed previous rank spell.",
1607 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1611 if(!sSpellStore
.LookupEntry(node
.first
))
1613 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing first rank spell.",
1614 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1618 // check basic spell chain data integrity (note: rank can be equal 0 or 1 for first/single spell)
1619 if( (spell_id
== node
.first
) != (node
.rank
<= 1) ||
1620 (spell_id
== node
.first
) != (node
.prev
== 0) ||
1621 (node
.rank
<= 1) != (node
.prev
== 0) )
1623 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not compatible chain data.",
1624 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1628 if(node
.req
!=0 && !sSpellStore
.LookupEntry(node
.req
))
1630 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing required spell.",
1631 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1635 // talents not required data in spell chain for work, but must be checked if present for intergrity
1636 if(TalentSpellPos
const* pos
= GetTalentSpellPos(spell_id
))
1638 if(node
.rank
!=pos
->rank
+1)
1640 sLog
.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong rank.",
1641 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1645 if(TalentEntry
const* talentEntry
= sTalentStore
.LookupEntry(pos
->talent_id
))
1647 if(node
.first
!=talentEntry
->RankID
[0])
1649 sLog
.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong first rank spell.",
1650 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1654 if(node
.rank
> 1 && node
.prev
!= talentEntry
->RankID
[node
.rank
-1-1])
1656 sLog
.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong prev rank spell.",
1657 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1661 /*if(node.req!=talentEntry->DependsOnSpell)
1663 sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong required spell.",
1664 spell_id,node.prev,node.first,node.rank,node.req);
1670 mSpellChains
[spell_id
] = node
;
1673 mSpellChainsNext
.insert(SpellChainMapNext::value_type(node
.prev
,spell_id
));
1676 mSpellChainsNext
.insert(SpellChainMapNext::value_type(node
.req
,spell_id
));
1679 } while( result
->NextRow() );
1683 // additional integrity checks
1684 for(SpellChainMap::iterator i
= mSpellChains
.begin(); i
!= mSpellChains
.end(); ++i
)
1688 SpellChainMap::iterator i_prev
= mSpellChains
.find(i
->second
.prev
);
1689 if(i_prev
== mSpellChains
.end())
1691 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found previous rank spell in table.",
1692 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
);
1694 else if( i_prev
->second
.first
!= i
->second
.first
)
1696 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has different first spell in chain compared to previous rank spell (prev: %u, first: %u, rank: %d, req: %u).",
1697 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1698 i_prev
->second
.prev
,i_prev
->second
.first
,i_prev
->second
.rank
,i_prev
->second
.req
);
1700 else if( i_prev
->second
.rank
+1 != i
->second
.rank
)
1702 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has different rank compared to previous rank spell (prev: %u, first: %u, rank: %d, req: %u).",
1703 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1704 i_prev
->second
.prev
,i_prev
->second
.first
,i_prev
->second
.rank
,i_prev
->second
.req
);
1710 SpellChainMap::iterator i_req
= mSpellChains
.find(i
->second
.req
);
1711 if(i_req
== mSpellChains
.end())
1713 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found required rank spell in table.",
1714 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
);
1716 else if( i_req
->second
.first
== i
->second
.first
)
1718 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has required rank spell from same spell chain (prev: %u, first: %u, rank: %d, req: %u).",
1719 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1720 i_req
->second
.prev
,i_req
->second
.first
,i_req
->second
.rank
,i_req
->second
.req
);
1722 else if( i_req
->second
.req
)
1724 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has required rank spell with required spell (prev: %u, first: %u, rank: %d, req: %u).",
1725 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1726 i_req
->second
.prev
,i_req
->second
.first
,i_req
->second
.rank
,i_req
->second
.req
);
1732 sLog
.outString( ">> Loaded %u spell chain records", count
);
1735 void SpellMgr::LoadSpellLearnSkills()
1737 mSpellLearnSkills
.clear(); // need for reload case
1739 // search auto-learned skills and add its to map also for use in unlearn spells/talents
1740 uint32 dbc_count
= 0;
1741 barGoLink
bar( sSpellStore
.GetNumRows() );
1742 for(uint32 spell
= 0; spell
< sSpellStore
.GetNumRows(); ++spell
)
1745 SpellEntry
const* entry
= sSpellStore
.LookupEntry(spell
);
1750 for(int i
= 0; i
< 3; ++i
)
1752 if(entry
->Effect
[i
]==SPELL_EFFECT_SKILL
)
1754 SpellLearnSkillNode dbc_node
;
1755 dbc_node
.skill
= entry
->EffectMiscValue
[i
];
1756 if ( dbc_node
.skill
!= SKILL_RIDING
)
1759 dbc_node
.value
= (entry
->EffectBasePoints
[i
]+1)*75;
1760 dbc_node
.maxvalue
= (entry
->EffectBasePoints
[i
]+1)*75;
1762 mSpellLearnSkills
[spell
] = dbc_node
;
1770 sLog
.outString( ">> Loaded %u Spell Learn Skills from DBC", dbc_count
);
1773 void SpellMgr::LoadSpellLearnSpells()
1775 mSpellLearnSpells
.clear(); // need for reload case
1778 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, SpellID, Active FROM spell_learn_spell");
1785 sLog
.outString( ">> Loaded 0 spell learn spells" );
1786 sLog
.outErrorDb("`spell_learn_spell` table is empty!");
1792 barGoLink
bar( result
->GetRowCount() );
1796 Field
*fields
= result
->Fetch();
1798 uint32 spell_id
= fields
[0].GetUInt32();
1800 SpellLearnSpellNode node
;
1801 node
.spell
= fields
[1].GetUInt32();
1802 node
.active
= fields
[2].GetBool();
1803 node
.autoLearned
= false;
1805 if(!sSpellStore
.LookupEntry(spell_id
))
1807 sLog
.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",spell_id
);
1811 if(!sSpellStore
.LookupEntry(node
.spell
))
1813 sLog
.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",node
.spell
);
1817 mSpellLearnSpells
.insert(SpellLearnSpellMap::value_type(spell_id
,node
));
1820 } while( result
->NextRow() );
1824 // search auto-learned spells and add its to map also for use in unlearn spells/talents
1825 uint32 dbc_count
= 0;
1826 for(uint32 spell
= 0; spell
< sSpellStore
.GetNumRows(); ++spell
)
1828 SpellEntry
const* entry
= sSpellStore
.LookupEntry(spell
);
1833 for(int i
= 0; i
< 3; ++i
)
1835 if(entry
->Effect
[i
]==SPELL_EFFECT_LEARN_SPELL
)
1837 SpellLearnSpellNode dbc_node
;
1838 dbc_node
.spell
= entry
->EffectTriggerSpell
[i
];
1839 dbc_node
.active
= true; // all dbc based learned spells is active (show in spell book or hide by client itself)
1841 // ignore learning not existed spells (broken/outdated/or generic learnig spell 483
1842 if(!sSpellStore
.LookupEntry(dbc_node
.spell
))
1845 // talent or passive spells or skill-step spells auto-casted and not need dependent learning,
1846 // pet teaching spells don't must be dependent learning (casted)
1847 // other required explicit dependent learning
1848 dbc_node
.autoLearned
= entry
->EffectImplicitTargetA
[i
]==TARGET_PET
|| GetTalentSpellCost(spell
) > 0 || IsPassiveSpell(spell
) || IsSpellHaveEffect(entry
,SPELL_EFFECT_SKILL_STEP
);
1850 SpellLearnSpellMap::const_iterator db_node_begin
= GetBeginSpellLearnSpell(spell
);
1851 SpellLearnSpellMap::const_iterator db_node_end
= GetEndSpellLearnSpell(spell
);
1854 for(SpellLearnSpellMap::const_iterator itr
= db_node_begin
; itr
!= db_node_end
; ++itr
)
1856 if(itr
->second
.spell
== dbc_node
.spell
)
1858 sLog
.outErrorDb("Spell %u auto-learn spell %u in spell.dbc then the record in `spell_learn_spell` is redundant, please fix DB.",
1859 spell
,dbc_node
.spell
);
1865 if(!found
) // add new spell-spell pair if not found
1867 mSpellLearnSpells
.insert(SpellLearnSpellMap::value_type(spell
,dbc_node
));
1875 sLog
.outString( ">> Loaded %u spell learn spells + %u found in DBC", count
, dbc_count
);
1878 void SpellMgr::LoadSpellScriptTarget()
1880 mSpellScriptTarget
.clear(); // need for reload case
1884 QueryResult
*result
= WorldDatabase
.Query("SELECT entry,type,targetEntry FROM spell_script_target");
1893 sLog
.outErrorDb(">> Loaded 0 SpellScriptTarget. DB table `spell_script_target` is empty.");
1897 barGoLink
bar(result
->GetRowCount());
1901 Field
*fields
= result
->Fetch();
1904 uint32 spellId
= fields
[0].GetUInt32();
1905 uint32 type
= fields
[1].GetUInt32();
1906 uint32 targetEntry
= fields
[2].GetUInt32();
1908 SpellEntry
const* spellProto
= sSpellStore
.LookupEntry(spellId
);
1912 sLog
.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not exist.",spellId
,targetEntry
);
1916 bool targetfound
= false;
1917 for(int i
= 0; i
<3; ++i
)
1919 if( spellProto
->EffectImplicitTargetA
[i
]==TARGET_SCRIPT
||
1920 spellProto
->EffectImplicitTargetB
[i
]==TARGET_SCRIPT
||
1921 spellProto
->EffectImplicitTargetA
[i
]==TARGET_SCRIPT_COORDINATES
||
1922 spellProto
->EffectImplicitTargetB
[i
]==TARGET_SCRIPT_COORDINATES
)
1930 sLog
.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_SCRIPT(38) or TARGET_SCRIPT_COORDINATES (46).",spellId
,targetEntry
);
1934 if( type
>= MAX_SPELL_TARGET_TYPE
)
1936 sLog
.outErrorDb("Table `spell_script_target`: target type %u for TargetEntry %u is incorrect.",type
,targetEntry
);
1942 case SPELL_TARGET_TYPE_GAMEOBJECT
:
1944 if( targetEntry
==0 )
1947 if(!sGOStorage
.LookupEntry
<GameObjectInfo
>(targetEntry
))
1949 sLog
.outErrorDb("Table `spell_script_target`: gameobject template entry %u does not exist.",targetEntry
);
1956 if( targetEntry
==0 )
1958 sLog
.outErrorDb("Table `spell_script_target`: target entry == 0 for not GO target type (%u).",type
);
1961 if(!sCreatureStorage
.LookupEntry
<CreatureInfo
>(targetEntry
))
1963 sLog
.outErrorDb("Table `spell_script_target`: creature template entry %u does not exist.",targetEntry
);
1966 const CreatureInfo
* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(targetEntry
);
1968 if(spellId
== 30427 && !cInfo
->SkinLootId
)
1970 sLog
.outErrorDb("Table `spell_script_target` has creature %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!", cInfo
->Entry
);
1977 mSpellScriptTarget
.insert(SpellScriptTarget::value_type(spellId
,SpellTargetEntry(SpellTargetType(type
),targetEntry
)));
1980 } while (result
->NextRow());
1985 /* Disabled (lot errors at this moment)
1986 for(uint32 i = 1; i < sSpellStore.nCount; ++i)
1988 SpellEntry const * spellInfo = sSpellStore.LookupEntry(i);
1993 for(int j=0; j<3; ++j)
1995 if( spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || spellInfo->EffectImplicitTargetA[j] != TARGET_SELF && spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT )
1997 SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(spellInfo->Id);
1998 SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(spellInfo->Id);
2001 sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = %u (TARGET_SCRIPT), but does not have record in `spell_script_target`",spellInfo->Id,TARGET_SCRIPT);
2002 break; // effects of spell
2010 sLog
.outString(">> Loaded %u Spell Script Targets", count
);
2013 void SpellMgr::LoadSpellPetAuras()
2015 mSpellPetAuraMap
.clear(); // need for reload case
2020 QueryResult
*result
= WorldDatabase
.Query("SELECT spell, pet, aura FROM spell_pet_auras");
2029 sLog
.outString( ">> Loaded %u spell pet auras", count
);
2033 barGoLink
bar( result
->GetRowCount() );
2037 Field
*fields
= result
->Fetch();
2041 uint16 spell
= fields
[0].GetUInt16();
2042 uint16 pet
= fields
[1].GetUInt16();
2043 uint16 aura
= fields
[2].GetUInt16();
2045 SpellPetAuraMap::iterator itr
= mSpellPetAuraMap
.find(spell
);
2046 if(itr
!= mSpellPetAuraMap
.end())
2048 itr
->second
.AddAura(pet
, aura
);
2052 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell
);
2055 sLog
.outErrorDb("Spell %u listed in `spell_pet_auras` does not exist", spell
);
2060 if((spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AURA
&&
2061 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_DUMMY
) ||
2062 spellInfo
->Effect
[i
] == SPELL_EFFECT_DUMMY
)
2067 sLog
.outError("Spell %u listed in `spell_pet_auras` does not have dummy aura or dummy effect", spell
);
2071 SpellEntry
const* spellInfo2
= sSpellStore
.LookupEntry(aura
);
2074 sLog
.outErrorDb("Aura %u listed in `spell_pet_auras` does not exist", aura
);
2078 PetAura
pa(pet
, aura
, spellInfo
->EffectImplicitTargetA
[i
] == TARGET_PET
, spellInfo
->EffectBasePoints
[i
] + spellInfo
->EffectBaseDice
[i
]);
2079 mSpellPetAuraMap
[spell
] = pa
;
2083 } while( result
->NextRow() );
2088 sLog
.outString( ">> Loaded %u spell pet auras", count
);
2091 void SpellMgr::LoadPetLevelupSpellMap()
2093 CreatureFamilyEntry
const *creatureFamily
;
2094 SpellEntry
const *spell
;
2097 for (uint32 i
= 0; i
< sCreatureFamilyStore
.GetNumRows(); ++i
)
2099 creatureFamily
= sCreatureFamilyStore
.LookupEntry(i
);
2101 if(!creatureFamily
) // not exist
2104 if(creatureFamily
->petTalentType
< 0) // not hunter pet family
2107 for(uint32 j
= 0; j
< sSpellStore
.GetNumRows(); ++j
)
2109 spell
= sSpellStore
.LookupEntry(j
);
2116 if(spell
->SpellFamilyName
!= SPELLFAMILY_HUNTER
)
2120 if(!(spell
->SpellFamilyFlags
& 0x1000000000000000LL
))
2123 // not Growl or Cower (generics)
2124 if(spell
->SpellIconID
!= 201 && spell
->SpellIconID
!= 958)
2126 switch(creatureFamily
->ID
)
2128 case CREATURE_FAMILY_BAT
: // Bite and Sonic Blast
2129 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1577)
2132 case CREATURE_FAMILY_BEAR
: // Claw and Swipe
2133 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 1562)
2136 case CREATURE_FAMILY_BIRD_OF_PREY
: // Claw and Snatch
2137 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 168)
2140 case CREATURE_FAMILY_BOAR
: // Bite and Gore
2141 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1578)
2144 case CREATURE_FAMILY_CARRION_BIRD
: // Bite and Demoralizing Screech
2145 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1579)
2148 case CREATURE_FAMILY_CAT
: // Claw and Prowl and Rake
2149 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 495 && spell
->SpellIconID
!= 494)
2152 case CREATURE_FAMILY_CHIMAERA
: // Bite and Froststorm Breath
2153 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 62)
2156 case CREATURE_FAMILY_CORE_HOUND
: // Bite and Lava Breath
2157 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1197)
2160 case CREATURE_FAMILY_CRAB
: // Claw and Pin
2161 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 2679)
2164 case CREATURE_FAMILY_CROCOLISK
: // Bite and Bad Attitude
2165 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1581)
2168 case CREATURE_FAMILY_DEVILSAUR
: // Bite and Monstrous Bite
2169 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 599)
2172 case CREATURE_FAMILY_DRAGONHAWK
: // Bite and Fire Breath
2173 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 2128)
2176 case CREATURE_FAMILY_GORILLA
: // Smack and Thunderstomp
2177 if(spell
->SpellIconID
!= 473 && spell
->SpellIconID
!= 148)
2180 case CREATURE_FAMILY_HYENA
: // Bite and Tendon Rip
2181 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 138)
2184 case CREATURE_FAMILY_MOTH
: // Serenity Dust and Smack
2185 if(spell
->SpellIconID
!= 1714 && spell
->SpellIconID
!= 473)
2188 case CREATURE_FAMILY_NETHER_RAY
: // Bite and Nether Shock
2189 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 2027)
2192 case CREATURE_FAMILY_RAPTOR
: // Claw and Savage Rend
2193 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 245)
2196 case CREATURE_FAMILY_RAVAGER
: // Bite and Ravage
2197 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 2253)
2200 case CREATURE_FAMILY_RHINO
: // Smack and Stampede
2201 if(spell
->SpellIconID
!= 473 && spell
->SpellIconID
!= 3066)
2204 case CREATURE_FAMILY_SCORPID
: // Claw and Scorpid Poison
2205 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 163)
2208 case CREATURE_FAMILY_SERPENT
: // Bite and Poison Spit
2209 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 68)
2212 case CREATURE_FAMILY_SILITHID
: // Claw and Venom Web Spray
2213 if(spell
->SpellIconID
!= 262 && (spell
->SpellIconID
!= 272 && spell
->SpellVisual
[0] != 12013))
2216 case CREATURE_FAMILY_SPIDER
: // Bite and Web
2217 if(spell
->SpellIconID
!= 1680 && (spell
->SpellIconID
!= 272 && spell
->SpellVisual
[0] != 684))
2220 case CREATURE_FAMILY_SPIRIT_BEAST
: // Claw and Prowl and Spirit Strike
2221 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 495 && spell
->SpellIconID
!= 255)
2224 case CREATURE_FAMILY_SPOREBAT
: // Smack and Spore Cloud
2225 if(spell
->SpellIconID
!= 473 && spell
->SpellIconID
!= 2681)
2228 case CREATURE_FAMILY_TALLSTRIDER
: // Claw and Dust Cloud
2229 if(spell
->SpellIconID
!= 262 && (spell
->SpellIconID
!= 157 && !(spell
->Attributes
& 0x4000000)))
2232 case CREATURE_FAMILY_TURTLE
: // Bite and Shell Shield
2233 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1588)
2236 case CREATURE_FAMILY_WARP_STALKER
: // Bite and Warp
2237 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1952)
2240 case CREATURE_FAMILY_WASP
: // Smack and Sting
2241 if(spell
->SpellIconID
!= 473 && spell
->SpellIconID
!= 110)
2244 case CREATURE_FAMILY_WIND_SERPENT
: // Bite and Lightning Breath
2245 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 62)
2248 case CREATURE_FAMILY_WOLF
: // Bite and Furious Howl
2249 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1573)
2252 case CREATURE_FAMILY_WORM
: // Acid Spit and Bite
2253 if(spell
->SpellIconID
!= 636 && spell
->SpellIconID
!= 1680)
2257 sLog
.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily
->ID
);
2262 mPetLevelupSpellMap
[creatureFamily
->ID
][spell
->spellLevel
] = spell
->Id
;
2268 sLog
.outString( ">> Loaded %u pet levelup spells", count
);
2271 /// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc
2272 bool SpellMgr::IsSpellValid(SpellEntry
const* spellInfo
, Player
* pl
, bool msg
)
2278 bool need_check_reagents
= false;
2281 for(int i
=0; i
<3; ++i
)
2283 switch(spellInfo
->Effect
[i
])
2288 // craft spell for crafting non-existed item (break client recipes list show)
2289 case SPELL_EFFECT_CREATE_ITEM
:
2291 if(!ObjectMgr::GetItemPrototype( spellInfo
->EffectItemType
[i
] ))
2296 ChatHandler(pl
).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->EffectItemType
[i
]);
2298 sLog
.outErrorDb("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->EffectItemType
[i
]);
2303 need_check_reagents
= true;
2306 case SPELL_EFFECT_LEARN_SPELL
:
2308 SpellEntry
const* spellInfo2
= sSpellStore
.LookupEntry(spellInfo
->EffectTriggerSpell
[i
]);
2309 if( !IsSpellValid(spellInfo2
,pl
,msg
) )
2314 ChatHandler(pl
).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo
->Id
,spellInfo
->EffectTriggerSpell
[i
]);
2316 sLog
.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo
->Id
,spellInfo
->EffectTriggerSpell
[i
]);
2325 if(need_check_reagents
)
2327 for(int j
= 0; j
< 8; ++j
)
2329 if(spellInfo
->Reagent
[j
] > 0 && !ObjectMgr::GetItemPrototype( spellInfo
->Reagent
[j
] ))
2334 ChatHandler(pl
).PSendSysMessage("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->Reagent
[j
]);
2336 sLog
.outErrorDb("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->Reagent
[j
]);
2346 uint8
GetSpellAllowedInLocationError(SpellEntry
const *spellInfo
,uint32 map_id
,uint32 zone_id
,uint32 area_id
, uint32 bgInstanceId
)
2349 if( spellInfo
->AreaGroupId
> 0)
2353 AreaGroupEntry
const* groupEntry
= sAreaGroupStore
.LookupEntry(spellInfo
->AreaGroupId
);
2356 for (uint8 i
=0; i
<7; i
++)
2357 if( groupEntry
->AreaId
[i
] == zone_id
|| groupEntry
->AreaId
[i
] == area_id
)
2362 return SPELL_FAILED_INCORRECT_AREA
;
2365 // elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup)
2366 if(spellInfo
->SpellFamilyName
==SPELLFAMILY_POTION
)
2368 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spellInfo
->Id
))
2370 if(mask
& ELIXIR_BATTLE_MASK
)
2372 if(spellInfo
->Id
==45373) // Bloodberry Elixir
2373 return zone_id
==4075 ? 0 : SPELL_FAILED_REQUIRES_AREA
;
2375 if(mask
& ELIXIR_UNSTABLE_MASK
)
2377 // in the Blade's Edge Mountains Plateaus and Gruul's Lair.
2378 return zone_id
==3522 || map_id
==565 ? 0 : SPELL_FAILED_INCORRECT_AREA
;
2380 if(mask
& ELIXIR_SHATTRATH_MASK
)
2382 // in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple, Sunwell Plateau
2383 if(zone_id
==3607 || map_id
==534 || map_id
==564 || zone_id
==4075)
2386 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2388 return SPELL_FAILED_INCORRECT_AREA
;
2390 return mapEntry
->multimap_id
==206 ? 0 : SPELL_FAILED_INCORRECT_AREA
;
2393 // elixirs not have another limitations
2398 // special cases zone check (maps checked by multimap common id)
2399 switch(spellInfo
->Id
)
2401 case 41618: // Bottled Nethergon Energy
2402 case 41620: // Bottled Nethergon Vapor
2404 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2406 return SPELL_FAILED_INCORRECT_AREA
;
2408 return mapEntry
->multimap_id
==206 ? 0 : SPELL_FAILED_REQUIRES_AREA
;
2410 case 41617: // Cenarion Mana Salve
2411 case 41619: // Cenarion Healing Salve
2413 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2415 return SPELL_FAILED_INCORRECT_AREA
;
2417 return mapEntry
->multimap_id
==207 ? 0 : SPELL_FAILED_REQUIRES_AREA
;
2419 case 40216: // Dragonmaw Illusion
2420 case 42016: // Dragonmaw Illusion
2421 return area_id
== 3759 || area_id
== 3966 || area_id
== 3939 ? 0 : SPELL_FAILED_INCORRECT_AREA
;
2422 case 51721: // Dominion Over Acherus
2423 case 54055: // Dominion Over Acherus
2424 return area_id
== 4281 || area_id
== 4342 ? 0 : SPELL_FAILED_INCORRECT_AREA
;
2425 case 51852: // The Eye of Acherus
2426 return map_id
== 609 ? 0 : SPELL_FAILED_REQUIRES_AREA
;
2427 case 54119: // Mist of the Kvaldir
2428 return area_id
== 4028 || area_id
== 4029 || area_id
== 4106 || area_id
== 4031 ? 0 : SPELL_FAILED_INCORRECT_AREA
;
2429 case 23333: // Warsong Flag
2430 case 23335: // Silverwing Flag
2431 return map_id
== 489 && bgInstanceId
? 0 : SPELL_FAILED_REQUIRES_AREA
;
2432 case 34976: // Netherstorm Flag
2433 return map_id
== 566 && bgInstanceId
? 0 : SPELL_FAILED_REQUIRES_AREA
;
2434 case 2584: // Waiting to Resurrect
2435 case 22011: // Spirit Heal Channel
2436 case 22012: // Spirit Heal
2437 case 24171: // Resurrection Impact Visual
2438 case 42792: // Recently Dropped Flag
2439 case 43681: // Inactive
2440 case 44535: // Spirit Heal (mana)
2442 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2444 return SPELL_FAILED_INCORRECT_AREA
;
2446 return mapEntry
->IsBattleGround() && bgInstanceId
? 0 : SPELL_FAILED_REQUIRES_AREA
;
2448 case 44521: // Preparation
2451 return SPELL_FAILED_REQUIRES_AREA
;
2453 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2455 return SPELL_FAILED_INCORRECT_AREA
;
2457 if(!mapEntry
->IsBattleGround())
2458 return SPELL_FAILED_REQUIRES_AREA
;
2460 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGround(bgInstanceId
);
2461 return bg
&& bg
->GetStatus()==STATUS_WAIT_JOIN
? 0 : SPELL_FAILED_REQUIRES_AREA
;
2463 case 32724: // Gold Team (Alliance)
2464 case 32725: // Green Team (Alliance)
2465 case 35774: // Gold Team (Horde)
2466 case 35775: // Green Team (Horde)
2468 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2470 return SPELL_FAILED_INCORRECT_AREA
;
2472 return mapEntry
->IsBattleArena() && bgInstanceId
? 0 : SPELL_FAILED_REQUIRES_AREA
;
2474 case 32727: // Arena Preparation
2477 return SPELL_FAILED_REQUIRES_AREA
;
2479 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2481 return SPELL_FAILED_INCORRECT_AREA
;
2483 if(!mapEntry
->IsBattleArena())
2484 return SPELL_FAILED_REQUIRES_AREA
;
2486 BattleGround
* bg
= sBattleGroundMgr
.GetBattleGround(bgInstanceId
);
2487 return bg
&& bg
->GetStatus()==STATUS_WAIT_JOIN
? 0 : SPELL_FAILED_REQUIRES_AREA
;
2494 void SpellMgr::LoadSkillLineAbilityMap()
2496 mSkillLineAbilityMap
.clear();
2498 barGoLink
bar( sSkillLineAbilityStore
.GetNumRows() );
2501 for (uint32 i
= 0; i
< sSkillLineAbilityStore
.GetNumRows(); i
++)
2504 SkillLineAbilityEntry
const *SkillInfo
= sSkillLineAbilityStore
.LookupEntry(i
);
2508 mSkillLineAbilityMap
.insert(SkillLineAbilityMap::value_type(SkillInfo
->spellId
,SkillInfo
));
2513 sLog
.outString(">> Loaded %u SkillLineAbility MultiMap Data", count
);
2516 DiminishingGroup
GetDiminishingReturnsGroupForSpell(SpellEntry
const* spellproto
, bool triggered
)
2518 // Explicit Diminishing Groups
2519 switch(spellproto
->SpellFamilyName
)
2521 case SPELLFAMILY_ROGUE
:
2524 if (spellproto
->SpellFamilyFlags
& 0x00000200000LL
)
2525 return DIMINISHING_KIDNEYSHOT
;
2527 else if (spellproto
->SpellFamilyFlags
& 0x00001000000LL
)
2528 return DIMINISHING_BLIND_CYCLONE
;
2531 case SPELLFAMILY_WARLOCK
:
2534 if (spellproto
->SpellFamilyFlags
& 0x40840000000LL
)
2535 return DIMINISHING_WARLOCK_FEAR
;
2537 else if (spellproto
->SpellFamilyFlags
& 0x00080000000LL
)
2538 return DIMINISHING_LIMITONLY
;
2541 case SPELLFAMILY_DRUID
:
2544 if (spellproto
->SpellFamilyFlags
& 0x02000000000LL
)
2545 return DIMINISHING_BLIND_CYCLONE
;
2548 case SPELLFAMILY_WARRIOR
:
2550 // Hamstring - limit duration to 10s in PvP
2551 if (spellproto
->SpellFamilyFlags
& 0x00000000002LL
)
2552 return DIMINISHING_LIMITONLY
;
2560 uint32 mechanic
= GetAllSpellMechanicMask(spellproto
);
2561 if (mechanic
== MECHANIC_NONE
) return DIMINISHING_NONE
;
2562 if (mechanic
& (1<<MECHANIC_STUN
)) return triggered
? DIMINISHING_TRIGGER_STUN
: DIMINISHING_CONTROL_STUN
;
2563 if (mechanic
& (1<<MECHANIC_SLEEP
)) return DIMINISHING_SLEEP
;
2564 if (mechanic
& (1<<MECHANIC_POLYMORPH
)) return DIMINISHING_POLYMORPH
;
2565 if (mechanic
& (1<<MECHANIC_ROOT
)) return triggered
? DIMINISHING_TRIGGER_ROOT
: DIMINISHING_CONTROL_ROOT
;
2566 if (mechanic
& (1<<MECHANIC_FEAR
)) return DIMINISHING_FEAR
;
2567 if (mechanic
& (1<<MECHANIC_CHARM
)) return DIMINISHING_CHARM
;
2568 if (mechanic
& (1<<MECHANIC_SILENCE
)) return DIMINISHING_SILENCE
;
2569 if (mechanic
& (1<<DIMINISHING_DISARM
)) return DIMINISHING_DISARM
;
2570 if (mechanic
& (1<<MECHANIC_FREEZE
)) return DIMINISHING_FREEZE
;
2571 if (mechanic
& ((1<<MECHANIC_KNOCKOUT
) | (1<<MECHANIC_SAPPED
))) return DIMINISHING_KNOCKOUT
;
2572 if (mechanic
& (1<<MECHANIC_BANISH
)) return DIMINISHING_BANISH
;
2573 if (mechanic
& (1<<MECHANIC_HORROR
)) return DIMINISHING_DEATHCOIL
;
2576 return DIMINISHING_NONE
;
2579 bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group
)
2583 case DIMINISHING_CONTROL_STUN
:
2584 case DIMINISHING_TRIGGER_STUN
:
2585 case DIMINISHING_KIDNEYSHOT
:
2586 case DIMINISHING_SLEEP
:
2587 case DIMINISHING_CONTROL_ROOT
:
2588 case DIMINISHING_TRIGGER_ROOT
:
2589 case DIMINISHING_FEAR
:
2590 case DIMINISHING_WARLOCK_FEAR
:
2591 case DIMINISHING_CHARM
:
2592 case DIMINISHING_POLYMORPH
:
2593 case DIMINISHING_FREEZE
:
2594 case DIMINISHING_KNOCKOUT
:
2595 case DIMINISHING_BLIND_CYCLONE
:
2596 case DIMINISHING_BANISH
:
2597 case DIMINISHING_LIMITONLY
:
2603 DiminishingReturnsType
GetDiminishingReturnsGroupType(DiminishingGroup group
)
2607 case DIMINISHING_BLIND_CYCLONE
:
2608 case DIMINISHING_CONTROL_STUN
:
2609 case DIMINISHING_TRIGGER_STUN
:
2610 case DIMINISHING_KIDNEYSHOT
:
2612 case DIMINISHING_SLEEP
:
2613 case DIMINISHING_CONTROL_ROOT
:
2614 case DIMINISHING_TRIGGER_ROOT
:
2615 case DIMINISHING_FEAR
:
2616 case DIMINISHING_CHARM
:
2617 case DIMINISHING_POLYMORPH
:
2618 case DIMINISHING_SILENCE
:
2619 case DIMINISHING_DISARM
:
2620 case DIMINISHING_DEATHCOIL
:
2621 case DIMINISHING_FREEZE
:
2622 case DIMINISHING_BANISH
:
2623 case DIMINISHING_WARLOCK_FEAR
:
2624 case DIMINISHING_KNOCKOUT
:
2625 return DRTYPE_PLAYER
;