[6922] Whitespace and newline fixes
[getmangos.git] / src / game / SpellMgr.cpp
blobd1b94fae2782f0dafa6a107b1b0b261b56f11835
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++)
187 // only paladin auras have this
188 if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
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 == 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
670 QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellFamilyMask 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 uint64 spellAffectMask = fields[2].GetUInt64();
719 // Spell.dbc have own data for low part of SpellFamilyMask
720 if( spellInfo->EffectItemType[effectId])
722 if(spellInfo->EffectItemType[effectId] == spellAffectMask)
724 sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectItemType%d) data for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId);
725 continue;
728 // 24429 have wrong data in EffectItemType and overwrites by DB, possible bug in client
729 if(spellInfo->Id!=24429 && spellInfo->EffectItemType[effectId] != spellAffectMask)
731 sLog.outErrorDb("Spell %u listed in `spell_affect` have different low part from EffectItemType%d for effect index (%u) and not needed, skipped.", entry,effectId+1,effectId);
732 continue;
736 mSpellAffectMap.insert(SpellAffectMap::value_type((entry<<8) + effectId,spellAffectMask));
738 ++count;
739 } while( result->NextRow() );
741 delete result;
743 sLog.outString();
744 sLog.outString( ">> Loaded %u spell affect definitions", count );
746 for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id)
748 SpellEntry const* spellInfo = sSpellStore.LookupEntry(id);
749 if (!spellInfo)
750 continue;
752 for (int effectId = 0; effectId < 3; ++effectId)
754 if( spellInfo->Effect[effectId] != SPELL_EFFECT_APPLY_AURA ||
755 (spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_FLAT_MODIFIER &&
756 spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_PCT_MODIFIER &&
757 spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER) )
758 continue;
760 if(spellInfo->EffectItemType[effectId] != 0)
761 continue;
763 if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end())
764 continue;
766 sLog.outErrorDb("Spell %u (%s) misses spell_affect for effect %u",id,spellInfo->SpellName[sWorld.GetDefaultDbcLocale()], effectId);
771 bool SpellMgr::IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const
773 // false for spellInfo == NULL
774 if (!spellInfo)
775 return false;
777 SpellEntry const *affect_spell = sSpellStore.LookupEntry(spellId);
778 // false for affect_spell == NULL
779 if (!affect_spell)
780 return false;
782 // False if spellFamily not equal
783 if (affect_spell->SpellFamilyName != spellInfo->SpellFamilyName)
784 return false;
786 // If familyFlags == 0
787 if (!familyFlags)
789 // Get it from spellAffect table
790 familyFlags = GetSpellAffectMask(spellId,effectId);
791 // false if familyFlags == 0
792 if (!familyFlags)
793 return false;
796 // true
797 if (familyFlags & spellInfo->SpellFamilyFlags)
798 return true;
800 return false;
803 void SpellMgr::LoadSpellProcEvents()
805 mSpellProcEventMap.clear(); // need for reload case
807 uint32 count = 0;
809 // 0 1 2 3 4 5 6 7 8
810 QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, Category, SkillID, SpellFamilyName, SpellFamilyMask, procFlags, ppmRate, cooldown FROM spell_proc_event");
811 if( !result )
814 barGoLink bar( 1 );
816 bar.step();
818 sLog.outString();
819 sLog.outString( ">> Loaded %u spell proc event conditions", count );
820 return;
823 barGoLink bar( result->GetRowCount() );
827 Field *fields = result->Fetch();
829 bar.step();
831 uint16 entry = fields[0].GetUInt16();
833 if (!sSpellStore.LookupEntry(entry))
835 sLog.outErrorDb("Spell %u listed in `spell_proc_event` does not exist", entry);
836 continue;
839 SpellProcEventEntry spe;
841 spe.schoolMask = fields[1].GetUInt32();
842 spe.category = fields[2].GetUInt32();
843 spe.skillId = fields[3].GetUInt32();
844 spe.spellFamilyName = fields[4].GetUInt32();
845 spe.spellFamilyMask = fields[5].GetUInt64();
846 spe.procFlags = fields[6].GetUInt32();
847 spe.ppmRate = fields[7].GetFloat();
848 spe.cooldown = fields[8].GetUInt32();
850 mSpellProcEventMap[entry] = spe;
852 ++count;
853 } while( result->NextRow() );
855 delete result;
857 sLog.outString();
858 sLog.outString( ">> Loaded %u spell proc event conditions", count );
861 // Commented for now, as it still produces many errors (still quite many spells miss spell_proc_event)
862 for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id)
864 SpellEntry const* spellInfo = sSpellStore.LookupEntry(id);
865 if (!spellInfo)
866 continue;
868 bool found = false;
869 for (int effectId = 0; effectId < 3; ++effectId)
871 // at this moment check only SPELL_AURA_PROC_TRIGGER_SPELL
872 if( spellInfo->EffectApplyAuraName[effectId] == SPELL_AURA_PROC_TRIGGER_SPELL )
874 found = true;
875 break;
879 if(!found)
880 continue;
882 if(GetSpellProcEvent(id))
883 continue;
885 sLog.outErrorDb("Spell %u (%s) misses spell_proc_event",id,spellInfo->SpellName[sWorld.GetDBClang()]);
890 bool SpellMgr::IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, SpellEntry const * procSpell, uint32 procFlags )
892 if((procFlags & spellProcEvent->procFlags) == 0)
893 return false;
895 // Additional checks in case spell cast/hit/crit is the event
896 // Check (if set) school, category, skill line, spell talent mask
897 if(spellProcEvent->schoolMask && (!procSpell || (GetSpellSchoolMask(procSpell) & spellProcEvent->schoolMask) == 0))
898 return false;
899 if(spellProcEvent->category && (!procSpell || procSpell->Category != spellProcEvent->category))
900 return false;
901 if(spellProcEvent->skillId)
903 if (!procSpell)
904 return false;
906 SkillLineAbilityMap::const_iterator lower = spellmgr.GetBeginSkillLineAbilityMap(procSpell->Id);
907 SkillLineAbilityMap::const_iterator upper = spellmgr.GetEndSkillLineAbilityMap(procSpell->Id);
909 bool found = false;
910 for(SkillLineAbilityMap::const_iterator _spell_idx = lower; _spell_idx != upper; ++_spell_idx)
912 if(_spell_idx->second->skillId == spellProcEvent->skillId)
914 found = true;
915 break;
918 if (!found)
919 return false;
921 if(spellProcEvent->spellFamilyName && (!procSpell || spellProcEvent->spellFamilyName != procSpell->SpellFamilyName))
922 return false;
923 if(spellProcEvent->spellFamilyMask && (!procSpell || (spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags) == 0))
924 return false;
926 return true;
929 void SpellMgr::LoadSpellElixirs()
931 mSpellElixirs.clear(); // need for reload case
933 uint32 count = 0;
935 // 0 1
936 QueryResult *result = WorldDatabase.Query("SELECT entry, mask FROM spell_elixir");
937 if( !result )
940 barGoLink bar( 1 );
942 bar.step();
944 sLog.outString();
945 sLog.outString( ">> Loaded %u spell elixir definitions", count );
946 return;
949 barGoLink bar( result->GetRowCount() );
953 Field *fields = result->Fetch();
955 bar.step();
957 uint16 entry = fields[0].GetUInt16();
958 uint8 mask = fields[1].GetUInt8();
960 SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry);
962 if (!spellInfo)
964 sLog.outErrorDb("Spell %u listed in `spell_elixir` does not exist", entry);
965 continue;
968 mSpellElixirs[entry] = mask;
970 ++count;
971 } while( result->NextRow() );
973 delete result;
975 sLog.outString();
976 sLog.outString( ">> Loaded %u spell elixir definitions", count );
979 void SpellMgr::LoadSpellThreats()
981 sSpellThreatStore.Free(); // for reload
983 sSpellThreatStore.Load();
985 sLog.outString( ">> Loaded %u aggro generating spells", sSpellThreatStore.RecordCount );
986 sLog.outString();
989 bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const
991 SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
992 if(!spellInfo_1 || !spellInfo_2) return false;
993 if(spellInfo_1->Id == spellId_2) return false;
995 return GetFirstSpellInChain(spellInfo_1->Id)==GetFirstSpellInChain(spellId_2);
998 bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
1000 if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH)
1001 return false;
1002 if(IsProfessionSpell(spellInfo->Id))
1003 return false;
1005 // All stance spells. if any better way, change it.
1006 for (int i = 0; i < 3; i++)
1008 // Paladin aura Spell
1009 if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN
1010 && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
1011 return false;
1012 // Druid form Spell
1013 if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID
1014 && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
1015 && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
1016 return false;
1017 // Rogue Stealth
1018 if(spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE
1019 && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
1020 && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
1021 return false;
1023 return true;
1026 bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const
1028 SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
1029 SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
1031 if(!spellInfo_1 || !spellInfo_2)
1032 return false;
1034 if(spellInfo_1->Id == spellId_2)
1035 return false;
1037 //I think we don't check this correctly because i need a exception for spell:
1038 //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.
1039 if(spellInfo_2->SpellFamilyFlags == 2048)
1040 return false;
1042 // Resurrection sickness
1043 if((spellInfo_1->Id == SPELL_ID_PASSIVE_RESURRECTION_SICKNESS) != (spellInfo_2->Id==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS))
1044 return false;
1046 // Specific spell family spells
1047 switch(spellInfo_1->SpellFamilyName)
1049 case SPELLFAMILY_GENERIC:
1050 switch(spellInfo_2->SpellFamilyName)
1052 case SPELLFAMILY_GENERIC: // same family case
1054 // Thunderfury
1055 if( spellInfo_1->Id == 21992 && spellInfo_2->Id == 27648 || spellInfo_2->Id == 21992 && spellInfo_1->Id == 27648 )
1056 return false;
1058 // Lightning Speed (Mongoose) and Fury of the Crashing Waves (Tsunami Talisman)
1059 if( spellInfo_1->Id == 28093 && spellInfo_2->Id == 42084 ||
1060 spellInfo_2->Id == 28093 && spellInfo_1->Id == 42084 )
1061 return false;
1063 // Soulstone Resurrection and Twisting Nether (resurrector)
1064 if( spellInfo_1->SpellIconID == 92 && spellInfo_2->SpellIconID == 92 && (
1065 spellInfo_1->SpellVisual == 99 && spellInfo_2->SpellVisual == 0 ||
1066 spellInfo_2->SpellVisual == 99 && spellInfo_1->SpellVisual == 0 ) )
1067 return false;
1069 // Heart of the Wild and (Primal Instinct (Idol of Terror) triggering spell or Agility)
1070 if( spellInfo_1->SpellIconID == 240 && spellInfo_2->SpellIconID == 240 && (
1071 spellInfo_1->SpellVisual == 0 && spellInfo_2->SpellVisual == 78 ||
1072 spellInfo_2->SpellVisual == 0 && spellInfo_1->SpellVisual == 78 ) )
1073 return false;
1075 // Personalized Weather (thunder effect should overwrite rainy aura)
1076 if(spellInfo_1->SpellIconID == 2606 && spellInfo_2->SpellIconID == 2606)
1077 return false;
1079 // Brood Affliction: Bronze
1080 if( (spellInfo_1->Id == 23170 && spellInfo_2->Id == 23171) ||
1081 (spellInfo_2->Id == 23170 && spellInfo_1->Id == 23171) )
1082 return false;
1084 break;
1086 case SPELLFAMILY_WARRIOR:
1088 // Scroll of Protection and Defensive Stance (multi-family check)
1089 if( spellInfo_1->SpellIconID == 276 && spellInfo_1->SpellVisual == 196 && spellInfo_2->Id == 71)
1090 return false;
1092 // Improved Hamstring -> Hamstring (multi-family check)
1093 if( (spellInfo_2->SpellFamilyFlags & 2) && spellInfo_1->Id == 23694 )
1094 return false;
1096 break;
1098 case SPELLFAMILY_DRUID:
1100 // Scroll of Stamina and Leader of the Pack (multi-family check)
1101 if( spellInfo_1->SpellIconID == 312 && spellInfo_1->SpellVisual == 216 && spellInfo_2->Id == 24932 )
1102 return false;
1104 // Dragonmaw Illusion (multi-family check)
1105 if (spellId_1 == 40216 && spellId_2 == 42016 )
1106 return false;
1108 break;
1110 case SPELLFAMILY_ROGUE:
1112 // Garrote-Silence -> Garrote (multi-family check)
1113 if( spellInfo_1->SpellIconID == 498 && spellInfo_1->SpellVisual == 0 && spellInfo_2->SpellIconID == 498 )
1114 return false;
1116 break;
1118 case SPELLFAMILY_HUNTER:
1120 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1121 if( spellInfo_1->Id == 19410 && spellInfo_2->Id == 5116 )
1122 return false;
1124 // Improved Wing Clip -> Wing Clip (multi-family check)
1125 if( (spellInfo_2->SpellFamilyFlags & 0x40) && spellInfo_1->Id == 19229 )
1126 return false;
1127 break;
1129 case SPELLFAMILY_PALADIN:
1131 // Unstable Currents and other -> *Sanctity Aura (multi-family check)
1132 if( spellInfo_2->SpellIconID==502 && spellInfo_1->SpellIconID==502 && spellInfo_1->SpellVisual==969 )
1133 return false;
1135 // *Band of Eternal Champion and Seal of Command(multi-family check)
1136 if( spellId_1 == 35081 && spellInfo_2->SpellIconID==561 && spellInfo_2->SpellVisual==7992)
1137 return false;
1139 break;
1142 break;
1143 case SPELLFAMILY_MAGE:
1144 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_MAGE )
1146 // Blizzard & Chilled (and some other stacked with blizzard spells
1147 if( (spellInfo_1->SpellFamilyFlags & 0x80) && (spellInfo_2->SpellFamilyFlags & 0x100000) ||
1148 (spellInfo_2->SpellFamilyFlags & 0x80) && (spellInfo_1->SpellFamilyFlags & 0x100000) )
1149 return false;
1151 // Blink & Improved Blink
1152 if( (spellInfo_1->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_2->SpellVisual == 72 && spellInfo_2->SpellIconID == 1499) ||
1153 (spellInfo_2->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_1->SpellVisual == 72 && spellInfo_1->SpellIconID == 1499) )
1154 return false;
1156 // Detect Invisibility and Mana Shield (multi-family check)
1157 if( spellInfo_2->Id == 132 && spellInfo_1->SpellIconID == 209 && spellInfo_1->SpellVisual == 968 )
1158 return false;
1160 // Combustion and Fire Protection Aura (multi-family check)
1161 if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual == 321 )
1162 return false;
1164 break;
1165 case SPELLFAMILY_WARLOCK:
1166 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_WARLOCK )
1168 // Siphon Life and Drain Life
1169 if( spellInfo_1->SpellIconID == 152 && spellInfo_2->SpellIconID == 546 ||
1170 spellInfo_2->SpellIconID == 152 && spellInfo_1->SpellIconID == 546 )
1171 return false;
1173 //Corruption & Seed of corruption
1174 if( spellInfo_1->SpellIconID == 313 && spellInfo_2->SpellIconID == 1932 ||
1175 spellInfo_2->SpellIconID == 313 && spellInfo_1->SpellIconID == 1932 )
1176 if(spellInfo_1->SpellVisual != 0 && spellInfo_2->SpellVisual != 0)
1177 return true; // can't be stacked
1179 // Corruption and Unstable Affliction
1180 if( spellInfo_1->SpellIconID == 313 && spellInfo_2->SpellIconID == 2039 ||
1181 spellInfo_2->SpellIconID == 313 && spellInfo_1->SpellIconID == 2039 )
1182 return false;
1184 // (Corruption or Unstable Affliction) and (Curse of Agony or Curse of Doom)
1185 if( (spellInfo_1->SpellIconID == 313 || spellInfo_1->SpellIconID == 2039) && (spellInfo_2->SpellIconID == 544 || spellInfo_2->SpellIconID == 91) ||
1186 (spellInfo_2->SpellIconID == 313 || spellInfo_2->SpellIconID == 2039) && (spellInfo_1->SpellIconID == 544 || spellInfo_1->SpellIconID == 91) )
1187 return false;
1189 // Detect Invisibility and Mana Shield (multi-family check)
1190 if( spellInfo_1->Id == 132 && spellInfo_2->SpellIconID == 209 && spellInfo_2->SpellVisual == 968 )
1191 return false;
1192 break;
1193 case SPELLFAMILY_WARRIOR:
1194 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_WARRIOR )
1196 // Rend and Deep Wound
1197 if( (spellInfo_1->SpellFamilyFlags & 0x20) && (spellInfo_2->SpellFamilyFlags & 0x1000000000LL) ||
1198 (spellInfo_2->SpellFamilyFlags & 0x20) && (spellInfo_1->SpellFamilyFlags & 0x1000000000LL) )
1199 return false;
1201 // Battle Shout and Rampage
1202 if( (spellInfo_1->SpellIconID == 456 && spellInfo_2->SpellIconID == 2006) ||
1203 (spellInfo_2->SpellIconID == 456 && spellInfo_1->SpellIconID == 2006) )
1204 return false;
1207 // Hamstring -> Improved Hamstring (multi-family check)
1208 if( (spellInfo_1->SpellFamilyFlags & 2) && spellInfo_2->Id == 23694 )
1209 return false;
1211 // Defensive Stance and Scroll of Protection (multi-family check)
1212 if( spellInfo_1->Id == 71 && spellInfo_2->SpellIconID == 276 && spellInfo_2->SpellVisual == 196 )
1213 return false;
1215 // Bloodlust and Bloodthirst (multi-family check)
1216 if( spellInfo_2->Id == 2825 && spellInfo_1->SpellIconID == 38 && spellInfo_1->SpellVisual == 0 )
1217 return false;
1219 break;
1220 case SPELLFAMILY_PRIEST:
1221 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PRIEST )
1223 //Devouring Plague and Shadow Vulnerability
1224 if( (spellInfo_1->SpellFamilyFlags & 0x2000000) && (spellInfo_2->SpellFamilyFlags & 0x800000000LL) ||
1225 (spellInfo_2->SpellFamilyFlags & 0x2000000) && (spellInfo_1->SpellFamilyFlags & 0x800000000LL) )
1226 return false;
1228 //StarShards and Shadow Word: Pain
1229 if( (spellInfo_1->SpellFamilyFlags & 0x200000) && (spellInfo_2->SpellFamilyFlags & 0x8000) ||
1230 (spellInfo_2->SpellFamilyFlags & 0x200000) && (spellInfo_1->SpellFamilyFlags & 0x8000) )
1231 return false;
1233 break;
1234 case SPELLFAMILY_DRUID:
1235 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_DRUID )
1237 //Omen of Clarity and Blood Frenzy
1238 if( (spellInfo_1->SpellFamilyFlags == 0x0 && spellInfo_1->SpellIconID == 108) && (spellInfo_2->SpellFamilyFlags & 0x20000000000000LL) ||
1239 (spellInfo_2->SpellFamilyFlags == 0x0 && spellInfo_2->SpellIconID == 108) && (spellInfo_1->SpellFamilyFlags & 0x20000000000000LL) )
1240 return false;
1242 // Tree of Life (Shapeshift) and 34123 Tree of Life (Passive)
1243 if ((spellId_1 == 33891 && spellId_2 == 34123) ||
1244 (spellId_2 == 33891 && spellId_1 == 34123))
1245 return false;
1247 // Wrath of Elune and Nature's Grace
1248 if( spellInfo_1->Id == 16886 && spellInfo_2->Id == 46833 || spellInfo_2->Id == 16886 && spellInfo_1->Id == 46833 )
1249 return false;
1251 // Bear Rage (Feral T4 (2)) and Omen of Clarity
1252 if( spellInfo_1->Id == 16864 && spellInfo_2->Id == 37306 || spellInfo_2->Id == 16864 && spellInfo_1->Id == 37306 )
1253 return false;
1255 // Cat Energy (Feral T4 (2)) and Omen of Clarity
1256 if( spellInfo_1->Id == 16864 && spellInfo_2->Id == 37311 || spellInfo_2->Id == 16864 && spellInfo_1->Id == 37311 )
1257 return false;
1260 // Leader of the Pack and Scroll of Stamina (multi-family check)
1261 if( spellInfo_1->Id == 24932 && spellInfo_2->SpellIconID == 312 && spellInfo_2->SpellVisual == 216 )
1262 return false;
1264 // Dragonmaw Illusion (multi-family check)
1265 if (spellId_1 == 42016 && spellId_2 == 40216 )
1266 return false;
1268 break;
1269 case SPELLFAMILY_ROGUE:
1270 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_ROGUE )
1272 // Master of Subtlety
1273 if (spellId_1 == 31665 && spellId_2 == 31666 || spellId_1 == 31666 && spellId_2 == 31665 )
1274 return false;
1277 // Garrote -> Garrote-Silence (multi-family check)
1278 if( spellInfo_1->SpellIconID == 498 && spellInfo_2->SpellIconID == 498 && spellInfo_2->SpellVisual == 0 )
1279 return false;
1280 break;
1281 case SPELLFAMILY_HUNTER:
1282 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_HUNTER )
1284 // Rapid Fire & Quick Shots
1285 if( (spellInfo_1->SpellFamilyFlags & 0x20) && (spellInfo_2->SpellFamilyFlags & 0x20000000000LL) ||
1286 (spellInfo_2->SpellFamilyFlags & 0x20) && (spellInfo_1->SpellFamilyFlags & 0x20000000000LL) )
1287 return false;
1289 // Serpent Sting & (Immolation/Explosive Trap Effect)
1290 if( (spellInfo_1->SpellFamilyFlags & 0x4) && (spellInfo_2->SpellFamilyFlags & 0x00000004000LL) ||
1291 (spellInfo_2->SpellFamilyFlags & 0x4) && (spellInfo_1->SpellFamilyFlags & 0x00000004000LL) )
1292 return false;
1294 // Bestial Wrath
1295 if( spellInfo_1->SpellIconID == 1680 && spellInfo_2->SpellIconID == 1680 )
1296 return false;
1299 // Wing Clip -> Improved Wing Clip (multi-family check)
1300 if( (spellInfo_1->SpellFamilyFlags & 0x40) && spellInfo_2->Id == 19229 )
1301 return false;
1303 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1304 if( spellInfo_2->Id == 19410 && spellInfo_1->Id == 5116 )
1305 return false;
1306 break;
1307 case SPELLFAMILY_PALADIN:
1308 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN )
1310 // Paladin Seals
1311 if( IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2) )
1312 return true;
1314 // Combustion and Fire Protection Aura (multi-family check)
1315 if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual == 321 )
1316 return false;
1318 // *Sanctity Aura -> Unstable Currents and other (multi-family check)
1319 if( spellInfo_1->SpellIconID==502 && spellInfo_2->SpellFamilyName == SPELLFAMILY_GENERIC && spellInfo_2->SpellIconID==502 && spellInfo_2->SpellVisual==969 )
1320 return false;
1322 // *Seal of Command and Band of Eternal Champion (multi-family check)
1323 if( spellInfo_1->SpellIconID==561 && spellInfo_1->SpellVisual==7992 && spellId_2 == 35081)
1324 return false;
1325 break;
1326 case SPELLFAMILY_SHAMAN:
1327 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_SHAMAN )
1329 // shaman shields
1330 if( IsElementalShield(spellInfo_1) && IsElementalShield(spellInfo_2) )
1331 return true;
1333 // Windfury weapon
1334 if( spellInfo_1->SpellIconID==220 && spellInfo_2->SpellIconID==220 &&
1335 spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags )
1336 return false;
1338 // Bloodlust and Bloodthirst (multi-family check)
1339 if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual == 0 )
1340 return false;
1341 break;
1342 default:
1343 break;
1346 // more generic checks
1347 if (spellInfo_1->SpellIconID == spellInfo_2->SpellIconID &&
1348 spellInfo_1->SpellIconID != 0 && spellInfo_2->SpellIconID != 0)
1350 bool isModifier = false;
1351 for (int i = 0; i < 3; i++)
1353 if (spellInfo_1->EffectApplyAuraName[i] == SPELL_AURA_ADD_FLAT_MODIFIER ||
1354 spellInfo_1->EffectApplyAuraName[i] == SPELL_AURA_ADD_PCT_MODIFIER ||
1355 spellInfo_2->EffectApplyAuraName[i] == SPELL_AURA_ADD_FLAT_MODIFIER ||
1356 spellInfo_2->EffectApplyAuraName[i] == SPELL_AURA_ADD_PCT_MODIFIER )
1357 isModifier = true;
1360 if (!isModifier)
1361 return true;
1364 if (IsRankSpellDueToSpell(spellInfo_1, spellId_2))
1365 return true;
1367 if (spellInfo_1->SpellFamilyName == 0 || spellInfo_2->SpellFamilyName == 0)
1368 return false;
1370 if (spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
1371 return false;
1373 for (int i = 0; i < 3; ++i)
1374 if (spellInfo_1->Effect[i] != spellInfo_2->Effect[i] ||
1375 spellInfo_1->EffectItemType[i] != spellInfo_2->EffectItemType[i] ||
1376 spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i] ||
1377 spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i])
1378 return false;
1380 return true;
1383 bool SpellMgr::IsProfessionSpell(uint32 spellId)
1385 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
1386 if(!spellInfo)
1387 return false;
1389 if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL)
1390 return false;
1392 uint32 skill = spellInfo->EffectMiscValue[1];
1394 return IsProfessionSkill(skill);
1397 bool SpellMgr::IsPrimaryProfessionSpell(uint32 spellId)
1399 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
1400 if(!spellInfo)
1401 return false;
1403 if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL)
1404 return false;
1406 uint32 skill = spellInfo->EffectMiscValue[1];
1408 return IsPrimaryProfessionSkill(skill);
1411 bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId) const
1413 return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId)==1;
1416 SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const
1418 // ignore passive spells
1419 if(IsPassiveSpell(spellInfo->Id))
1420 return spellInfo;
1422 bool needRankSelection = false;
1423 for(int i=0;i<3;i++)
1425 if( IsPositiveEffect(spellInfo->Id, i) && (
1426 spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA ||
1427 spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY
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 /// Some checks for spells, to prevent adding depricated/broken spells for trainers, spell book, etc
1970 bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg)
1972 // not exist
1973 if(!spellInfo)
1974 return false;
1976 bool need_check_reagents = false;
1978 // check effects
1979 for(int i=0; i<3; ++i)
1981 switch(spellInfo->Effect[i])
1983 case 0:
1984 continue;
1986 // craft spell for crafting non-existed item (break client recipes list show)
1987 case SPELL_EFFECT_CREATE_ITEM:
1989 if(!ObjectMgr::GetItemPrototype( spellInfo->EffectItemType[i] ))
1991 if(msg)
1993 if(pl)
1994 ChatHandler(pl).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->EffectItemType[i]);
1995 else
1996 sLog.outErrorDb("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->EffectItemType[i]);
1998 return false;
2001 need_check_reagents = true;
2002 break;
2004 case SPELL_EFFECT_LEARN_SPELL:
2006 SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(spellInfo->EffectTriggerSpell[i]);
2007 if( !IsSpellValid(spellInfo2,pl,msg) )
2009 if(msg)
2011 if(pl)
2012 ChatHandler(pl).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[i]);
2013 else
2014 sLog.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[i]);
2016 return false;
2018 break;
2023 if(need_check_reagents)
2025 for(int j = 0; j < 8; ++j)
2027 if(spellInfo->Reagent[j] > 0 && !ObjectMgr::GetItemPrototype( spellInfo->Reagent[j] ))
2029 if(msg)
2031 if(pl)
2032 ChatHandler(pl).PSendSysMessage("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->Reagent[j]);
2033 else
2034 sLog.outErrorDb("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->Reagent[j]);
2036 return false;
2041 return true;
2044 bool IsSpellAllowedInLocation(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id)
2046 // normal case
2047 if( spellInfo->AreaId && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id )
2048 return false;
2050 // elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup)
2051 if(spellInfo->SpellFamilyName==SPELLFAMILY_POTION)
2053 if(uint32 mask = spellmgr.GetSpellElixirMask(spellInfo->Id))
2055 if(mask & ELIXIR_BATTLE_MASK)
2057 if(spellInfo->Id==45373) // Bloodberry Elixir
2058 return zone_id==4075;
2060 if(mask & ELIXIR_UNSTABLE_MASK)
2062 // in the Blade's Edge Mountains Plateaus and Gruul's Lair.
2063 return zone_id ==3522 || map_id==565;
2065 if(mask & ELIXIR_SHATTRATH_MASK)
2067 // in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple, Sunwell Plateau
2068 if(zone_id ==3607 || map_id==534 || map_id==564 || zone_id==4075)
2069 return true;
2071 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2072 if(!mapEntry)
2073 return false;
2075 return mapEntry->multimap_id==206;
2078 // elixirs not have another limitations
2079 return true;
2083 // special cases zone check (maps checked by multimap common id)
2084 switch(spellInfo->Id)
2086 case 41618: // Bottled Nethergon Energy
2087 case 41620: // Bottled Nethergon Vapor
2089 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2090 if(!mapEntry)
2091 return false;
2093 return mapEntry->multimap_id==206;
2095 case 41617: // Cenarion Mana Salve
2096 case 41619: // Cenarion Healing Salve
2098 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2099 if(!mapEntry)
2100 return false;
2102 return mapEntry->multimap_id==207;
2104 case 40216: // Dragonmaw Illusion
2105 case 42016: // Dragonmaw Illusion
2106 return area_id == 3759 || area_id == 3966 || area_id == 3939;
2109 return true;
2112 void SpellMgr::LoadSkillLineAbilityMap()
2114 mSkillLineAbilityMap.clear();
2116 uint32 count = 0;
2118 for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); i++)
2120 SkillLineAbilityEntry const *SkillInfo = sSkillLineAbilityStore.LookupEntry(i);
2121 if(!SkillInfo)
2122 continue;
2124 mSkillLineAbilityMap.insert(SkillLineAbilityMap::value_type(SkillInfo->spellId,SkillInfo));
2125 ++count;
2128 sLog.outString();
2129 sLog.outString(">> Loaded %u SkillLineAbility MultiMap", count);
2132 DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto, bool triggered)
2134 // Explicit Diminishing Groups
2135 switch(spellproto->SpellFamilyName)
2137 case SPELLFAMILY_MAGE:
2139 // Polymorph
2140 if ((spellproto->SpellFamilyFlags & 0x00001000000LL) && spellproto->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE)
2141 return DIMINISHING_POLYMORPH;
2142 break;
2144 case SPELLFAMILY_ROGUE:
2146 // Kidney Shot
2147 if (spellproto->SpellFamilyFlags & 0x00000200000LL)
2148 return DIMINISHING_KIDNEYSHOT;
2149 // Blind
2150 else if (spellproto->SpellFamilyFlags & 0x00001000000LL)
2151 return DIMINISHING_BLIND_CYCLONE;
2152 break;
2154 case SPELLFAMILY_WARLOCK:
2156 // Death Coil
2157 if (spellproto->SpellFamilyFlags & 0x00000080000LL)
2158 return DIMINISHING_DEATHCOIL;
2159 // Fear
2160 else if (spellproto->SpellFamilyFlags & 0x40840000000LL)
2161 return DIMINISHING_WARLOCK_FEAR;
2162 // Curses/etc
2163 else if (spellproto->SpellFamilyFlags & 0x00080000000LL)
2164 return DIMINISHING_LIMITONLY;
2165 break;
2167 case SPELLFAMILY_DRUID:
2169 // Cyclone
2170 if (spellproto->SpellFamilyFlags & 0x02000000000LL)
2171 return DIMINISHING_BLIND_CYCLONE;
2172 break;
2174 case SPELLFAMILY_WARRIOR:
2176 // Hamstring - limit duration to 10s in PvP
2177 if (spellproto->SpellFamilyFlags & 0x00000000002LL)
2178 return DIMINISHING_LIMITONLY;
2179 break;
2181 default:
2182 break;
2185 // Get by mechanic
2186 for (uint8 i=0;i<3;++i)
2188 if (spellproto->Mechanic == MECHANIC_STUN || spellproto->EffectMechanic[i] == MECHANIC_STUN)
2189 return triggered ? DIMINISHING_TRIGGER_STUN : DIMINISHING_CONTROL_STUN;
2190 else if (spellproto->Mechanic == MECHANIC_SLEEP || spellproto->EffectMechanic[i] == MECHANIC_SLEEP)
2191 return DIMINISHING_SLEEP;
2192 else if (spellproto->Mechanic == MECHANIC_ROOT || spellproto->EffectMechanic[i] == MECHANIC_ROOT)
2193 return triggered ? DIMINISHING_TRIGGER_ROOT : DIMINISHING_CONTROL_ROOT;
2194 else if (spellproto->Mechanic == MECHANIC_FEAR || spellproto->EffectMechanic[i] == MECHANIC_FEAR)
2195 return DIMINISHING_FEAR;
2196 else if (spellproto->Mechanic == MECHANIC_CHARM || spellproto->EffectMechanic[i] == MECHANIC_CHARM)
2197 return DIMINISHING_CHARM;
2198 else if (spellproto->Mechanic == MECHANIC_SILENCE || spellproto->EffectMechanic[i] == MECHANIC_SILENCE)
2199 return DIMINISHING_SILENCE;
2200 else if (spellproto->Mechanic == MECHANIC_DISARM || spellproto->EffectMechanic[i] == MECHANIC_DISARM)
2201 return DIMINISHING_DISARM;
2202 else if (spellproto->Mechanic == MECHANIC_FREEZE || spellproto->EffectMechanic[i] == MECHANIC_FREEZE)
2203 return DIMINISHING_FREEZE;
2204 else if (spellproto->Mechanic == MECHANIC_KNOCKOUT|| spellproto->EffectMechanic[i] == MECHANIC_KNOCKOUT ||
2205 spellproto->Mechanic == MECHANIC_SAPPED || spellproto->EffectMechanic[i] == MECHANIC_SAPPED)
2206 return DIMINISHING_KNOCKOUT;
2207 else if (spellproto->Mechanic == MECHANIC_BANISH || spellproto->EffectMechanic[i] == MECHANIC_BANISH)
2208 return DIMINISHING_BANISH;
2211 return DIMINISHING_NONE;
2214 bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group)
2216 switch(group)
2218 case DIMINISHING_CONTROL_STUN:
2219 case DIMINISHING_TRIGGER_STUN:
2220 case DIMINISHING_KIDNEYSHOT:
2221 case DIMINISHING_SLEEP:
2222 case DIMINISHING_CONTROL_ROOT:
2223 case DIMINISHING_TRIGGER_ROOT:
2224 case DIMINISHING_FEAR:
2225 case DIMINISHING_WARLOCK_FEAR:
2226 case DIMINISHING_CHARM:
2227 case DIMINISHING_POLYMORPH:
2228 case DIMINISHING_FREEZE:
2229 case DIMINISHING_KNOCKOUT:
2230 case DIMINISHING_BLIND_CYCLONE:
2231 case DIMINISHING_BANISH:
2232 case DIMINISHING_LIMITONLY:
2233 return true;
2235 return false;
2238 DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group)
2240 switch(group)
2242 case DIMINISHING_BLIND_CYCLONE:
2243 case DIMINISHING_CONTROL_STUN:
2244 case DIMINISHING_TRIGGER_STUN:
2245 case DIMINISHING_KIDNEYSHOT:
2246 return DRTYPE_ALL;
2247 case DIMINISHING_SLEEP:
2248 case DIMINISHING_CONTROL_ROOT:
2249 case DIMINISHING_TRIGGER_ROOT:
2250 case DIMINISHING_FEAR:
2251 case DIMINISHING_CHARM:
2252 case DIMINISHING_POLYMORPH:
2253 case DIMINISHING_SILENCE:
2254 case DIMINISHING_DISARM:
2255 case DIMINISHING_DEATHCOIL:
2256 case DIMINISHING_FREEZE:
2257 case DIMINISHING_BANISH:
2258 case DIMINISHING_WARLOCK_FEAR:
2259 case DIMINISHING_KNOCKOUT:
2260 return DRTYPE_PLAYER;
2263 return DRTYPE_NONE;