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