2 * Copyright (C) 2005-2008 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"
36 SpellMgr
& SpellMgr::Instance()
38 static SpellMgr spellMgr
;
42 int32
GetSpellDuration(SpellEntry
const *spellInfo
)
46 SpellDurationEntry
const *du
= sSpellDurationStore
.LookupEntry(spellInfo
->DurationIndex
);
49 return (du
->Duration
[0] == -1) ? -1 : abs(du
->Duration
[0]);
52 int32
GetSpellMaxDuration(SpellEntry
const *spellInfo
)
56 SpellDurationEntry
const *du
= sSpellDurationStore
.LookupEntry(spellInfo
->DurationIndex
);
59 return (du
->Duration
[2] == -1) ? -1 : abs(du
->Duration
[2]);
62 uint32
GetSpellCastTime(SpellEntry
const* spellInfo
, Spell
const* spell
)
64 SpellCastTimesEntry
const *spellCastTimeEntry
= sSpellCastTimesStore
.LookupEntry(spellInfo
->CastingTimeIndex
);
66 // not all spells have cast time index and this is all is pasiive abilities
67 if(!spellCastTimeEntry
)
70 int32 castTime
= spellCastTimeEntry
->CastTime
;
74 if(Player
* modOwner
= spell
->GetCaster()->GetSpellModOwner())
75 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_CASTING_TIME
, castTime
, spell
);
77 if( !(spellInfo
->Attributes
& (SPELL_ATTR_UNK4
|SPELL_ATTR_UNK5
)) )
78 castTime
= int32(castTime
* spell
->GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED
));
81 if (spell
->IsRangedSpell() && !spell
->IsAutoRepeat())
82 castTime
= int32(castTime
* spell
->GetCaster()->m_modAttackSpeedPct
[RANGED_ATTACK
]);
86 if (spellInfo
->Attributes
& SPELL_ATTR_RANGED
&& (!spell
|| !(spell
->IsAutoRepeat())))
89 return (castTime
> 0) ? uint32(castTime
) : 0;
92 bool IsPassiveSpell(uint32 spellId
)
94 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
97 return (spellInfo
->Attributes
& SPELL_ATTR_PASSIVE
) != 0;
100 bool IsNoStackAuraDueToAura(uint32 spellId_1
, uint32 effIndex_1
, uint32 spellId_2
, uint32 effIndex_2
)
102 SpellEntry
const *spellInfo_1
= sSpellStore
.LookupEntry(spellId_1
);
103 SpellEntry
const *spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
104 if(!spellInfo_1
|| !spellInfo_2
) return false;
105 if(spellInfo_1
->Id
== spellId_2
) return false;
107 if (spellInfo_1
->Effect
[effIndex_1
] != spellInfo_2
->Effect
[effIndex_2
] ||
108 spellInfo_1
->EffectItemType
[effIndex_1
] != spellInfo_2
->EffectItemType
[effIndex_2
] ||
109 spellInfo_1
->EffectMiscValue
[effIndex_1
] != spellInfo_2
->EffectMiscValue
[effIndex_2
] ||
110 spellInfo_1
->EffectApplyAuraName
[effIndex_1
] != spellInfo_2
->EffectApplyAuraName
[effIndex_2
])
116 int32
CompareAuraRanks(uint32 spellId_1
, uint32 effIndex_1
, uint32 spellId_2
, uint32 effIndex_2
)
118 SpellEntry
const*spellInfo_1
= sSpellStore
.LookupEntry(spellId_1
);
119 SpellEntry
const*spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
120 if(!spellInfo_1
|| !spellInfo_2
) return 0;
121 if (spellId_1
== spellId_2
) return 0;
123 int32 diff
= spellInfo_1
->EffectBasePoints
[effIndex_1
] - spellInfo_2
->EffectBasePoints
[effIndex_2
];
124 if (spellInfo_1
->EffectBasePoints
[effIndex_1
]+1 < 0 && spellInfo_2
->EffectBasePoints
[effIndex_2
]+1 < 0) return -diff
;
128 SpellSpecific
GetSpellSpecific(uint32 spellId
)
130 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
134 switch(spellInfo
->SpellFamilyName
)
136 case SPELLFAMILY_MAGE
:
138 // family flags 18(Molten), 25(Frost/Ice), 28(Mage)
139 if (spellInfo
->SpellFamilyFlags
& 0x12040000)
140 return SPELL_MAGE_ARMOR
;
142 if ((spellInfo
->SpellFamilyFlags
& 0x1000000) && spellInfo
->EffectApplyAuraName
[0]==SPELL_AURA_MOD_CONFUSE
)
143 return SPELL_MAGE_POLYMORPH
;
147 case SPELLFAMILY_WARRIOR
:
149 if (spellInfo
->SpellFamilyFlags
& 0x00008000010000LL
)
150 return SPELL_POSITIVE_SHOUT
;
154 case SPELLFAMILY_WARLOCK
:
156 // only warlock curses have this
157 if (spellInfo
->Dispel
== DISPEL_CURSE
)
160 // family flag 37 (only part spells have family name)
161 if (spellInfo
->SpellFamilyFlags
& 0x2000000000LL
)
162 return SPELL_WARLOCK_ARMOR
;
166 case SPELLFAMILY_HUNTER
:
168 // only hunter stings have this
169 if (spellInfo
->Dispel
== DISPEL_POISON
)
174 case SPELLFAMILY_PALADIN
:
176 if (IsSealSpell(spellInfo
))
179 if (spellInfo
->SpellFamilyFlags
& 0x10000100LL
)
180 return SPELL_BLESSING
;
182 if ((spellInfo
->SpellFamilyFlags
& 0x00000820180400LL
) && (spellInfo
->AttributesEx3
& 0x200))
183 return SPELL_JUDGEMENT
;
185 for (int i
= 0; i
< 3; i
++) // TODO: fix it for WotLK!!!
187 // only paladin auras have this
188 if (spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AREA_AURA_RAID
)
193 case SPELLFAMILY_SHAMAN
:
195 if (IsElementalShield(spellInfo
))
196 return SPELL_ELEMENTAL_SHIELD
;
201 case SPELLFAMILY_POTION
:
202 return spellmgr
.GetSpellElixirSpecific(spellInfo
->Id
);
205 // only warlock armor/skin have this (in additional to family cases)
206 if( spellInfo
->SpellVisual
[0] == 130 && spellInfo
->SpellIconID
== 89)
208 return SPELL_WARLOCK_ARMOR
;
211 // only hunter aspects have this (but not all aspects in hunter family)
212 if( spellInfo
->activeIconID
== 122 && (GetSpellSchoolMask(spellInfo
) & SPELL_SCHOOL_MASK_NATURE
) &&
213 (spellInfo
->Attributes
& 0x50000) != 0 && (spellInfo
->Attributes
& 0x9000010) == 0)
218 for(int i
= 0; i
< 3; i
++)
219 if( spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AURA
&& (
220 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_TRACK_CREATURES
||
221 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_TRACK_RESOURCES
||
222 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_TRACK_STEALTHED
) )
223 return SPELL_TRACKER
;
225 // elixirs can have different families, but potion most ofc.
226 if(SpellSpecific sp
= spellmgr
.GetSpellElixirSpecific(spellInfo
->Id
))
232 bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1
,uint32 spellSpec2
)
243 case SPELL_WARLOCK_ARMOR
:
244 case SPELL_MAGE_ARMOR
:
245 case SPELL_MAGE_POLYMORPH
:
246 case SPELL_POSITIVE_SHOUT
:
247 case SPELL_JUDGEMENT
:
248 return spellSpec1
==spellSpec2
;
249 case SPELL_BATTLE_ELIXIR
:
250 return spellSpec2
==SPELL_BATTLE_ELIXIR
251 || spellSpec2
==SPELL_FLASK_ELIXIR
;
252 case SPELL_GUARDIAN_ELIXIR
:
253 return spellSpec2
==SPELL_GUARDIAN_ELIXIR
254 || spellSpec2
==SPELL_FLASK_ELIXIR
;
255 case SPELL_FLASK_ELIXIR
:
256 return spellSpec2
==SPELL_BATTLE_ELIXIR
257 || spellSpec2
==SPELL_GUARDIAN_ELIXIR
258 || spellSpec2
==SPELL_FLASK_ELIXIR
;
264 bool IsPositiveTarget(uint32 targetA
, uint32 targetB
)
266 // non-positive targets
269 case TARGET_CHAIN_DAMAGE
:
270 case TARGET_ALL_ENEMY_IN_AREA
:
271 case TARGET_ALL_ENEMY_IN_AREA_INSTANT
:
272 case TARGET_IN_FRONT_OF_CASTER
:
273 case TARGET_ALL_ENEMY_IN_AREA_CHANNELED
:
274 case TARGET_CURRENT_ENEMY_COORDINATES
:
275 case TARGET_SINGLE_ENEMY
:
277 case TARGET_ALL_AROUND_CASTER
:
278 return (targetB
== TARGET_ALL_PARTY
|| targetB
== TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER
);
283 return IsPositiveTarget(targetB
, 0);
287 bool IsPositiveEffect(uint32 spellId
, uint32 effIndex
)
289 SpellEntry
const *spellproto
= sSpellStore
.LookupEntry(spellId
);
290 if (!spellproto
) return false;
294 case 23333: // BG spell
295 case 23335: // BG spell
296 case 34976: // BG spell
298 case 28441: // not positive dummy spell
299 case 37675: // Chaos Blast
303 switch(spellproto
->Effect
[effIndex
])
305 // always positive effects (check before target checks that provided non-positive result in some case for positive effects)
306 case SPELL_EFFECT_HEAL
:
307 case SPELL_EFFECT_LEARN_SPELL
:
308 case SPELL_EFFECT_SKILL_STEP
:
309 case SPELL_EFFECT_HEAL_PCT
:
310 case SPELL_EFFECT_ENERGIZE_PCT
:
313 // non-positive aura use
314 case SPELL_EFFECT_APPLY_AURA
:
315 case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
:
317 switch(spellproto
->EffectApplyAuraName
[effIndex
])
319 case SPELL_AURA_DUMMY
:
321 // dummy aura can be positive or negative dependent from casted spell
322 switch(spellproto
->Id
)
324 case 13139: // net-o-matic special effect
325 case 23445: // evil twin
326 case 38637: // Nether Exhaustion (red)
327 case 38638: // Nether Exhaustion (green)
328 case 38639: // Nether Exhaustion (blue)
334 case SPELL_AURA_MOD_STAT
:
335 case SPELL_AURA_MOD_DAMAGE_DONE
: // dependent from bas point sign (negative -> negative)
336 case SPELL_AURA_MOD_HEALING_DONE
:
338 if(spellproto
->EffectBasePoints
[effIndex
]+int32(spellproto
->EffectBaseDice
[effIndex
]) < 0)
342 case SPELL_AURA_ADD_TARGET_TRIGGER
:
344 case SPELL_AURA_PERIODIC_TRIGGER_SPELL
:
345 if(spellId
!= spellproto
->EffectTriggerSpell
[effIndex
])
347 uint32 spellTriggeredId
= spellproto
->EffectTriggerSpell
[effIndex
];
348 SpellEntry
const *spellTriggeredProto
= sSpellStore
.LookupEntry(spellTriggeredId
);
350 if(spellTriggeredProto
)
352 // non-positive targets of main spell return early
353 for(int i
= 0; i
< 3; ++i
)
355 // if non-positive trigger cast targeted to positive target this main cast is non-positive
356 // this will place this spell auras as debuffs
357 if(IsPositiveTarget(spellTriggeredProto
->EffectImplicitTargetA
[effIndex
],spellTriggeredProto
->EffectImplicitTargetB
[effIndex
]) && !IsPositiveEffect(spellTriggeredId
,i
))
363 case SPELL_AURA_PROC_TRIGGER_SPELL
:
364 // many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example)
366 case SPELL_AURA_MOD_STUN
: //have positive and negative spells, we can't sort its correctly at this moment.
367 if(effIndex
==0 && spellproto
->Effect
[1]==0 && spellproto
->Effect
[2]==0)
368 return false; // but all single stun aura spells is negative
371 if(spellproto
->Id
== 17624)
374 case SPELL_AURA_MOD_ROOT
:
375 case SPELL_AURA_MOD_SILENCE
:
376 case SPELL_AURA_GHOST
:
377 case SPELL_AURA_PERIODIC_LEECH
:
378 case SPELL_AURA_MOD_PACIFY_SILENCE
:
379 case SPELL_AURA_MOD_STALKED
:
380 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT
:
382 case SPELL_AURA_PERIODIC_DAMAGE
: // used in positive spells also.
383 // part of negative spell if casted at self (prevent cancel)
384 if(spellproto
->EffectImplicitTargetA
[effIndex
] == TARGET_SELF
)
387 case SPELL_AURA_MOD_DECREASE_SPEED
: // used in positive spells also
388 // part of positive spell if casted at self
389 if(spellproto
->EffectImplicitTargetA
[effIndex
] != TARGET_SELF
)
391 // but not this if this first effect (don't found batter check)
392 if(spellproto
->Attributes
& 0x4000000 && effIndex
==0)
395 case SPELL_AURA_TRANSFORM
:
396 // some spells negative
397 switch(spellproto
->Id
)
399 case 36897: // Transporter Malfunction (race mutation to horde)
400 case 36899: // Transporter Malfunction (race mutation to alliance)
404 case SPELL_AURA_MOD_SCALE
:
405 // some spells negative
406 switch(spellproto
->Id
)
408 case 36900: // Soul Split: Evil!
409 case 36901: // Soul Split: Good
410 case 36893: // Transporter Malfunction (decrease size case)
411 case 36895: // Transporter Malfunction (increase size case)
415 case SPELL_AURA_MECHANIC_IMMUNITY
:
417 // non-positive immunities
418 switch(spellproto
->EffectMiscValue
[effIndex
])
420 case MECHANIC_BANDAGE
:
421 case MECHANIC_SHIELD
:
423 case MECHANIC_INVULNERABILITY
:
429 case SPELL_AURA_ADD_FLAT_MODIFIER
: // mods
430 case SPELL_AURA_ADD_PCT_MODIFIER
:
433 switch(spellproto
->EffectMiscValue
[effIndex
])
435 case SPELLMOD_COST
: // dependent from bas point sign (negative -> positive)
436 if(spellproto
->EffectBasePoints
[effIndex
]+int32(spellproto
->EffectBaseDice
[effIndex
]) > 0)
443 case SPELL_AURA_MOD_HEALING_PCT
:
444 if(spellproto
->EffectBasePoints
[effIndex
]+int32(spellproto
->EffectBaseDice
[effIndex
]) < 0)
447 case SPELL_AURA_MOD_SKILL
:
448 if(spellproto
->EffectBasePoints
[effIndex
]+int32(spellproto
->EffectBaseDice
[effIndex
]) < 0)
451 case SPELL_AURA_FORCE_REACTION
:
452 if(spellproto
->Id
==42792) // Recently Dropped Flag (prevent cancel)
464 // non-positive targets
465 if(!IsPositiveTarget(spellproto
->EffectImplicitTargetA
[effIndex
],spellproto
->EffectImplicitTargetB
[effIndex
]))
468 // AttributesEx check
469 if(spellproto
->AttributesEx
& (1<<7))
476 bool IsPositiveSpell(uint32 spellId
)
478 SpellEntry
const *spellproto
= sSpellStore
.LookupEntry(spellId
);
479 if (!spellproto
) return false;
481 // spells with atleast one negative effect are considered negative
482 // some self-applied spells have negative effects but in self casting case negative check ignored.
483 for (int i
= 0; i
< 3; i
++)
484 if (!IsPositiveEffect(spellId
, i
))
489 bool IsSingleTargetSpell(SpellEntry
const *spellInfo
)
491 // all other single target spells have if it has AttributesEx5
492 if ( spellInfo
->AttributesEx5
& SPELL_ATTR_EX5_SINGLE_TARGET_SPELL
)
495 // TODO - need found Judgements rule
496 switch(GetSpellSpecific(spellInfo
->Id
))
498 case SPELL_JUDGEMENT
:
502 // single target triggered spell.
503 // Not real client side single target spell, but it' not triggered until prev. aura expired.
504 // This is allow store it in single target spells list for caster for spell proc checking
505 if(spellInfo
->Id
==38324) // Regeneration (triggered by 38299 (HoTs on Heals))
511 bool IsSingleTargetSpells(SpellEntry
const *spellInfo1
, SpellEntry
const *spellInfo2
)
513 // TODO - need better check
514 // Equal icon and spellfamily
515 if( spellInfo1
->SpellFamilyName
== spellInfo2
->SpellFamilyName
&&
516 spellInfo1
->SpellIconID
== spellInfo2
->SpellIconID
)
519 // TODO - need found Judgements rule
520 SpellSpecific spec1
= GetSpellSpecific(spellInfo1
->Id
);
521 // spell with single target specific types
524 case SPELL_JUDGEMENT
:
525 if(GetSpellSpecific(spellInfo2
->Id
) == spec1
)
533 uint8
GetErrorAtShapeshiftedCast (SpellEntry
const *spellInfo
, uint32 form
)
535 // talents that learn spells can have stance requirements that need ignore
536 // (this requirement only for client-side stance show in talent description)
537 if( GetTalentSpellCost(spellInfo
->Id
) > 0 &&
538 (spellInfo
->Effect
[0]==SPELL_EFFECT_LEARN_SPELL
|| spellInfo
->Effect
[1]==SPELL_EFFECT_LEARN_SPELL
|| spellInfo
->Effect
[2]==SPELL_EFFECT_LEARN_SPELL
) )
541 uint32 stanceMask
= (form
? 1 << (form
- 1) : 0);
543 if (stanceMask
& spellInfo
->StancesNot
) // can explicitly not be casted in this stance
544 return SPELL_FAILED_NOT_SHAPESHIFT
;
546 if (stanceMask
& spellInfo
->Stances
) // can explicitly be casted in this stance
549 bool actAsShifted
= false;
552 SpellShapeshiftEntry
const *shapeInfo
= sSpellShapeshiftStore
.LookupEntry(form
);
555 sLog
.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form
);
558 actAsShifted
= !(shapeInfo
->flags1
& 1); // shapeshift acts as normal form for spells
563 if (spellInfo
->Attributes
& SPELL_ATTR_NOT_SHAPESHIFT
) // not while shapeshifted
564 return SPELL_FAILED_NOT_SHAPESHIFT
;
565 else if (spellInfo
->Stances
!= 0) // needs other shapeshift
566 return SPELL_FAILED_ONLY_SHAPESHIFT
;
571 if(!(spellInfo
->AttributesEx2
& SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT
) && spellInfo
->Stances
!= 0)
572 return SPELL_FAILED_ONLY_SHAPESHIFT
;
578 void SpellMgr::LoadSpellTargetPositions()
580 mSpellTargetPositions
.clear(); // need for reload case
585 QueryResult
*result
= WorldDatabase
.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position");
594 sLog
.outString( ">> Loaded %u spell target coordinates", count
);
598 barGoLink
bar( result
->GetRowCount() );
602 Field
*fields
= result
->Fetch();
608 uint32 Spell_ID
= fields
[0].GetUInt32();
610 SpellTargetPosition st
;
612 st
.target_mapId
= fields
[1].GetUInt32();
613 st
.target_X
= fields
[2].GetFloat();
614 st
.target_Y
= fields
[3].GetFloat();
615 st
.target_Z
= fields
[4].GetFloat();
616 st
.target_Orientation
= fields
[5].GetFloat();
618 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(Spell_ID
);
621 sLog
.outErrorDb("Spell (ID:%u) listed in `spell_target_position` does not exist.",Spell_ID
);
626 for(int i
= 0; i
< 3; ++i
)
628 if( spellInfo
->EffectImplicitTargetA
[i
]==TARGET_TABLE_X_Y_Z_COORDINATES
|| spellInfo
->EffectImplicitTargetB
[i
]==TARGET_TABLE_X_Y_Z_COORDINATES
)
636 sLog
.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID
);
640 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(st
.target_mapId
);
643 sLog
.outErrorDb("Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Spell_ID
,st
.target_mapId
);
647 if(st
.target_X
==0 && st
.target_Y
==0 && st
.target_Z
==0)
649 sLog
.outErrorDb("Spell (ID:%u) target coordinates not provided.",Spell_ID
);
653 mSpellTargetPositions
[Spell_ID
] = st
;
655 } while( result
->NextRow() );
660 sLog
.outString( ">> Loaded %u spell teleport coordinates", count
);
663 void SpellMgr::LoadSpellAffects()
665 mSpellAffectMap
.clear(); // need for reload case
670 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, effectId, SpellClassMask0, SpellClassMask1, SpellClassMask2 FROM spell_affect");
679 sLog
.outString( ">> Loaded %u spell affect definitions", count
);
683 barGoLink
bar( result
->GetRowCount() );
687 Field
*fields
= result
->Fetch();
691 uint16 entry
= fields
[0].GetUInt16();
692 uint8 effectId
= fields
[1].GetUInt8();
694 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(entry
);
698 sLog
.outErrorDb("Spell %u listed in `spell_affect` does not exist", entry
);
704 sLog
.outErrorDb("Spell %u listed in `spell_affect` have invalid effect index (%u)", entry
,effectId
);
708 if( spellInfo
->Effect
[effectId
] != SPELL_EFFECT_APPLY_AURA
||
709 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_FLAT_MODIFIER
&&
710 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_PCT_MODIFIER
&&
711 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_TARGET_TRIGGER
)
713 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
);
717 SpellAffectEntry affect
;
718 affect
.SpellClassMask
[0] = fields
[2].GetUInt32();
719 affect
.SpellClassMask
[1] = fields
[3].GetUInt32();
720 affect
.SpellClassMask
[2] = fields
[4].GetUInt32();
722 // Spell.dbc have own data
723 uint32
const *ptr
= 0;
726 case 0: ptr
= &spellInfo
->EffectSpellClassMaskA
[0]; break;
727 case 1: ptr
= &spellInfo
->EffectSpellClassMaskB
[0]; break;
728 case 2: ptr
= &spellInfo
->EffectSpellClassMaskC
[0]; break;
732 if(ptr
[0] == affect
.SpellClassMask
[0] || ptr
[1] == affect
.SpellClassMask
[1] || ptr
[2] == affect
.SpellClassMask
[2])
735 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
);
739 mSpellAffectMap
[(entry
<<8) + effectId
] = affect
;
742 } while( result
->NextRow() );
747 sLog
.outString( ">> Loaded %u custom spell affect definitions", count
);
749 for (uint32 id
= 0; id
< sSpellStore
.GetNumRows(); ++id
)
751 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(id
);
755 for (int effectId
= 0; effectId
< 3; ++effectId
)
757 if( spellInfo
->Effect
[effectId
] != SPELL_EFFECT_APPLY_AURA
||
758 (spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_FLAT_MODIFIER
&&
759 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_PCT_MODIFIER
&&
760 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_TARGET_TRIGGER
) )
763 uint32
const *ptr
= 0;
766 case 0: ptr
= &spellInfo
->EffectSpellClassMaskA
[0]; break;
767 case 1: ptr
= &spellInfo
->EffectSpellClassMaskB
[0]; break;
768 case 2: ptr
= &spellInfo
->EffectSpellClassMaskC
[0]; break;
772 if(ptr
[0] || ptr
[1] || ptr
[2])
775 if(mSpellAffectMap
.find((id
<<8) + effectId
) != mSpellAffectMap
.end())
778 sLog
.outErrorDb("Spell %u (%s) misses spell_affect for effect %u",id
,spellInfo
->SpellName
[sWorld
.GetDefaultDbcLocale()], effectId
);
783 bool SpellMgr::IsAffectedByMod(SpellEntry
const *spellInfo
, SpellModifier
*mod
) const
785 // false for spellInfo == NULL
786 if (!spellInfo
|| !mod
)
789 SpellEntry
const *affect_spell
= sSpellStore
.LookupEntry(mod
->spellId
);
790 // False if affect_spell == NULL or spellFamily not equal
791 if (!affect_spell
|| affect_spell
->SpellFamilyName
!= spellInfo
->SpellFamilyName
)
795 if (mod
->mask
& spellInfo
->SpellFamilyFlags
||
796 mod
->mask2
& spellInfo
->SpellFamilyFlags2
)
802 void SpellMgr::LoadSpellProcEvents()
804 mSpellProcEventMap
.clear(); // need for reload case
809 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown FROM spell_proc_event");
818 sLog
.outString( ">> Loaded %u spell proc event conditions", count
);
822 barGoLink
bar( result
->GetRowCount() );
826 Field
*fields
= result
->Fetch();
830 uint16 entry
= fields
[0].GetUInt16();
832 if (!sSpellStore
.LookupEntry(entry
))
834 sLog
.outErrorDb("Spell %u listed in `spell_proc_event` does not exist", entry
);
838 SpellProcEventEntry spe
;
840 spe
.schoolMask
= fields
[1].GetUInt32();
841 spe
.category
= fields
[2].GetUInt32();
842 spe
.skillId
= fields
[3].GetUInt32();
843 spe
.spellFamilyName
= fields
[4].GetUInt32();
844 spe
.spellFamilyMask
= fields
[5].GetUInt64();
845 spe
.procFlags
= fields
[6].GetUInt32();
846 spe
.ppmRate
= fields
[7].GetFloat();
847 spe
.cooldown
= fields
[8].GetUInt32();
849 mSpellProcEventMap
[entry
] = spe
;
852 } while( result
->NextRow() );
857 sLog
.outString( ">> Loaded %u spell proc event conditions", count
);
860 // Commented for now, as it still produces many errors (still quite many spells miss spell_proc_event)
861 for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id)
863 SpellEntry const* spellInfo = sSpellStore.LookupEntry(id);
868 for (int effectId = 0; effectId < 3; ++effectId)
870 // at this moment check only SPELL_AURA_PROC_TRIGGER_SPELL
871 if( spellInfo->EffectApplyAuraName[effectId] == SPELL_AURA_PROC_TRIGGER_SPELL )
881 if(GetSpellProcEvent(id))
884 sLog.outErrorDb("Spell %u (%s) misses spell_proc_event",id,spellInfo->SpellName[sWorld.GetDBClang()]);
889 bool SpellMgr::IsSpellProcEventCanTriggeredBy( SpellProcEventEntry
const * spellProcEvent
, SpellEntry
const * procSpell
, uint32 procFlags
)
891 if((procFlags
& spellProcEvent
->procFlags
) == 0)
894 // Additional checks in case spell cast/hit/crit is the event
895 // Check (if set) school, category, skill line, spell talent mask
896 if(spellProcEvent
->schoolMask
&& (!procSpell
|| (GetSpellSchoolMask(procSpell
) & spellProcEvent
->schoolMask
) == 0))
898 if(spellProcEvent
->category
&& (!procSpell
|| procSpell
->Category
!= spellProcEvent
->category
))
900 if(spellProcEvent
->skillId
)
905 SkillLineAbilityMap::const_iterator lower
= spellmgr
.GetBeginSkillLineAbilityMap(procSpell
->Id
);
906 SkillLineAbilityMap::const_iterator upper
= spellmgr
.GetEndSkillLineAbilityMap(procSpell
->Id
);
909 for(SkillLineAbilityMap::const_iterator _spell_idx
= lower
; _spell_idx
!= upper
; ++_spell_idx
)
911 if(_spell_idx
->second
->skillId
== spellProcEvent
->skillId
)
920 if(spellProcEvent
->spellFamilyName
&& (!procSpell
|| spellProcEvent
->spellFamilyName
!= procSpell
->SpellFamilyName
))
922 if(spellProcEvent
->spellFamilyMask
&& (!procSpell
|| (spellProcEvent
->spellFamilyMask
& procSpell
->SpellFamilyFlags
) == 0))
928 void SpellMgr::LoadSpellElixirs()
930 mSpellElixirs
.clear(); // need for reload case
935 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, mask FROM spell_elixir");
944 sLog
.outString( ">> Loaded %u spell elixir definitions", count
);
948 barGoLink
bar( result
->GetRowCount() );
952 Field
*fields
= result
->Fetch();
956 uint16 entry
= fields
[0].GetUInt16();
957 uint8 mask
= fields
[1].GetUInt8();
959 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(entry
);
963 sLog
.outErrorDb("Spell %u listed in `spell_elixir` does not exist", entry
);
967 mSpellElixirs
[entry
] = mask
;
970 } while( result
->NextRow() );
975 sLog
.outString( ">> Loaded %u spell elixir definitions", count
);
978 void SpellMgr::LoadSpellThreats()
980 sSpellThreatStore
.Free(); // for reload
982 sSpellThreatStore
.Load();
984 sLog
.outString( ">> Loaded %u aggro generating spells", sSpellThreatStore
.RecordCount
);
988 bool SpellMgr::IsRankSpellDueToSpell(SpellEntry
const *spellInfo_1
,uint32 spellId_2
) const
990 SpellEntry
const *spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
991 if(!spellInfo_1
|| !spellInfo_2
) return false;
992 if(spellInfo_1
->Id
== spellId_2
) return false;
994 return GetFirstSpellInChain(spellInfo_1
->Id
)==GetFirstSpellInChain(spellId_2
);
997 bool SpellMgr::canStackSpellRanks(SpellEntry
const *spellInfo
)
999 if(spellInfo
->powerType
!= POWER_MANA
&& spellInfo
->powerType
!= POWER_HEALTH
)
1001 if(IsProfessionSpell(spellInfo
->Id
))
1004 // All stance spells. if any better way, change it.
1005 for (int i
= 0; i
< 3; i
++)
1007 // Paladin aura Spell
1008 if(spellInfo
->SpellFamilyName
== SPELLFAMILY_PALADIN
1009 && spellInfo
->Effect
[i
]==SPELL_EFFECT_APPLY_AREA_AURA_RAID
)
1012 if(spellInfo
->SpellFamilyName
== SPELLFAMILY_DRUID
1013 && spellInfo
->Effect
[i
]==SPELL_EFFECT_APPLY_AURA
1014 && spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_MOD_SHAPESHIFT
)
1017 if(spellInfo
->SpellFamilyName
== SPELLFAMILY_ROGUE
1018 && spellInfo
->Effect
[i
]==SPELL_EFFECT_APPLY_AURA
1019 && spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_MOD_SHAPESHIFT
)
1025 bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1
, uint32 spellId_2
) const
1027 SpellEntry
const *spellInfo_1
= sSpellStore
.LookupEntry(spellId_1
);
1028 SpellEntry
const *spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
1030 if(!spellInfo_1
|| !spellInfo_2
)
1033 if(spellInfo_1
->Id
== spellId_2
)
1036 //I think we don't check this correctly because i need a exception for spell:
1037 //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.
1038 if(spellInfo_2
->SpellFamilyFlags
== 2048)
1041 // Resurrection sickness
1042 if((spellInfo_1
->Id
== SPELL_ID_PASSIVE_RESURRECTION_SICKNESS
) != (spellInfo_2
->Id
==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS
))
1045 // Specific spell family spells
1046 switch(spellInfo_1
->SpellFamilyName
)
1048 case SPELLFAMILY_GENERIC
:
1049 switch(spellInfo_2
->SpellFamilyName
)
1051 case SPELLFAMILY_GENERIC
: // same family case
1054 if( spellInfo_1
->Id
== 21992 && spellInfo_2
->Id
== 27648 || spellInfo_2
->Id
== 21992 && spellInfo_1
->Id
== 27648 )
1057 // Lightning Speed (Mongoose) and Fury of the Crashing Waves (Tsunami Talisman)
1058 if( spellInfo_1
->Id
== 28093 && spellInfo_2
->Id
== 42084 ||
1059 spellInfo_2
->Id
== 28093 && spellInfo_1
->Id
== 42084 )
1062 // Soulstone Resurrection and Twisting Nether (resurrector)
1063 if( spellInfo_1
->SpellIconID
== 92 && spellInfo_2
->SpellIconID
== 92 && (
1064 spellInfo_1
->SpellVisual
[0] == 99 && spellInfo_2
->SpellVisual
[0] == 0 ||
1065 spellInfo_2
->SpellVisual
[0] == 99 && spellInfo_1
->SpellVisual
[0] == 0 ) )
1068 // Heart of the Wild and (Primal Instinct (Idol of Terror) triggering spell or Agility)
1069 if( spellInfo_1
->SpellIconID
== 240 && spellInfo_2
->SpellIconID
== 240 && (
1070 spellInfo_1
->SpellVisual
[0] == 0 && spellInfo_2
->SpellVisual
[0] == 78 ||
1071 spellInfo_2
->SpellVisual
[0] == 0 && spellInfo_1
->SpellVisual
[0] == 78 ) )
1074 // Personalized Weather (thunder effect should overwrite rainy aura)
1075 if(spellInfo_1
->SpellIconID
== 2606 && spellInfo_2
->SpellIconID
== 2606)
1078 // Brood Affliction: Bronze
1079 if( (spellInfo_1
->Id
== 23170 && spellInfo_2
->Id
== 23171) ||
1080 (spellInfo_2
->Id
== 23170 && spellInfo_1
->Id
== 23171) )
1085 case SPELLFAMILY_WARRIOR
:
1087 // Scroll of Protection and Defensive Stance (multi-family check)
1088 if( spellInfo_1
->SpellIconID
== 276 && spellInfo_1
->SpellVisual
[0] == 196 && spellInfo_2
->Id
== 71)
1091 // Improved Hamstring -> Hamstring (multi-family check)
1092 if( (spellInfo_2
->SpellFamilyFlags
& 2) && spellInfo_1
->Id
== 23694 )
1097 case SPELLFAMILY_DRUID
:
1099 // Scroll of Stamina and Leader of the Pack (multi-family check)
1100 if( spellInfo_1
->SpellIconID
== 312 && spellInfo_1
->SpellVisual
[0] == 216 && spellInfo_2
->Id
== 24932 )
1103 // Dragonmaw Illusion (multi-family check)
1104 if (spellId_1
== 40216 && spellId_2
== 42016 )
1109 case SPELLFAMILY_ROGUE
:
1111 // Garrote-Silence -> Garrote (multi-family check)
1112 if( spellInfo_1
->SpellIconID
== 498 && spellInfo_1
->SpellVisual
== 0 && spellInfo_2
->SpellIconID
== 498 )
1117 case SPELLFAMILY_HUNTER
:
1119 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1120 if( spellInfo_1
->Id
== 19410 && spellInfo_2
->Id
== 5116 )
1123 // Improved Wing Clip -> Wing Clip (multi-family check)
1124 if( (spellInfo_2
->SpellFamilyFlags
& 0x40) && spellInfo_1
->Id
== 19229 )
1128 case SPELLFAMILY_PALADIN
:
1130 // Unstable Currents and other -> *Sanctity Aura (multi-family check)
1131 if( spellInfo_2
->SpellIconID
==502 && spellInfo_1
->SpellIconID
==502 && spellInfo_1
->SpellVisual
[0]==969 )
1134 // *Band of Eternal Champion and Seal of Command(multi-family check)
1135 if( spellId_1
== 35081 && spellInfo_2
->SpellIconID
==561 && spellInfo_2
->SpellVisual
[0]==7992)
1142 case SPELLFAMILY_MAGE
:
1143 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_MAGE
)
1145 // Blizzard & Chilled (and some other stacked with blizzard spells
1146 if( (spellInfo_1
->SpellFamilyFlags
& 0x80) && (spellInfo_2
->SpellFamilyFlags
& 0x100000) ||
1147 (spellInfo_2
->SpellFamilyFlags
& 0x80) && (spellInfo_1
->SpellFamilyFlags
& 0x100000) )
1150 // Blink & Improved Blink
1151 if( (spellInfo_1
->SpellFamilyFlags
& 0x0000000000010000LL
) && (spellInfo_2
->SpellVisual
[0] == 72 && spellInfo_2
->SpellIconID
== 1499) ||
1152 (spellInfo_2
->SpellFamilyFlags
& 0x0000000000010000LL
) && (spellInfo_1
->SpellVisual
[0] == 72 && spellInfo_1
->SpellIconID
== 1499) )
1155 // Detect Invisibility and Mana Shield (multi-family check)
1156 if( spellInfo_2
->Id
== 132 && spellInfo_1
->SpellIconID
== 209 && spellInfo_1
->SpellVisual
[0] == 968 )
1159 // Combustion and Fire Protection Aura (multi-family check)
1160 if( spellInfo_1
->Id
== 11129 && spellInfo_2
->SpellIconID
== 33 && spellInfo_2
->SpellVisual
[0] == 321 )
1164 case SPELLFAMILY_WARLOCK
:
1165 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_WARLOCK
)
1167 // Siphon Life and Drain Life
1168 if( spellInfo_1
->SpellIconID
== 152 && spellInfo_2
->SpellIconID
== 546 ||
1169 spellInfo_2
->SpellIconID
== 152 && spellInfo_1
->SpellIconID
== 546 )
1172 //Corruption & Seed of corruption
1173 if( spellInfo_1
->SpellIconID
== 313 && spellInfo_2
->SpellIconID
== 1932 ||
1174 spellInfo_2
->SpellIconID
== 313 && spellInfo_1
->SpellIconID
== 1932 )
1175 if(spellInfo_1
->SpellVisual
!= 0 && spellInfo_2
->SpellVisual
!= 0)
1176 return true; // can't be stacked
1178 // Corruption and Unstable Affliction
1179 if( spellInfo_1
->SpellIconID
== 313 && spellInfo_2
->SpellIconID
== 2039 ||
1180 spellInfo_2
->SpellIconID
== 313 && spellInfo_1
->SpellIconID
== 2039 )
1183 // (Corruption or Unstable Affliction) and (Curse of Agony or Curse of Doom)
1184 if( (spellInfo_1
->SpellIconID
== 313 || spellInfo_1
->SpellIconID
== 2039) && (spellInfo_2
->SpellIconID
== 544 || spellInfo_2
->SpellIconID
== 91) ||
1185 (spellInfo_2
->SpellIconID
== 313 || spellInfo_2
->SpellIconID
== 2039) && (spellInfo_1
->SpellIconID
== 544 || spellInfo_1
->SpellIconID
== 91) )
1188 // Detect Invisibility and Mana Shield (multi-family check)
1189 if( spellInfo_1
->Id
== 132 && spellInfo_2
->SpellIconID
== 209 && spellInfo_2
->SpellVisual
[0] == 968 )
1192 case SPELLFAMILY_WARRIOR
:
1193 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_WARRIOR
)
1195 // Rend and Deep Wound
1196 if( (spellInfo_1
->SpellFamilyFlags
& 0x20) && (spellInfo_2
->SpellFamilyFlags
& 0x1000000000LL
) ||
1197 (spellInfo_2
->SpellFamilyFlags
& 0x20) && (spellInfo_1
->SpellFamilyFlags
& 0x1000000000LL
) )
1200 // Battle Shout and Rampage
1201 if( (spellInfo_1
->SpellIconID
== 456 && spellInfo_2
->SpellIconID
== 2006) ||
1202 (spellInfo_2
->SpellIconID
== 456 && spellInfo_1
->SpellIconID
== 2006) )
1206 // Hamstring -> Improved Hamstring (multi-family check)
1207 if( (spellInfo_1
->SpellFamilyFlags
& 2) && spellInfo_2
->Id
== 23694 )
1210 // Defensive Stance and Scroll of Protection (multi-family check)
1211 if( spellInfo_1
->Id
== 71 && spellInfo_2
->SpellIconID
== 276 && spellInfo_2
->SpellVisual
[0] == 196 )
1214 // Bloodlust and Bloodthirst (multi-family check)
1215 if( spellInfo_2
->Id
== 2825 && spellInfo_1
->SpellIconID
== 38 && spellInfo_1
->SpellVisual
[0] == 0 )
1219 case SPELLFAMILY_PRIEST
:
1220 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_PRIEST
)
1222 //Devouring Plague and Shadow Vulnerability
1223 if( (spellInfo_1
->SpellFamilyFlags
& 0x2000000) && (spellInfo_2
->SpellFamilyFlags
& 0x800000000LL
) ||
1224 (spellInfo_2
->SpellFamilyFlags
& 0x2000000) && (spellInfo_1
->SpellFamilyFlags
& 0x800000000LL
) )
1227 //StarShards and Shadow Word: Pain
1228 if( (spellInfo_1
->SpellFamilyFlags
& 0x200000) && (spellInfo_2
->SpellFamilyFlags
& 0x8000) ||
1229 (spellInfo_2
->SpellFamilyFlags
& 0x200000) && (spellInfo_1
->SpellFamilyFlags
& 0x8000) )
1233 case SPELLFAMILY_DRUID
:
1234 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_DRUID
)
1236 //Omen of Clarity and Blood Frenzy
1237 if( (spellInfo_1
->SpellFamilyFlags
== 0x0 && spellInfo_1
->SpellIconID
== 108) && (spellInfo_2
->SpellFamilyFlags
& 0x20000000000000LL
) ||
1238 (spellInfo_2
->SpellFamilyFlags
== 0x0 && spellInfo_2
->SpellIconID
== 108) && (spellInfo_1
->SpellFamilyFlags
& 0x20000000000000LL
) )
1241 // Tree of Life (Shapeshift) and 34123 Tree of Life (Passive)
1242 if ((spellId_1
== 33891 && spellId_2
== 34123) ||
1243 (spellId_2
== 33891 && spellId_1
== 34123))
1246 // Wrath of Elune and Nature's Grace
1247 if( spellInfo_1
->Id
== 16886 && spellInfo_2
->Id
== 46833 || spellInfo_2
->Id
== 16886 && spellInfo_1
->Id
== 46833 )
1250 // Bear Rage (Feral T4 (2)) and Omen of Clarity
1251 if( spellInfo_1
->Id
== 16864 && spellInfo_2
->Id
== 37306 || spellInfo_2
->Id
== 16864 && spellInfo_1
->Id
== 37306 )
1254 // Cat Energy (Feral T4 (2)) and Omen of Clarity
1255 if( spellInfo_1
->Id
== 16864 && spellInfo_2
->Id
== 37311 || spellInfo_2
->Id
== 16864 && spellInfo_1
->Id
== 37311 )
1259 // Leader of the Pack and Scroll of Stamina (multi-family check)
1260 if( spellInfo_1
->Id
== 24932 && spellInfo_2
->SpellIconID
== 312 && spellInfo_2
->SpellVisual
[0] == 216 )
1263 // Dragonmaw Illusion (multi-family check)
1264 if (spellId_1
== 42016 && spellId_2
== 40216 )
1268 case SPELLFAMILY_ROGUE
:
1269 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_ROGUE
)
1271 // Master of Subtlety
1272 if (spellId_1
== 31665 && spellId_2
== 31666 || spellId_1
== 31666 && spellId_2
== 31665 )
1276 // Garrote -> Garrote-Silence (multi-family check)
1277 if( spellInfo_1
->SpellIconID
== 498 && spellInfo_2
->SpellIconID
== 498 && spellInfo_2
->SpellVisual
[0] == 0 )
1280 case SPELLFAMILY_HUNTER
:
1281 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_HUNTER
)
1283 // Rapid Fire & Quick Shots
1284 if( (spellInfo_1
->SpellFamilyFlags
& 0x20) && (spellInfo_2
->SpellFamilyFlags
& 0x20000000000LL
) ||
1285 (spellInfo_2
->SpellFamilyFlags
& 0x20) && (spellInfo_1
->SpellFamilyFlags
& 0x20000000000LL
) )
1288 // Serpent Sting & (Immolation/Explosive Trap Effect)
1289 if( (spellInfo_1
->SpellFamilyFlags
& 0x4) && (spellInfo_2
->SpellFamilyFlags
& 0x00000004000LL
) ||
1290 (spellInfo_2
->SpellFamilyFlags
& 0x4) && (spellInfo_1
->SpellFamilyFlags
& 0x00000004000LL
) )
1294 if( spellInfo_1
->SpellIconID
== 1680 && spellInfo_2
->SpellIconID
== 1680 )
1298 // Wing Clip -> Improved Wing Clip (multi-family check)
1299 if( (spellInfo_1
->SpellFamilyFlags
& 0x40) && spellInfo_2
->Id
== 19229 )
1302 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1303 if( spellInfo_2
->Id
== 19410 && spellInfo_1
->Id
== 5116 )
1306 case SPELLFAMILY_PALADIN
:
1307 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_PALADIN
)
1310 if( IsSealSpell(spellInfo_1
) && IsSealSpell(spellInfo_2
) )
1313 // Combustion and Fire Protection Aura (multi-family check)
1314 if( spellInfo_2
->Id
== 11129 && spellInfo_1
->SpellIconID
== 33 && spellInfo_1
->SpellVisual
[0] == 321 )
1317 // *Sanctity Aura -> Unstable Currents and other (multi-family check)
1318 if( spellInfo_1
->SpellIconID
==502 && spellInfo_2
->SpellFamilyName
== SPELLFAMILY_GENERIC
&& spellInfo_2
->SpellIconID
==502 && spellInfo_2
->SpellVisual
[0]==969 )
1321 // *Seal of Command and Band of Eternal Champion (multi-family check)
1322 if( spellInfo_1
->SpellIconID
==561 && spellInfo_1
->SpellVisual
[0]==7992 && spellId_2
== 35081)
1325 case SPELLFAMILY_SHAMAN
:
1326 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_SHAMAN
)
1329 if( IsElementalShield(spellInfo_1
) && IsElementalShield(spellInfo_2
) )
1333 if( spellInfo_1
->SpellIconID
==220 && spellInfo_2
->SpellIconID
==220 &&
1334 spellInfo_1
->SpellFamilyFlags
!= spellInfo_2
->SpellFamilyFlags
)
1337 // Bloodlust and Bloodthirst (multi-family check)
1338 if( spellInfo_1
->Id
== 2825 && spellInfo_2
->SpellIconID
== 38 && spellInfo_2
->SpellVisual
[0] == 0 )
1345 // more generic checks
1346 if (spellInfo_1
->SpellIconID
== spellInfo_2
->SpellIconID
&&
1347 spellInfo_1
->SpellIconID
!= 0 && spellInfo_2
->SpellIconID
!= 0)
1349 bool isModifier
= false;
1350 for (int i
= 0; i
< 3; i
++)
1352 if (spellInfo_1
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_FLAT_MODIFIER
||
1353 spellInfo_1
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_PCT_MODIFIER
||
1354 spellInfo_2
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_FLAT_MODIFIER
||
1355 spellInfo_2
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_PCT_MODIFIER
)
1363 if (IsRankSpellDueToSpell(spellInfo_1
, spellId_2
))
1366 if (spellInfo_1
->SpellFamilyName
== 0 || spellInfo_2
->SpellFamilyName
== 0)
1369 if (spellInfo_1
->SpellFamilyName
!= spellInfo_2
->SpellFamilyName
)
1372 for (int i
= 0; i
< 3; ++i
)
1373 if (spellInfo_1
->Effect
[i
] != spellInfo_2
->Effect
[i
] ||
1374 spellInfo_1
->EffectItemType
[i
] != spellInfo_2
->EffectItemType
[i
] ||
1375 spellInfo_1
->EffectMiscValue
[i
] != spellInfo_2
->EffectMiscValue
[i
] ||
1376 spellInfo_1
->EffectApplyAuraName
[i
] != spellInfo_2
->EffectApplyAuraName
[i
])
1382 bool SpellMgr::IsProfessionSpell(uint32 spellId
)
1384 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
1388 if(spellInfo
->Effect
[1] != SPELL_EFFECT_SKILL
)
1391 uint32 skill
= spellInfo
->EffectMiscValue
[1];
1393 return IsProfessionSkill(skill
);
1396 bool SpellMgr::IsPrimaryProfessionSpell(uint32 spellId
)
1398 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
1402 if(spellInfo
->Effect
[1] != SPELL_EFFECT_SKILL
)
1405 uint32 skill
= spellInfo
->EffectMiscValue
[1];
1407 return IsPrimaryProfessionSkill(skill
);
1410 bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId
) const
1412 return IsPrimaryProfessionSpell(spellId
) && GetSpellRank(spellId
)==1;
1415 SpellEntry
const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry
const* spellInfo
, uint32 playerLevel
) const
1417 // ignore passive spells
1418 if(IsPassiveSpell(spellInfo
->Id
))
1421 bool needRankSelection
= false;
1422 for(int i
=0;i
<3;i
++)
1424 if( IsPositiveEffect(spellInfo
->Id
, i
) && (
1425 spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AURA
||
1426 spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY
||
1427 spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AREA_AURA_RAID
1430 needRankSelection
= true;
1436 if(!needRankSelection
)
1439 for(uint32 nextSpellId
= spellInfo
->Id
; nextSpellId
!= 0; nextSpellId
= GetPrevSpellInChain(nextSpellId
))
1441 SpellEntry
const *nextSpellInfo
= sSpellStore
.LookupEntry(nextSpellId
);
1445 // if found appropriate level
1446 if(playerLevel
+ 10 >= nextSpellInfo
->spellLevel
)
1447 return nextSpellInfo
;
1449 // one rank less then
1456 void SpellMgr::LoadSpellChains()
1458 mSpellChains
.clear(); // need for reload case
1459 mSpellChainsNext
.clear(); // need for reload case
1461 QueryResult
*result
= WorldDatabase
.Query("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain");
1468 sLog
.outString( ">> Loaded 0 spell chain records" );
1469 sLog
.outErrorDb("`spell_chains` table is empty!");
1475 barGoLink
bar( result
->GetRowCount() );
1479 Field
*fields
= result
->Fetch();
1481 uint32 spell_id
= fields
[0].GetUInt32();
1483 SpellChainNode node
;
1484 node
.prev
= fields
[1].GetUInt32();
1485 node
.first
= fields
[2].GetUInt32();
1486 node
.rank
= fields
[3].GetUInt8();
1487 node
.req
= fields
[4].GetUInt32();
1489 if(!sSpellStore
.LookupEntry(spell_id
))
1491 sLog
.outErrorDb("Spell %u listed in `spell_chain` does not exist",spell_id
);
1495 if(node
.prev
!=0 && !sSpellStore
.LookupEntry(node
.prev
))
1497 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existed previous rank spell.",
1498 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1502 if(!sSpellStore
.LookupEntry(node
.first
))
1504 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing first rank spell.",
1505 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1509 // check basic spell chain data integrity (note: rank can be equal 0 or 1 for first/single spell)
1510 if( (spell_id
== node
.first
) != (node
.rank
<= 1) ||
1511 (spell_id
== node
.first
) != (node
.prev
== 0) ||
1512 (node
.rank
<= 1) != (node
.prev
== 0) )
1514 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not compatible chain data.",
1515 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1519 if(node
.req
!=0 && !sSpellStore
.LookupEntry(node
.req
))
1521 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing required spell.",
1522 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1526 // talents not required data in spell chain for work, but must be checked if present for intergrity
1527 if(TalentSpellPos
const* pos
= GetTalentSpellPos(spell_id
))
1529 if(node
.rank
!=pos
->rank
+1)
1531 sLog
.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong rank.",
1532 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1536 if(TalentEntry
const* talentEntry
= sTalentStore
.LookupEntry(pos
->talent_id
))
1538 if(node
.first
!=talentEntry
->RankID
[0])
1540 sLog
.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong first rank spell.",
1541 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1545 if(node
.rank
> 1 && node
.prev
!= talentEntry
->RankID
[node
.rank
-1-1])
1547 sLog
.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong prev rank spell.",
1548 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1552 /*if(node.req!=talentEntry->DependsOnSpell)
1554 sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong required spell.",
1555 spell_id,node.prev,node.first,node.rank,node.req);
1561 mSpellChains
[spell_id
] = node
;
1564 mSpellChainsNext
.insert(SpellChainMapNext::value_type(node
.prev
,spell_id
));
1567 mSpellChainsNext
.insert(SpellChainMapNext::value_type(node
.req
,spell_id
));
1570 } while( result
->NextRow() );
1572 // additional integrity checks
1573 for(SpellChainMap::iterator i
= mSpellChains
.begin(); i
!= mSpellChains
.end(); ++i
)
1577 SpellChainMap::iterator i_prev
= mSpellChains
.find(i
->second
.prev
);
1578 if(i_prev
== mSpellChains
.end())
1580 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found previous rank spell in table.",
1581 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
);
1583 else if( i_prev
->second
.first
!= i
->second
.first
)
1585 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).",
1586 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1587 i_prev
->second
.prev
,i_prev
->second
.first
,i_prev
->second
.rank
,i_prev
->second
.req
);
1589 else if( i_prev
->second
.rank
+1 != i
->second
.rank
)
1591 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).",
1592 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1593 i_prev
->second
.prev
,i_prev
->second
.first
,i_prev
->second
.rank
,i_prev
->second
.req
);
1599 SpellChainMap::iterator i_req
= mSpellChains
.find(i
->second
.req
);
1600 if(i_req
== mSpellChains
.end())
1602 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found required rank spell in table.",
1603 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
);
1605 else if( i_req
->second
.first
== i
->second
.first
)
1607 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).",
1608 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1609 i_req
->second
.prev
,i_req
->second
.first
,i_req
->second
.rank
,i_req
->second
.req
);
1611 else if( i_req
->second
.req
)
1613 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).",
1614 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1615 i_req
->second
.prev
,i_req
->second
.first
,i_req
->second
.rank
,i_req
->second
.req
);
1623 sLog
.outString( ">> Loaded %u spell chain records", count
);
1626 void SpellMgr::LoadSpellLearnSkills()
1628 mSpellLearnSkills
.clear(); // need for reload case
1630 // search auto-learned skills and add its to map also for use in unlearn spells/talents
1631 uint32 dbc_count
= 0;
1632 for(uint32 spell
= 0; spell
< sSpellStore
.GetNumRows(); ++spell
)
1634 SpellEntry
const* entry
= sSpellStore
.LookupEntry(spell
);
1639 for(int i
= 0; i
< 3; ++i
)
1641 if(entry
->Effect
[i
]==SPELL_EFFECT_SKILL
)
1643 SpellLearnSkillNode dbc_node
;
1644 dbc_node
.skill
= entry
->EffectMiscValue
[i
];
1645 if ( dbc_node
.skill
!= SKILL_RIDING
)
1648 dbc_node
.value
= (entry
->EffectBasePoints
[i
]+1)*75;
1649 dbc_node
.maxvalue
= (entry
->EffectBasePoints
[i
]+1)*75;
1651 mSpellLearnSkills
[spell
] = dbc_node
;
1659 sLog
.outString( ">> Loaded %u Spell Learn Skills from DBC", dbc_count
);
1662 void SpellMgr::LoadSpellLearnSpells()
1664 mSpellLearnSpells
.clear(); // need for reload case
1666 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, SpellID FROM spell_learn_spell");
1673 sLog
.outString( ">> Loaded 0 spell learn spells" );
1674 sLog
.outErrorDb("`spell_learn_spell` table is empty!");
1680 barGoLink
bar( result
->GetRowCount() );
1684 Field
*fields
= result
->Fetch();
1686 uint32 spell_id
= fields
[0].GetUInt32();
1688 SpellLearnSpellNode node
;
1689 node
.spell
= fields
[1].GetUInt32();
1690 node
.autoLearned
= false;
1692 if(!sSpellStore
.LookupEntry(spell_id
))
1694 sLog
.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",spell_id
);
1698 if(!sSpellStore
.LookupEntry(node
.spell
))
1700 sLog
.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",node
.spell
);
1704 mSpellLearnSpells
.insert(SpellLearnSpellMap::value_type(spell_id
,node
));
1707 } while( result
->NextRow() );
1711 // search auto-learned spells and add its to map also for use in unlearn spells/talents
1712 uint32 dbc_count
= 0;
1713 for(uint32 spell
= 0; spell
< sSpellStore
.GetNumRows(); ++spell
)
1715 SpellEntry
const* entry
= sSpellStore
.LookupEntry(spell
);
1720 for(int i
= 0; i
< 3; ++i
)
1722 if(entry
->Effect
[i
]==SPELL_EFFECT_LEARN_SPELL
)
1724 SpellLearnSpellNode dbc_node
;
1725 dbc_node
.spell
= entry
->EffectTriggerSpell
[i
];
1726 dbc_node
.autoLearned
= true;
1728 SpellLearnSpellMap::const_iterator db_node_begin
= GetBeginSpellLearnSpell(spell
);
1729 SpellLearnSpellMap::const_iterator db_node_end
= GetEndSpellLearnSpell(spell
);
1732 for(SpellLearnSpellMap::const_iterator itr
= db_node_begin
; itr
!= db_node_end
; ++itr
)
1734 if(itr
->second
.spell
== dbc_node
.spell
)
1736 sLog
.outErrorDb("Spell %u auto-learn spell %u in spell.dbc then the record in `spell_learn_spell` is redundant, please fix DB.",
1737 spell
,dbc_node
.spell
);
1743 if(!found
) // add new spell-spell pair if not found
1745 mSpellLearnSpells
.insert(SpellLearnSpellMap::value_type(spell
,dbc_node
));
1753 sLog
.outString( ">> Loaded %u spell learn spells + %u found in DBC", count
, dbc_count
);
1756 void SpellMgr::LoadSpellScriptTarget()
1758 mSpellScriptTarget
.clear(); // need for reload case
1762 QueryResult
*result
= WorldDatabase
.Query("SELECT entry,type,targetEntry FROM spell_script_target");
1771 sLog
.outErrorDb(">> Loaded 0 SpellScriptTarget. DB table `spell_script_target` is empty.");
1775 barGoLink
bar(result
->GetRowCount());
1779 Field
*fields
= result
->Fetch();
1782 uint32 spellId
= fields
[0].GetUInt32();
1783 uint32 type
= fields
[1].GetUInt32();
1784 uint32 targetEntry
= fields
[2].GetUInt32();
1786 SpellEntry
const* spellProto
= sSpellStore
.LookupEntry(spellId
);
1790 sLog
.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not exist.",spellId
,targetEntry
);
1794 bool targetfound
= false;
1795 for(int i
= 0; i
<3; ++i
)
1797 if( spellProto
->EffectImplicitTargetA
[i
]==TARGET_SCRIPT
||
1798 spellProto
->EffectImplicitTargetB
[i
]==TARGET_SCRIPT
||
1799 spellProto
->EffectImplicitTargetA
[i
]==TARGET_SCRIPT_COORDINATES
||
1800 spellProto
->EffectImplicitTargetB
[i
]==TARGET_SCRIPT_COORDINATES
)
1808 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
);
1812 if( type
>= MAX_SPELL_TARGET_TYPE
)
1814 sLog
.outErrorDb("Table `spell_script_target`: target type %u for TargetEntry %u is incorrect.",type
,targetEntry
);
1820 case SPELL_TARGET_TYPE_GAMEOBJECT
:
1822 if( targetEntry
==0 )
1825 if(!sGOStorage
.LookupEntry
<GameObjectInfo
>(targetEntry
))
1827 sLog
.outErrorDb("Table `spell_script_target`: gameobject template entry %u does not exist.",targetEntry
);
1834 if( targetEntry
==0 )
1836 sLog
.outErrorDb("Table `spell_script_target`: target entry == 0 for not GO target type (%u).",type
);
1839 if(!sCreatureStorage
.LookupEntry
<CreatureInfo
>(targetEntry
))
1841 sLog
.outErrorDb("Table `spell_script_target`: creature template entry %u does not exist.",targetEntry
);
1844 const CreatureInfo
* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(targetEntry
);
1846 if(spellId
== 30427 && !cInfo
->SkinLootId
)
1848 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
);
1855 mSpellScriptTarget
.insert(SpellScriptTarget::value_type(spellId
,SpellTargetEntry(SpellTargetType(type
),targetEntry
)));
1858 } while (result
->NextRow());
1863 /* Disabled (lot errors at this moment)
1864 for(uint32 i = 1; i < sSpellStore.nCount; ++i)
1866 SpellEntry const * spellInfo = sSpellStore.LookupEntry(i);
1871 for(int j=0; j<3; ++j)
1873 if( spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || spellInfo->EffectImplicitTargetA[j] != TARGET_SELF && spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT )
1875 SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(spellInfo->Id);
1876 SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(spellInfo->Id);
1879 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);
1880 break; // effects of spell
1888 sLog
.outString(">> Loaded %u Spell Script Targets", count
);
1891 void SpellMgr::LoadSpellPetAuras()
1893 mSpellPetAuraMap
.clear(); // need for reload case
1898 QueryResult
*result
= WorldDatabase
.Query("SELECT spell, pet, aura FROM spell_pet_auras");
1907 sLog
.outString( ">> Loaded %u spell pet auras", count
);
1911 barGoLink
bar( result
->GetRowCount() );
1915 Field
*fields
= result
->Fetch();
1919 uint16 spell
= fields
[0].GetUInt16();
1920 uint16 pet
= fields
[1].GetUInt16();
1921 uint16 aura
= fields
[2].GetUInt16();
1923 SpellPetAuraMap::iterator itr
= mSpellPetAuraMap
.find(spell
);
1924 if(itr
!= mSpellPetAuraMap
.end())
1926 itr
->second
.AddAura(pet
, aura
);
1930 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell
);
1933 sLog
.outErrorDb("Spell %u listed in `spell_pet_auras` does not exist", spell
);
1938 if((spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AURA
&&
1939 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_DUMMY
) ||
1940 spellInfo
->Effect
[i
] == SPELL_EFFECT_DUMMY
)
1945 sLog
.outError("Spell %u listed in `spell_pet_auras` does not have dummy aura or dummy effect", spell
);
1949 SpellEntry
const* spellInfo2
= sSpellStore
.LookupEntry(aura
);
1952 sLog
.outErrorDb("Aura %u listed in `spell_pet_auras` does not exist", aura
);
1956 PetAura
pa(pet
, aura
, spellInfo
->EffectImplicitTargetA
[i
] == TARGET_PET
, spellInfo
->EffectBasePoints
[i
] + spellInfo
->EffectBaseDice
[i
]);
1957 mSpellPetAuraMap
[spell
] = pa
;
1961 } while( result
->NextRow() );
1966 sLog
.outString( ">> Loaded %u spell pet auras", count
);
1969 void SpellMgr::LoadPetLevelupSpellMap()
1971 CreatureFamilyEntry
const *creatureFamily
;
1972 SpellEntry
const *spell
;
1975 for (uint32 i
= 0; i
< sCreatureFamilyStore
.GetNumRows(); ++i
)
1977 creatureFamily
= sCreatureFamilyStore
.LookupEntry(i
);
1979 if(!creatureFamily
) // not exist
1982 if(creatureFamily
->petTalentType
< 0) // not hunter pet family
1985 for(uint32 j
= 0; j
< sSpellStore
.GetNumRows(); ++j
)
1987 spell
= sSpellStore
.LookupEntry(j
);
1994 if(spell
->SpellFamilyName
!= SPELLFAMILY_HUNTER
)
1998 if(!(spell
->SpellFamilyFlags
& 0x1000000000000000LL
))
2001 // not Growl or Cower (generics)
2002 if(spell
->SpellIconID
!= 201 && spell
->SpellIconID
!= 958)
2004 switch(creatureFamily
->ID
)
2006 case CREATURE_FAMILY_BAT
: // Bite and Sonic Blast
2007 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1577)
2010 case CREATURE_FAMILY_BEAR
: // Claw and Swipe
2011 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 1562)
2014 case CREATURE_FAMILY_BIRD_OF_PREY
: // Claw and Snatch
2015 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 168)
2018 case CREATURE_FAMILY_BOAR
: // Bite and Gore
2019 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1578)
2022 case CREATURE_FAMILY_CARRION_BIRD
: // Bite and Demoralizing Screech
2023 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1579)
2026 case CREATURE_FAMILY_CAT
: // Claw and Prowl and Rake
2027 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 495 && spell
->SpellIconID
!= 494)
2030 case CREATURE_FAMILY_CHIMAERA
: // Bite and Froststorm Breath
2031 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 62)
2034 case CREATURE_FAMILY_CORE_HOUND
: // Bite and Lava Breath
2035 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1197)
2038 case CREATURE_FAMILY_CRAB
: // Claw and Pin
2039 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 2679)
2042 case CREATURE_FAMILY_CROCOLISK
: // Bite and Bad Attitude
2043 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1581)
2046 case CREATURE_FAMILY_DEVILSAUR
: // Bite and Monstrous Bite
2047 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 599)
2050 case CREATURE_FAMILY_DRAGONHAWK
: // Bite and Fire Breath
2051 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 2128)
2054 case CREATURE_FAMILY_GORILLA
: // Smack and Thunderstomp
2055 if(spell
->SpellIconID
!= 473 && spell
->SpellIconID
!= 148)
2058 case CREATURE_FAMILY_HYENA
: // Bite and Tendon Rip
2059 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 138)
2062 case CREATURE_FAMILY_MOTH
: // Serenity Dust and Smack
2063 if(spell
->SpellIconID
!= 1714 && spell
->SpellIconID
!= 473)
2066 case CREATURE_FAMILY_NETHER_RAY
: // Bite and Nether Shock
2067 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 2027)
2070 case CREATURE_FAMILY_RAPTOR
: // Claw and Savage Rend
2071 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 245)
2074 case CREATURE_FAMILY_RAVAGER
: // Bite and Ravage
2075 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 2253)
2078 case CREATURE_FAMILY_RHINO
: // Smack and Stampede
2079 if(spell
->SpellIconID
!= 473 && spell
->SpellIconID
!= 3066)
2082 case CREATURE_FAMILY_SCORPID
: // Claw and Scorpid Poison
2083 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 163)
2086 case CREATURE_FAMILY_SERPENT
: // Bite and Poison Spit
2087 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 68)
2090 case CREATURE_FAMILY_SILITHID
: // Claw and Venom Web Spray
2091 if(spell
->SpellIconID
!= 262 && (spell
->SpellIconID
!= 272 && spell
->SpellVisual
[0] != 12013))
2094 case CREATURE_FAMILY_SPIDER
: // Bite and Web
2095 if(spell
->SpellIconID
!= 1680 && (spell
->SpellIconID
!= 272 && spell
->SpellVisual
[0] != 684))
2098 case CREATURE_FAMILY_SPIRIT_BEAST
: // Claw and Prowl and Spirit Strike
2099 if(spell
->SpellIconID
!= 262 && spell
->SpellIconID
!= 495 && spell
->SpellIconID
!= 255)
2102 case CREATURE_FAMILY_SPOREBAT
: // Smack and Spore Cloud
2103 if(spell
->SpellIconID
!= 473 && spell
->SpellIconID
!= 2681)
2106 case CREATURE_FAMILY_TALLSTRIDER
: // Claw and Dust Cloud
2107 if(spell
->SpellIconID
!= 262 && (spell
->SpellIconID
!= 157 && !(spell
->Attributes
& 0x4000000)))
2110 case CREATURE_FAMILY_TURTLE
: // Bite and Shell Shield
2111 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1588)
2114 case CREATURE_FAMILY_WARP_STALKER
: // Bite and Warp
2115 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1952)
2118 case CREATURE_FAMILY_WASP
: // Smack and Sting
2119 if(spell
->SpellIconID
!= 473 && spell
->SpellIconID
!= 110)
2122 case CREATURE_FAMILY_WIND_SERPENT
: // Bite and Lightning Breath
2123 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 62)
2126 case CREATURE_FAMILY_WOLF
: // Bite and Furious Howl
2127 if(spell
->SpellIconID
!= 1680 && spell
->SpellIconID
!= 1573)
2130 case CREATURE_FAMILY_WORM
: // Acid Spit and Bite
2131 if(spell
->SpellIconID
!= 636 && spell
->SpellIconID
!= 1680)
2135 sLog
.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily
->ID
);
2140 mPetLevelupSpellMap
[creatureFamily
->ID
][spell
->spellLevel
] = spell
->Id
;
2146 sLog
.outString( ">> Loaded %u pet levelup spells", count
);
2149 /// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc
2150 bool SpellMgr::IsSpellValid(SpellEntry
const* spellInfo
, Player
* pl
, bool msg
)
2156 bool need_check_reagents
= false;
2159 for(int i
=0; i
<3; ++i
)
2161 switch(spellInfo
->Effect
[i
])
2166 // craft spell for crafting non-existed item (break client recipes list show)
2167 case SPELL_EFFECT_CREATE_ITEM
:
2169 if(!ObjectMgr::GetItemPrototype( spellInfo
->EffectItemType
[i
] ))
2174 ChatHandler(pl
).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->EffectItemType
[i
]);
2176 sLog
.outErrorDb("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->EffectItemType
[i
]);
2181 need_check_reagents
= true;
2184 case SPELL_EFFECT_LEARN_SPELL
:
2186 SpellEntry
const* spellInfo2
= sSpellStore
.LookupEntry(spellInfo
->EffectTriggerSpell
[0]);
2187 if( !IsSpellValid(spellInfo2
,pl
,msg
) )
2192 ChatHandler(pl
).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo
->Id
,spellInfo
->EffectTriggerSpell
[0]);
2194 sLog
.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo
->Id
,spellInfo
->EffectTriggerSpell
[0]);
2203 if(need_check_reagents
)
2205 for(int j
= 0; j
< 8; ++j
)
2207 if(spellInfo
->Reagent
[j
] > 0 && !ObjectMgr::GetItemPrototype( spellInfo
->Reagent
[j
] ))
2212 ChatHandler(pl
).PSendSysMessage("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->Reagent
[j
]);
2214 sLog
.outErrorDb("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->Reagent
[j
]);
2224 bool IsSpellAllowedInLocation(SpellEntry
const *spellInfo
,uint32 map_id
,uint32 zone_id
,uint32 area_id
)
2227 if( spellInfo
->AreaId
> 0 && spellInfo
->AreaId
!= zone_id
&& spellInfo
->AreaId
!= area_id
)
2230 // elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup)
2231 if(spellInfo
->SpellFamilyName
==SPELLFAMILY_POTION
)
2233 if(uint32 mask
= spellmgr
.GetSpellElixirMask(spellInfo
->Id
))
2235 if(mask
& ELIXIR_BATTLE_MASK
)
2237 if(spellInfo
->Id
==45373) // Bloodberry Elixir
2238 return zone_id
==4075;
2240 if(mask
& ELIXIR_UNSTABLE_MASK
)
2242 // in the Blade's Edge Mountains Plateaus and Gruul's Lair.
2243 return zone_id
==3522 || map_id
==565;
2245 if(mask
& ELIXIR_SHATTRATH_MASK
)
2247 // in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple, Sunwell Plateau
2248 if(zone_id
==3607 || map_id
==534 || map_id
==564 || zone_id
==4075)
2251 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2255 return mapEntry
->multimap_id
==206;
2258 // elixirs not have another limitations
2263 // special cases zone check (maps checked by multimap common id)
2264 switch(spellInfo
->Id
)
2266 case 41618: // Bottled Nethergon Energy
2267 case 41620: // Bottled Nethergon Vapor
2269 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2273 return mapEntry
->multimap_id
==206;
2275 case 41617: // Cenarion Mana Salve
2276 case 41619: // Cenarion Healing Salve
2278 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2282 return mapEntry
->multimap_id
==207;
2284 case 40216: // Dragonmaw Illusion
2285 case 42016: // Dragonmaw Illusion
2286 return area_id
== 3759 || area_id
== 3966 || area_id
== 3939;
2292 void SpellMgr::LoadSkillLineAbilityMap()
2294 mSkillLineAbilityMap
.clear();
2298 for (uint32 i
= 0; i
< sSkillLineAbilityStore
.GetNumRows(); i
++)
2300 SkillLineAbilityEntry
const *SkillInfo
= sSkillLineAbilityStore
.LookupEntry(i
);
2304 mSkillLineAbilityMap
.insert(SkillLineAbilityMap::value_type(SkillInfo
->spellId
,SkillInfo
));
2309 sLog
.outString(">> Loaded %u SkillLineAbility MultiMap", count
);
2312 DiminishingGroup
GetDiminishingReturnsGroupForSpell(SpellEntry
const* spellproto
, bool triggered
)
2314 // Explicit Diminishing Groups
2315 switch(spellproto
->SpellFamilyName
)
2317 case SPELLFAMILY_MAGE
:
2320 if ((spellproto
->SpellFamilyFlags
& 0x00001000000LL
) && spellproto
->EffectApplyAuraName
[0]==SPELL_AURA_MOD_CONFUSE
)
2321 return DIMINISHING_POLYMORPH
;
2324 case SPELLFAMILY_ROGUE
:
2327 if (spellproto
->SpellFamilyFlags
& 0x00000200000LL
)
2328 return DIMINISHING_KIDNEYSHOT
;
2330 else if (spellproto
->SpellFamilyFlags
& 0x00001000000LL
)
2331 return DIMINISHING_BLIND_CYCLONE
;
2334 case SPELLFAMILY_WARLOCK
:
2337 if (spellproto
->SpellFamilyFlags
& 0x00000080000LL
)
2338 return DIMINISHING_DEATHCOIL
;
2340 else if (spellproto
->SpellFamilyFlags
& 0x40840000000LL
)
2341 return DIMINISHING_WARLOCK_FEAR
;
2343 else if (spellproto
->SpellFamilyFlags
& 0x00080000000LL
)
2344 return DIMINISHING_LIMITONLY
;
2347 case SPELLFAMILY_DRUID
:
2350 if (spellproto
->SpellFamilyFlags
& 0x02000000000LL
)
2351 return DIMINISHING_BLIND_CYCLONE
;
2354 case SPELLFAMILY_WARRIOR
:
2356 // Hamstring - limit duration to 10s in PvP
2357 if (spellproto
->SpellFamilyFlags
& 0x00000000002LL
)
2358 return DIMINISHING_LIMITONLY
;
2366 for (uint8 i
=0;i
<3;++i
)
2368 if (spellproto
->Mechanic
== MECHANIC_STUN
|| spellproto
->EffectMechanic
[i
] == MECHANIC_STUN
)
2369 return triggered
? DIMINISHING_TRIGGER_STUN
: DIMINISHING_CONTROL_STUN
;
2370 else if (spellproto
->Mechanic
== MECHANIC_SLEEP
|| spellproto
->EffectMechanic
[i
] == MECHANIC_SLEEP
)
2371 return DIMINISHING_SLEEP
;
2372 else if (spellproto
->Mechanic
== MECHANIC_ROOT
|| spellproto
->EffectMechanic
[i
] == MECHANIC_ROOT
)
2373 return triggered
? DIMINISHING_TRIGGER_ROOT
: DIMINISHING_CONTROL_ROOT
;
2374 else if (spellproto
->Mechanic
== MECHANIC_FEAR
|| spellproto
->EffectMechanic
[i
] == MECHANIC_FEAR
)
2375 return DIMINISHING_FEAR
;
2376 else if (spellproto
->Mechanic
== MECHANIC_CHARM
|| spellproto
->EffectMechanic
[i
] == MECHANIC_CHARM
)
2377 return DIMINISHING_CHARM
;
2378 else if (spellproto
->Mechanic
== MECHANIC_SILENCE
|| spellproto
->EffectMechanic
[i
] == MECHANIC_SILENCE
)
2379 return DIMINISHING_SILENCE
;
2380 else if (spellproto
->Mechanic
== MECHANIC_DISARM
|| spellproto
->EffectMechanic
[i
] == MECHANIC_DISARM
)
2381 return DIMINISHING_DISARM
;
2382 else if (spellproto
->Mechanic
== MECHANIC_FREEZE
|| spellproto
->EffectMechanic
[i
] == MECHANIC_FREEZE
)
2383 return DIMINISHING_FREEZE
;
2384 else if (spellproto
->Mechanic
== MECHANIC_KNOCKOUT
|| spellproto
->EffectMechanic
[i
] == MECHANIC_KNOCKOUT
||
2385 spellproto
->Mechanic
== MECHANIC_SAPPED
|| spellproto
->EffectMechanic
[i
] == MECHANIC_SAPPED
)
2386 return DIMINISHING_KNOCKOUT
;
2387 else if (spellproto
->Mechanic
== MECHANIC_BANISH
|| spellproto
->EffectMechanic
[i
] == MECHANIC_BANISH
)
2388 return DIMINISHING_BANISH
;
2391 return DIMINISHING_NONE
;
2394 bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group
)
2398 case DIMINISHING_CONTROL_STUN
:
2399 case DIMINISHING_TRIGGER_STUN
:
2400 case DIMINISHING_KIDNEYSHOT
:
2401 case DIMINISHING_SLEEP
:
2402 case DIMINISHING_CONTROL_ROOT
:
2403 case DIMINISHING_TRIGGER_ROOT
:
2404 case DIMINISHING_FEAR
:
2405 case DIMINISHING_WARLOCK_FEAR
:
2406 case DIMINISHING_CHARM
:
2407 case DIMINISHING_POLYMORPH
:
2408 case DIMINISHING_FREEZE
:
2409 case DIMINISHING_KNOCKOUT
:
2410 case DIMINISHING_BLIND_CYCLONE
:
2411 case DIMINISHING_BANISH
:
2412 case DIMINISHING_LIMITONLY
:
2418 DiminishingReturnsType
GetDiminishingReturnsGroupType(DiminishingGroup group
)
2422 case DIMINISHING_BLIND_CYCLONE
:
2423 case DIMINISHING_CONTROL_STUN
:
2424 case DIMINISHING_TRIGGER_STUN
:
2425 case DIMINISHING_KIDNEYSHOT
:
2427 case DIMINISHING_SLEEP
:
2428 case DIMINISHING_CONTROL_ROOT
:
2429 case DIMINISHING_TRIGGER_ROOT
:
2430 case DIMINISHING_FEAR
:
2431 case DIMINISHING_CHARM
:
2432 case DIMINISHING_POLYMORPH
:
2433 case DIMINISHING_SILENCE
:
2434 case DIMINISHING_DISARM
:
2435 case DIMINISHING_DEATHCOIL
:
2436 case DIMINISHING_FREEZE
:
2437 case DIMINISHING_BANISH
:
2438 case DIMINISHING_WARLOCK_FEAR
:
2439 case DIMINISHING_KNOCKOUT
:
2440 return DRTYPE_PLAYER
;