Character re-customization fix
[getmangos.git] / src / game / SpellMgr.cpp
blob0054842bd36c54da01ede7429e56aeb36f9891c8
1 /*
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
19 #include "SpellMgr.h"
20 #include "ObjectMgr.h"
21 #include "SpellAuraDefines.h"
22 #include "ProgressBar.h"
23 #include "Database/DBCStores.h"
24 #include "World.h"
25 #include "Chat.h"
26 #include "Spell.h"
28 SpellMgr::SpellMgr()
32 SpellMgr::~SpellMgr()
36 SpellMgr& SpellMgr::Instance()
38 static SpellMgr spellMgr;
39 return spellMgr;
42 int32 GetSpellDuration(SpellEntry const *spellInfo)
44 if(!spellInfo)
45 return 0;
46 SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex);
47 if(!du)
48 return 0;
49 return (du->Duration[0] == -1) ? -1 : abs(du->Duration[0]);
52 int32 GetSpellMaxDuration(SpellEntry const *spellInfo)
54 if(!spellInfo)
55 return 0;
56 SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex);
57 if(!du)
58 return 0;
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)
68 return 0;
70 int32 castTime = spellCastTimeEntry->CastTime;
72 if (spell)
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));
79 else
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())))
87 castTime += 500;
89 return (castTime > 0) ? uint32(castTime) : 0;
92 bool IsPassiveSpell(uint32 spellId)
94 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
95 if (!spellInfo)
96 return false;
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])
111 return false;
113 return true;
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;
125 else return diff;
128 SpellSpecific GetSpellSpecific(uint32 spellId)
130 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
131 if(!spellInfo)
132 return SPELL_NORMAL;
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;
145 break;
147 case SPELLFAMILY_WARRIOR:
149 if (spellInfo->SpellFamilyFlags & 0x00008000010000LL)
150 return SPELL_POSITIVE_SHOUT;
152 break;
154 case SPELLFAMILY_WARLOCK:
156 // only warlock curses have this
157 if (spellInfo->Dispel == DISPEL_CURSE)
158 return SPELL_CURSE;
160 // family flag 37 (only part spells have family name)
161 if (spellInfo->SpellFamilyFlags & 0x2000000000LL)
162 return SPELL_WARLOCK_ARMOR;
164 break;
166 case SPELLFAMILY_HUNTER:
168 // only hunter stings have this
169 if (spellInfo->Dispel == DISPEL_POISON)
170 return SPELL_STING;
172 break;
174 case SPELLFAMILY_PALADIN:
176 if (IsSealSpell(spellInfo))
177 return SPELL_SEAL;
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)
189 return SPELL_AURA;
191 break;
193 case SPELLFAMILY_SHAMAN:
195 if (IsElementalShield(spellInfo))
196 return SPELL_ELEMENTAL_SHIELD;
198 break;
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)
215 return SPELL_ASPECT;
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))
227 return sp;
229 return SPELL_NORMAL;
232 bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2)
234 switch(spellSpec1)
236 case SPELL_SEAL:
237 case SPELL_BLESSING:
238 case SPELL_AURA:
239 case SPELL_STING:
240 case SPELL_CURSE:
241 case SPELL_ASPECT:
242 case SPELL_TRACKER:
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;
259 default:
260 return false;
264 bool IsPositiveTarget(uint32 targetA, uint32 targetB)
266 // non-positive targets
267 switch(targetA)
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:
276 return false;
277 case TARGET_ALL_AROUND_CASTER:
278 return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER);
279 default:
280 break;
282 if (targetB)
283 return IsPositiveTarget(targetB, 0);
284 return true;
287 bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
289 SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId);
290 if (!spellproto) return false;
292 switch(spellId)
294 case 23333: // BG spell
295 case 23335: // BG spell
296 case 34976: // BG spell
297 return true;
298 case 28441: // not positive dummy spell
299 case 37675: // Chaos Blast
300 return false;
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:
311 return true;
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)
329 return false;
330 default:
331 break;
333 } break;
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)
339 return false;
340 break;
342 case SPELL_AURA_ADD_TARGET_TRIGGER:
343 return true;
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))
358 return false;
362 break;
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)
365 break;
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
370 // Petrification
371 if(spellproto->Id == 17624)
372 return false;
373 break;
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:
381 return false;
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)
385 return false;
386 break;
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)
390 return false;
391 // but not this if this first effect (don't found batter check)
392 if(spellproto->Attributes & 0x4000000 && effIndex==0)
393 return false;
394 break;
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)
401 return false;
403 break;
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)
412 return false;
414 break;
415 case SPELL_AURA_MECHANIC_IMMUNITY:
417 // non-positive immunities
418 switch(spellproto->EffectMiscValue[effIndex])
420 case MECHANIC_BANDAGE:
421 case MECHANIC_SHIELD:
422 case MECHANIC_MOUNT:
423 case MECHANIC_INVULNERABILITY:
424 return false;
425 default:
426 break;
428 } break;
429 case SPELL_AURA_ADD_FLAT_MODIFIER: // mods
430 case SPELL_AURA_ADD_PCT_MODIFIER:
432 // non-positive mods
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)
437 return false;
438 break;
439 default:
440 break;
442 } break;
443 case SPELL_AURA_MOD_HEALING_PCT:
444 if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) < 0)
445 return false;
446 break;
447 case SPELL_AURA_MOD_SKILL:
448 if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) < 0)
449 return false;
450 break;
451 case SPELL_AURA_FORCE_REACTION:
452 if(spellproto->Id==42792) // Recently Dropped Flag (prevent cancel)
453 return false;
454 break;
455 default:
456 break;
458 break;
460 default:
461 break;
464 // non-positive targets
465 if(!IsPositiveTarget(spellproto->EffectImplicitTargetA[effIndex],spellproto->EffectImplicitTargetB[effIndex]))
466 return false;
468 // AttributesEx check
469 if(spellproto->AttributesEx & (1<<7))
470 return false;
472 // ok, positive
473 return true;
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))
485 return false;
486 return true;
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 )
493 return true;
495 // TODO - need found Judgements rule
496 switch(GetSpellSpecific(spellInfo->Id))
498 case SPELL_JUDGEMENT:
499 return true;
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))
506 return true;
508 return false;
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 )
517 return true;
519 // TODO - need found Judgements rule
520 SpellSpecific spec1 = GetSpellSpecific(spellInfo1->Id);
521 // spell with single target specific types
522 switch(spec1)
524 case SPELL_JUDGEMENT:
525 if(GetSpellSpecific(spellInfo2->Id) == spec1)
526 return true;
527 break;
530 return false;
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) )
539 return 0;
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
547 return 0;
549 bool actAsShifted = false;
550 if (form > 0)
552 SpellShapeshiftEntry const *shapeInfo = sSpellShapeshiftStore.LookupEntry(form);
553 if (!shapeInfo)
555 sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form);
556 return 0;
558 actAsShifted = !(shapeInfo->flags1 & 1); // shapeshift acts as normal form for spells
561 if(actAsShifted)
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;
568 else
570 // needs shapeshift
571 if(!(spellInfo->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && spellInfo->Stances != 0)
572 return SPELL_FAILED_ONLY_SHAPESHIFT;
575 return 0;
578 void SpellMgr::LoadSpellTargetPositions()
580 mSpellTargetPositions.clear(); // need for reload case
582 uint32 count = 0;
584 // 0 1 2 3 4 5
585 QueryResult *result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position");
586 if( !result )
589 barGoLink bar( 1 );
591 bar.step();
593 sLog.outString();
594 sLog.outString( ">> Loaded %u spell target coordinates", count );
595 return;
598 barGoLink bar( result->GetRowCount() );
602 Field *fields = result->Fetch();
604 bar.step();
606 ++count;
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);
619 if(!spellInfo)
621 sLog.outErrorDb("Spell (ID:%u) listed in `spell_target_position` does not exist.",Spell_ID);
622 continue;
625 bool found = false;
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 )
630 found = true;
631 break;
634 if(!found)
636 sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID);
637 continue;
640 MapEntry const* mapEntry = sMapStore.LookupEntry(st.target_mapId);
641 if(!mapEntry)
643 sLog.outErrorDb("Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Spell_ID,st.target_mapId);
644 continue;
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);
650 continue;
653 mSpellTargetPositions[Spell_ID] = st;
655 } while( result->NextRow() );
657 delete result;
659 sLog.outString();
660 sLog.outString( ">> Loaded %u spell teleport coordinates", count );
663 void SpellMgr::LoadSpellAffects()
665 mSpellAffectMap.clear(); // need for reload case
667 uint32 count = 0;
669 // 0 1 2 3 4
670 QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellClassMask0, SpellClassMask1, SpellClassMask2 FROM spell_affect");
671 if( !result )
674 barGoLink bar( 1 );
676 bar.step();
678 sLog.outString();
679 sLog.outString( ">> Loaded %u spell affect definitions", count );
680 return;
683 barGoLink bar( result->GetRowCount() );
687 Field *fields = result->Fetch();
689 bar.step();
691 uint16 entry = fields[0].GetUInt16();
692 uint8 effectId = fields[1].GetUInt8();
694 SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry);
696 if (!spellInfo)
698 sLog.outErrorDb("Spell %u listed in `spell_affect` does not exist", entry);
699 continue;
702 if (effectId >= 3)
704 sLog.outErrorDb("Spell %u listed in `spell_affect` have invalid effect index (%u)", entry,effectId);
705 continue;
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);
714 continue;
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;
724 switch (effectId)
726 case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break;
727 case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break;
728 case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break;
729 default:
730 continue;
732 if(ptr[0] == affect.SpellClassMask[0] || ptr[1] == affect.SpellClassMask[1] || ptr[2] == affect.SpellClassMask[2])
734 char text[]="ABC";
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);
736 continue;
739 mSpellAffectMap[(entry<<8) + effectId] = affect;
741 ++count;
742 } while( result->NextRow() );
744 delete result;
746 sLog.outString();
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);
752 if (!spellInfo)
753 continue;
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) )
761 continue;
763 uint32 const *ptr = 0;
764 switch (effectId)
766 case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break;
767 case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break;
768 case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break;
769 default:
770 continue;
772 if(ptr[0] || ptr[1] || ptr[2])
773 continue;
775 if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end())
776 continue;
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)
787 return false;
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)
792 return false;
794 // true
795 if (mod->mask & spellInfo->SpellFamilyFlags ||
796 mod->mask2 & spellInfo->SpellFamilyFlags2)
797 return true;
799 return false;
802 void SpellMgr::LoadSpellProcEvents()
804 mSpellProcEventMap.clear(); // need for reload case
806 uint32 count = 0;
808 // 0 1 2 3 4 5 6 7 8
809 QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown FROM spell_proc_event");
810 if( !result )
813 barGoLink bar( 1 );
815 bar.step();
817 sLog.outString();
818 sLog.outString( ">> Loaded %u spell proc event conditions", count );
819 return;
822 barGoLink bar( result->GetRowCount() );
826 Field *fields = result->Fetch();
828 bar.step();
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);
835 continue;
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;
851 ++count;
852 } while( result->NextRow() );
854 delete result;
856 sLog.outString();
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);
864 if (!spellInfo)
865 continue;
867 bool found = false;
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 )
873 found = true;
874 break;
878 if(!found)
879 continue;
881 if(GetSpellProcEvent(id))
882 continue;
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)
892 return false;
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))
897 return false;
898 if(spellProcEvent->category && (!procSpell || procSpell->Category != spellProcEvent->category))
899 return false;
900 if(spellProcEvent->skillId)
902 if (!procSpell)
903 return false;
905 SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(procSpell->Id);
906 SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(procSpell->Id);
908 bool found = false;
909 for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
911 if(_spell_idx->second->skillId == spellProcEvent->skillId)
913 found = true;
914 break;
917 if (!found)
918 return false;
920 if(spellProcEvent->spellFamilyName && (!procSpell || spellProcEvent->spellFamilyName != procSpell->SpellFamilyName))
921 return false;
922 if(spellProcEvent->spellFamilyMask && (!procSpell || (spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags) == 0))
923 return false;
925 return true;
928 void SpellMgr::LoadSpellElixirs()
930 mSpellElixirs.clear(); // need for reload case
932 uint32 count = 0;
934 // 0 1
935 QueryResult *result = WorldDatabase.Query("SELECT entry, mask FROM spell_elixir");
936 if( !result )
939 barGoLink bar( 1 );
941 bar.step();
943 sLog.outString();
944 sLog.outString( ">> Loaded %u spell elixir definitions", count );
945 return;
948 barGoLink bar( result->GetRowCount() );
952 Field *fields = result->Fetch();
954 bar.step();
956 uint16 entry = fields[0].GetUInt16();
957 uint8 mask = fields[1].GetUInt8();
959 SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry);
961 if (!spellInfo)
963 sLog.outErrorDb("Spell %u listed in `spell_elixir` does not exist", entry);
964 continue;
967 mSpellElixirs[entry] = mask;
969 ++count;
970 } while( result->NextRow() );
972 delete result;
974 sLog.outString();
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 );
985 sLog.outString();
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)
1000 return false;
1001 if(IsProfessionSpell(spellInfo->Id))
1002 return false;
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)
1010 return false;
1011 // Druid form Spell
1012 if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID
1013 && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
1014 && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
1015 return false;
1016 // Rogue Stealth
1017 if(spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE
1018 && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
1019 && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
1020 return false;
1022 return true;
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)
1031 return false;
1033 if(spellInfo_1->Id == spellId_2)
1034 return false;
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)
1039 return false;
1041 // Resurrection sickness
1042 if((spellInfo_1->Id == SPELL_ID_PASSIVE_RESURRECTION_SICKNESS) != (spellInfo_2->Id==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS))
1043 return false;
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
1053 // Thunderfury
1054 if( spellInfo_1->Id == 21992 && spellInfo_2->Id == 27648 || spellInfo_2->Id == 21992 && spellInfo_1->Id == 27648 )
1055 return false;
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 )
1060 return false;
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 ) )
1066 return false;
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 ) )
1072 return false;
1074 // Personalized Weather (thunder effect should overwrite rainy aura)
1075 if(spellInfo_1->SpellIconID == 2606 && spellInfo_2->SpellIconID == 2606)
1076 return false;
1078 // Brood Affliction: Bronze
1079 if( (spellInfo_1->Id == 23170 && spellInfo_2->Id == 23171) ||
1080 (spellInfo_2->Id == 23170 && spellInfo_1->Id == 23171) )
1081 return false;
1083 break;
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)
1089 return false;
1091 // Improved Hamstring -> Hamstring (multi-family check)
1092 if( (spellInfo_2->SpellFamilyFlags & 2) && spellInfo_1->Id == 23694 )
1093 return false;
1095 break;
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 )
1101 return false;
1103 // Dragonmaw Illusion (multi-family check)
1104 if (spellId_1 == 40216 && spellId_2 == 42016 )
1105 return false;
1107 break;
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 )
1113 return false;
1115 break;
1117 case SPELLFAMILY_HUNTER:
1119 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1120 if( spellInfo_1->Id == 19410 && spellInfo_2->Id == 5116 )
1121 return false;
1123 // Improved Wing Clip -> Wing Clip (multi-family check)
1124 if( (spellInfo_2->SpellFamilyFlags & 0x40) && spellInfo_1->Id == 19229 )
1125 return false;
1126 break;
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 )
1132 return false;
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)
1136 return false;
1138 break;
1141 break;
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) )
1148 return false;
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) )
1153 return false;
1155 // Detect Invisibility and Mana Shield (multi-family check)
1156 if( spellInfo_2->Id == 132 && spellInfo_1->SpellIconID == 209 && spellInfo_1->SpellVisual[0] == 968 )
1157 return false;
1159 // Combustion and Fire Protection Aura (multi-family check)
1160 if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual[0] == 321 )
1161 return false;
1163 break;
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 )
1170 return false;
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 )
1181 return false;
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) )
1186 return false;
1188 // Detect Invisibility and Mana Shield (multi-family check)
1189 if( spellInfo_1->Id == 132 && spellInfo_2->SpellIconID == 209 && spellInfo_2->SpellVisual[0] == 968 )
1190 return false;
1191 break;
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) )
1198 return false;
1200 // Battle Shout and Rampage
1201 if( (spellInfo_1->SpellIconID == 456 && spellInfo_2->SpellIconID == 2006) ||
1202 (spellInfo_2->SpellIconID == 456 && spellInfo_1->SpellIconID == 2006) )
1203 return false;
1206 // Hamstring -> Improved Hamstring (multi-family check)
1207 if( (spellInfo_1->SpellFamilyFlags & 2) && spellInfo_2->Id == 23694 )
1208 return false;
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 )
1212 return false;
1214 // Bloodlust and Bloodthirst (multi-family check)
1215 if( spellInfo_2->Id == 2825 && spellInfo_1->SpellIconID == 38 && spellInfo_1->SpellVisual[0] == 0 )
1216 return false;
1218 break;
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) )
1225 return false;
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) )
1230 return false;
1232 break;
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) )
1239 return false;
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))
1244 return false;
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 )
1248 return false;
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 )
1252 return false;
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 )
1256 return false;
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 )
1261 return false;
1263 // Dragonmaw Illusion (multi-family check)
1264 if (spellId_1 == 42016 && spellId_2 == 40216 )
1265 return false;
1267 break;
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 )
1273 return false;
1276 // Garrote -> Garrote-Silence (multi-family check)
1277 if( spellInfo_1->SpellIconID == 498 && spellInfo_2->SpellIconID == 498 && spellInfo_2->SpellVisual[0] == 0 )
1278 return false;
1279 break;
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) )
1286 return false;
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) )
1291 return false;
1293 // Bestial Wrath
1294 if( spellInfo_1->SpellIconID == 1680 && spellInfo_2->SpellIconID == 1680 )
1295 return false;
1298 // Wing Clip -> Improved Wing Clip (multi-family check)
1299 if( (spellInfo_1->SpellFamilyFlags & 0x40) && spellInfo_2->Id == 19229 )
1300 return false;
1302 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1303 if( spellInfo_2->Id == 19410 && spellInfo_1->Id == 5116 )
1304 return false;
1305 break;
1306 case SPELLFAMILY_PALADIN:
1307 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN )
1309 // Paladin Seals
1310 if( IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2) )
1311 return true;
1313 // Combustion and Fire Protection Aura (multi-family check)
1314 if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 )
1315 return false;
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 )
1319 return false;
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)
1323 return false;
1324 break;
1325 case SPELLFAMILY_SHAMAN:
1326 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_SHAMAN )
1328 // shaman shields
1329 if( IsElementalShield(spellInfo_1) && IsElementalShield(spellInfo_2) )
1330 return true;
1332 // Windfury weapon
1333 if( spellInfo_1->SpellIconID==220 && spellInfo_2->SpellIconID==220 &&
1334 spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags )
1335 return false;
1337 // Bloodlust and Bloodthirst (multi-family check)
1338 if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual[0] == 0 )
1339 return false;
1340 break;
1341 default:
1342 break;
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 )
1356 isModifier = true;
1359 if (!isModifier)
1360 return true;
1363 if (IsRankSpellDueToSpell(spellInfo_1, spellId_2))
1364 return true;
1366 if (spellInfo_1->SpellFamilyName == 0 || spellInfo_2->SpellFamilyName == 0)
1367 return false;
1369 if (spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
1370 return false;
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])
1377 return false;
1379 return true;
1382 bool SpellMgr::IsProfessionSpell(uint32 spellId)
1384 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
1385 if(!spellInfo)
1386 return false;
1388 if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL)
1389 return false;
1391 uint32 skill = spellInfo->EffectMiscValue[1];
1393 return IsProfessionSkill(skill);
1396 bool SpellMgr::IsPrimaryProfessionSpell(uint32 spellId)
1398 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
1399 if(!spellInfo)
1400 return false;
1402 if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL)
1403 return false;
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))
1419 return spellInfo;
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;
1431 break;
1435 // not required
1436 if(!needRankSelection)
1437 return spellInfo;
1439 for(uint32 nextSpellId = spellInfo->Id; nextSpellId != 0; nextSpellId = GetPrevSpellInChain(nextSpellId))
1441 SpellEntry const *nextSpellInfo = sSpellStore.LookupEntry(nextSpellId);
1442 if(!nextSpellInfo)
1443 break;
1445 // if found appropriate level
1446 if(playerLevel + 10 >= nextSpellInfo->spellLevel)
1447 return nextSpellInfo;
1449 // one rank less then
1452 // not found
1453 return NULL;
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");
1462 if(result == NULL)
1464 barGoLink bar( 1 );
1465 bar.step();
1467 sLog.outString();
1468 sLog.outString( ">> Loaded 0 spell chain records" );
1469 sLog.outErrorDb("`spell_chains` table is empty!");
1470 return;
1473 uint32 count = 0;
1475 barGoLink bar( result->GetRowCount() );
1478 bar.step();
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);
1492 continue;
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);
1499 continue;
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);
1506 continue;
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);
1516 continue;
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);
1523 continue;
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);
1533 continue;
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);
1542 continue;
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);
1549 continue;
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);
1556 continue;
1561 mSpellChains[spell_id] = node;
1563 if(node.prev)
1564 mSpellChainsNext.insert(SpellChainMapNext::value_type(node.prev,spell_id));
1566 if(node.req)
1567 mSpellChainsNext.insert(SpellChainMapNext::value_type(node.req,spell_id));
1569 ++count;
1570 } while( result->NextRow() );
1572 // additional integrity checks
1573 for(SpellChainMap::iterator i = mSpellChains.begin(); i != mSpellChains.end(); ++i)
1575 if(i->second.prev)
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);
1597 if(i->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);
1620 delete result;
1622 sLog.outString();
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);
1636 if(!entry)
1637 continue;
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 )
1646 dbc_node.value = 1;
1647 else
1648 dbc_node.value = (entry->EffectBasePoints[i]+1)*75;
1649 dbc_node.maxvalue = (entry->EffectBasePoints[i]+1)*75;
1651 mSpellLearnSkills[spell] = dbc_node;
1652 ++dbc_count;
1653 break;
1658 sLog.outString();
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");
1667 if(!result)
1669 barGoLink bar( 1 );
1670 bar.step();
1672 sLog.outString();
1673 sLog.outString( ">> Loaded 0 spell learn spells" );
1674 sLog.outErrorDb("`spell_learn_spell` table is empty!");
1675 return;
1678 uint32 count = 0;
1680 barGoLink bar( result->GetRowCount() );
1683 bar.step();
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);
1695 continue;
1698 if(!sSpellStore.LookupEntry(node.spell))
1700 sLog.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",node.spell);
1701 continue;
1704 mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spell_id,node));
1706 ++count;
1707 } while( result->NextRow() );
1709 delete result;
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);
1717 if(!entry)
1718 continue;
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);
1731 bool found = false;
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);
1738 found = true;
1739 break;
1743 if(!found) // add new spell-spell pair if not found
1745 mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spell,dbc_node));
1746 ++dbc_count;
1752 sLog.outString();
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
1760 uint32 count = 0;
1762 QueryResult *result = WorldDatabase.Query("SELECT entry,type,targetEntry FROM spell_script_target");
1764 if(!result)
1766 barGoLink bar(1);
1768 bar.step();
1770 sLog.outString();
1771 sLog.outErrorDb(">> Loaded 0 SpellScriptTarget. DB table `spell_script_target` is empty.");
1772 return;
1775 barGoLink bar(result->GetRowCount());
1779 Field *fields = result->Fetch();
1780 bar.step();
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);
1788 if(!spellProto)
1790 sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not exist.",spellId,targetEntry);
1791 continue;
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 )
1802 targetfound = true;
1803 break;
1806 if(!targetfound)
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);
1809 continue;
1812 if( type >= MAX_SPELL_TARGET_TYPE )
1814 sLog.outErrorDb("Table `spell_script_target`: target type %u for TargetEntry %u is incorrect.",type,targetEntry);
1815 continue;
1818 switch(type)
1820 case SPELL_TARGET_TYPE_GAMEOBJECT:
1822 if( targetEntry==0 )
1823 break;
1825 if(!sGOStorage.LookupEntry<GameObjectInfo>(targetEntry))
1827 sLog.outErrorDb("Table `spell_script_target`: gameobject template entry %u does not exist.",targetEntry);
1828 continue;
1830 break;
1832 default:
1834 if( targetEntry==0 )
1836 sLog.outErrorDb("Table `spell_script_target`: target entry == 0 for not GO target type (%u).",type);
1837 continue;
1839 if(!sCreatureStorage.LookupEntry<CreatureInfo>(targetEntry))
1841 sLog.outErrorDb("Table `spell_script_target`: creature template entry %u does not exist.",targetEntry);
1842 continue;
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);
1849 continue;
1851 break;
1855 mSpellScriptTarget.insert(SpellScriptTarget::value_type(spellId,SpellTargetEntry(SpellTargetType(type),targetEntry)));
1857 ++count;
1858 } while (result->NextRow());
1860 delete result;
1862 // Check all spells
1863 /* Disabled (lot errors at this moment)
1864 for(uint32 i = 1; i < sSpellStore.nCount; ++i)
1866 SpellEntry const * spellInfo = sSpellStore.LookupEntry(i);
1867 if(!spellInfo)
1868 continue;
1870 bool found = false;
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);
1877 if(lower==upper)
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
1887 sLog.outString();
1888 sLog.outString(">> Loaded %u Spell Script Targets", count);
1891 void SpellMgr::LoadSpellPetAuras()
1893 mSpellPetAuraMap.clear(); // need for reload case
1895 uint32 count = 0;
1897 // 0 1 2
1898 QueryResult *result = WorldDatabase.Query("SELECT spell, pet, aura FROM spell_pet_auras");
1899 if( !result )
1902 barGoLink bar( 1 );
1904 bar.step();
1906 sLog.outString();
1907 sLog.outString( ">> Loaded %u spell pet auras", count );
1908 return;
1911 barGoLink bar( result->GetRowCount() );
1915 Field *fields = result->Fetch();
1917 bar.step();
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);
1928 else
1930 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
1931 if (!spellInfo)
1933 sLog.outErrorDb("Spell %u listed in `spell_pet_auras` does not exist", spell);
1934 continue;
1936 int i = 0;
1937 for(; i < 3; ++i)
1938 if((spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA &&
1939 spellInfo->EffectApplyAuraName[i] == SPELL_AURA_DUMMY) ||
1940 spellInfo->Effect[i] == SPELL_EFFECT_DUMMY)
1941 break;
1943 if(i == 3)
1945 sLog.outError("Spell %u listed in `spell_pet_auras` does not have dummy aura or dummy effect", spell);
1946 continue;
1949 SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(aura);
1950 if (!spellInfo2)
1952 sLog.outErrorDb("Aura %u listed in `spell_pet_auras` does not exist", aura);
1953 continue;
1956 PetAura pa(pet, aura, spellInfo->EffectImplicitTargetA[i] == TARGET_PET, spellInfo->EffectBasePoints[i] + spellInfo->EffectBaseDice[i]);
1957 mSpellPetAuraMap[spell] = pa;
1960 ++count;
1961 } while( result->NextRow() );
1963 delete result;
1965 sLog.outString();
1966 sLog.outString( ">> Loaded %u spell pet auras", count );
1969 void SpellMgr::LoadPetLevelupSpellMap()
1971 CreatureFamilyEntry const *creatureFamily;
1972 SpellEntry const *spell;
1973 uint32 count = 0;
1975 for (uint32 i = 0; i < sCreatureFamilyStore.GetNumRows(); ++i)
1977 creatureFamily = sCreatureFamilyStore.LookupEntry(i);
1979 if(!creatureFamily) // not exist
1980 continue;
1982 if(creatureFamily->petTalentType < 0) // not hunter pet family
1983 continue;
1985 for(uint32 j = 0; j < sSpellStore.GetNumRows(); ++j)
1987 spell = sSpellStore.LookupEntry(j);
1989 // not exist
1990 if(!spell)
1991 continue;
1993 // not hunter spell
1994 if(spell->SpellFamilyName != SPELLFAMILY_HUNTER)
1995 continue;
1997 // not pet spell
1998 if(!(spell->SpellFamilyFlags & 0x1000000000000000LL))
1999 continue;
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)
2008 continue;
2009 break;
2010 case CREATURE_FAMILY_BEAR: // Claw and Swipe
2011 if(spell->SpellIconID != 262 && spell->SpellIconID != 1562)
2012 continue;
2013 break;
2014 case CREATURE_FAMILY_BIRD_OF_PREY: // Claw and Snatch
2015 if(spell->SpellIconID != 262 && spell->SpellIconID != 168)
2016 continue;
2017 break;
2018 case CREATURE_FAMILY_BOAR: // Bite and Gore
2019 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578)
2020 continue;
2021 break;
2022 case CREATURE_FAMILY_CARRION_BIRD: // Bite and Demoralizing Screech
2023 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579)
2024 continue;
2025 break;
2026 case CREATURE_FAMILY_CAT: // Claw and Prowl and Rake
2027 if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494)
2028 continue;
2029 break;
2030 case CREATURE_FAMILY_CHIMAERA: // Bite and Froststorm Breath
2031 if(spell->SpellIconID != 1680 && spell->SpellIconID != 62)
2032 continue;
2033 break;
2034 case CREATURE_FAMILY_CORE_HOUND: // Bite and Lava Breath
2035 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197)
2036 continue;
2037 break;
2038 case CREATURE_FAMILY_CRAB: // Claw and Pin
2039 if(spell->SpellIconID != 262 && spell->SpellIconID != 2679)
2040 continue;
2041 break;
2042 case CREATURE_FAMILY_CROCOLISK: // Bite and Bad Attitude
2043 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581)
2044 continue;
2045 break;
2046 case CREATURE_FAMILY_DEVILSAUR: // Bite and Monstrous Bite
2047 if(spell->SpellIconID != 1680 && spell->SpellIconID != 599)
2048 continue;
2049 break;
2050 case CREATURE_FAMILY_DRAGONHAWK: // Bite and Fire Breath
2051 if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128)
2052 continue;
2053 break;
2054 case CREATURE_FAMILY_GORILLA: // Smack and Thunderstomp
2055 if(spell->SpellIconID != 473 && spell->SpellIconID != 148)
2056 continue;
2057 break;
2058 case CREATURE_FAMILY_HYENA: // Bite and Tendon Rip
2059 if(spell->SpellIconID != 1680 && spell->SpellIconID != 138)
2060 continue;
2061 break;
2062 case CREATURE_FAMILY_MOTH: // Serenity Dust and Smack
2063 if(spell->SpellIconID != 1714 && spell->SpellIconID != 473)
2064 continue;
2065 break;
2066 case CREATURE_FAMILY_NETHER_RAY: // Bite and Nether Shock
2067 if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027)
2068 continue;
2069 break;
2070 case CREATURE_FAMILY_RAPTOR: // Claw and Savage Rend
2071 if(spell->SpellIconID != 262 && spell->SpellIconID != 245)
2072 continue;
2073 break;
2074 case CREATURE_FAMILY_RAVAGER: // Bite and Ravage
2075 if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253)
2076 continue;
2077 break;
2078 case CREATURE_FAMILY_RHINO: // Smack and Stampede
2079 if(spell->SpellIconID != 473 && spell->SpellIconID != 3066)
2080 continue;
2081 break;
2082 case CREATURE_FAMILY_SCORPID: // Claw and Scorpid Poison
2083 if(spell->SpellIconID != 262 && spell->SpellIconID != 163)
2084 continue;
2085 break;
2086 case CREATURE_FAMILY_SERPENT: // Bite and Poison Spit
2087 if(spell->SpellIconID != 1680 && spell->SpellIconID != 68)
2088 continue;
2089 break;
2090 case CREATURE_FAMILY_SILITHID: // Claw and Venom Web Spray
2091 if(spell->SpellIconID != 262 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 12013))
2092 continue;
2093 break;
2094 case CREATURE_FAMILY_SPIDER: // Bite and Web
2095 if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684))
2096 continue;
2097 break;
2098 case CREATURE_FAMILY_SPIRIT_BEAST: // Claw and Prowl and Spirit Strike
2099 if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 255)
2100 continue;
2101 break;
2102 case CREATURE_FAMILY_SPOREBAT: // Smack and Spore Cloud
2103 if(spell->SpellIconID != 473 && spell->SpellIconID != 2681)
2104 continue;
2105 break;
2106 case CREATURE_FAMILY_TALLSTRIDER: // Claw and Dust Cloud
2107 if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && !(spell->Attributes & 0x4000000)))
2108 continue;
2109 break;
2110 case CREATURE_FAMILY_TURTLE: // Bite and Shell Shield
2111 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1588)
2112 continue;
2113 break;
2114 case CREATURE_FAMILY_WARP_STALKER: // Bite and Warp
2115 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1952)
2116 continue;
2117 break;
2118 case CREATURE_FAMILY_WASP: // Smack and Sting
2119 if(spell->SpellIconID != 473 && spell->SpellIconID != 110)
2120 continue;
2121 break;
2122 case CREATURE_FAMILY_WIND_SERPENT: // Bite and Lightning Breath
2123 if(spell->SpellIconID != 1680 && spell->SpellIconID != 62)
2124 continue;
2125 break;
2126 case CREATURE_FAMILY_WOLF: // Bite and Furious Howl
2127 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573)
2128 continue;
2129 break;
2130 case CREATURE_FAMILY_WORM: // Acid Spit and Bite
2131 if(spell->SpellIconID != 636 && spell->SpellIconID != 1680)
2132 continue;
2133 break;
2134 default:
2135 sLog.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily->ID);
2136 continue;
2140 mPetLevelupSpellMap[creatureFamily->ID][spell->spellLevel] = spell->Id;
2141 count++;
2145 sLog.outString();
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)
2152 // not exist
2153 if(!spellInfo)
2154 return false;
2156 bool need_check_reagents = false;
2158 // check effects
2159 for(int i=0; i<3; ++i)
2161 switch(spellInfo->Effect[i])
2163 case 0:
2164 continue;
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] ))
2171 if(msg)
2173 if(pl)
2174 ChatHandler(pl).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->EffectItemType[i]);
2175 else
2176 sLog.outErrorDb("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->EffectItemType[i]);
2178 return false;
2181 need_check_reagents = true;
2182 break;
2184 case SPELL_EFFECT_LEARN_SPELL:
2186 SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(spellInfo->EffectTriggerSpell[0]);
2187 if( !IsSpellValid(spellInfo2,pl,msg) )
2189 if(msg)
2191 if(pl)
2192 ChatHandler(pl).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[0]);
2193 else
2194 sLog.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[0]);
2196 return false;
2198 break;
2203 if(need_check_reagents)
2205 for(int j = 0; j < 8; ++j)
2207 if(spellInfo->Reagent[j] > 0 && !ObjectMgr::GetItemPrototype( spellInfo->Reagent[j] ))
2209 if(msg)
2211 if(pl)
2212 ChatHandler(pl).PSendSysMessage("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->Reagent[j]);
2213 else
2214 sLog.outErrorDb("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->Reagent[j]);
2216 return false;
2221 return true;
2224 bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id)
2226 // normal case
2227 if( spellInfo->AreaId > 0 && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id )
2228 return false;
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)
2249 return true;
2251 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2252 if(!mapEntry)
2253 return false;
2255 return mapEntry->multimap_id==206;
2258 // elixirs not have another limitations
2259 return true;
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);
2270 if(!mapEntry)
2271 return false;
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);
2279 if(!mapEntry)
2280 return false;
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;
2289 return true;
2292 void SpellMgr::LoadSkillLineAbilityMap()
2294 mSkillLineAbilityMap.clear();
2296 uint32 count = 0;
2298 for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); i++)
2300 SkillLineAbilityEntry const *SkillInfo = sSkillLineAbilityStore.LookupEntry(i);
2301 if(!SkillInfo)
2302 continue;
2304 mSkillLineAbilityMap.insert(SkillLineAbilityMap::value_type(SkillInfo->spellId,SkillInfo));
2305 ++count;
2308 sLog.outString();
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:
2319 // Polymorph
2320 if ((spellproto->SpellFamilyFlags & 0x00001000000LL) && spellproto->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE)
2321 return DIMINISHING_POLYMORPH;
2322 break;
2324 case SPELLFAMILY_ROGUE:
2326 // Kidney Shot
2327 if (spellproto->SpellFamilyFlags & 0x00000200000LL)
2328 return DIMINISHING_KIDNEYSHOT;
2329 // Blind
2330 else if (spellproto->SpellFamilyFlags & 0x00001000000LL)
2331 return DIMINISHING_BLIND_CYCLONE;
2332 break;
2334 case SPELLFAMILY_WARLOCK:
2336 // Death Coil
2337 if (spellproto->SpellFamilyFlags & 0x00000080000LL)
2338 return DIMINISHING_DEATHCOIL;
2339 // Fear
2340 else if (spellproto->SpellFamilyFlags & 0x40840000000LL)
2341 return DIMINISHING_WARLOCK_FEAR;
2342 // Curses/etc
2343 else if (spellproto->SpellFamilyFlags & 0x00080000000LL)
2344 return DIMINISHING_LIMITONLY;
2345 break;
2347 case SPELLFAMILY_DRUID:
2349 // Cyclone
2350 if (spellproto->SpellFamilyFlags & 0x02000000000LL)
2351 return DIMINISHING_BLIND_CYCLONE;
2352 break;
2354 case SPELLFAMILY_WARRIOR:
2356 // Hamstring - limit duration to 10s in PvP
2357 if (spellproto->SpellFamilyFlags & 0x00000000002LL)
2358 return DIMINISHING_LIMITONLY;
2359 break;
2361 default:
2362 break;
2365 // Get by mechanic
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)
2396 switch(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:
2413 return true;
2415 return false;
2418 DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group)
2420 switch(group)
2422 case DIMINISHING_BLIND_CYCLONE:
2423 case DIMINISHING_CONTROL_STUN:
2424 case DIMINISHING_TRIGGER_STUN:
2425 case DIMINISHING_KIDNEYSHOT:
2426 return DRTYPE_ALL;
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;
2443 return DRTYPE_NONE;