OregonCore  revision 3611e8a-git
Your Favourite TBC server
SpellMgr.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Unit.h"
19 #include "SpellMgr.h"
20 #include "ObjectMgr.h"
21 #include "SpellAuraDefines.h"
22 #include "DBCStores.h"
23 #include "Chat.h"
24 #include "Spell.h"
25 #include "CreatureAI.h"
26 #include "BattlegroundMgr.h"
27 
29 
31 {
32  for (int i = 0; i < TOTAL_SPELL_EFFECTS; ++i)
33  {
34  switch (i)
35  {
37  case SPELL_EFFECT_SUMMON: //28
39  case SPELL_EFFECT_TRANS_DOOR: //50 summon object
40  case SPELL_EFFECT_SUMMON_PET: //56
41  case SPELL_EFFECT_ADD_FARSIGHT: //72
48  case SPELL_EFFECT_TRIGGER_SPELL_2: //151 ritual of summon
50  break;
51  case SPELL_EFFECT_PARRY: // 0
52  case SPELL_EFFECT_BLOCK: // 0
53  case SPELL_EFFECT_SKILL: // always with dummy 3 as A
54  //case SPELL_EFFECT_LEARN_SPELL: // 0 may be 5 pet
55  case SPELL_EFFECT_TRADE_SKILL: // 0 or 1
56  case SPELL_EFFECT_PROFICIENCY: // 0
58  break;
65  break;
66  //caster must be pushed otherwise no sound
73  break;
74  default:
76  break;
77  }
78  }
79 
80  for (int i = 0; i < TOTAL_SPELL_TARGETS; ++i)
81  {
82  switch (i)
83  {
84  case TARGET_UNIT_CASTER:
86  case TARGET_UNIT_MASTER:
87  case TARGET_UNIT_PET:
91  break;
102  break;
109  break;
116  break;
123  break;
129  break;
130  case TARGET_DST_CASTER:
131  case TARGET_SRC_CASTER:
132  case TARGET_MINION:
145  break;
159  break;
163  case TARGET_DEST_DEST:
164  case TARGET_DEST_TRAJ:
175  break;
176  case TARGET_DST_DB:
177  case TARGET_DST_HOME:
180  break;
181  case TARGET_UNIT_CHANNEL:
182  case TARGET_DEST_CHANNEL:
184  break;
185  default:
187  }
188  }
189 
190  for (int i = 0; i < TOTAL_SPELL_TARGETS; ++i)
191  {
192  switch (i)
193  {
208  IsAreaEffectTarget[i] = true;
209  break;
210  default:
211  IsAreaEffectTarget[i] = false;
212  break;
213  }
214  }
215 }
216 
218 {
220 }
221 
223 {
224  static SpellMgr spellMgr;
225  return spellMgr;
226 }
227 
229 {
230  if (!spellInfo)
231  return 0;
232  SpellDurationEntry const* du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex);
233  if (!du)
234  return 0;
235  return (du->Duration[0] == -1) ? -1 : abs(du->Duration[0]);
236 }
237 
239 {
240  if (!spellInfo)
241  return 0;
242  SpellDurationEntry const* du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex);
243  if (!du)
244  return 0;
245  return (du->Duration[2] == -1) ? -1 : abs(du->Duration[2]);
246 }
247 
248 uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell)
249 {
250  SpellCastTimesEntry const* spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(spellInfo->CastingTimeIndex);
251 
252  // not all spells have cast time index and this is all is pasiive abilities
253  if (!spellCastTimeEntry)
254  return 0;
255 
256  int32 castTime = spellCastTimeEntry->CastTime;
257 
258  if (spell)
259  {
260  if (Player* modOwner = spell->GetCaster()->GetSpellModOwner())
261  modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell);
262 
263  if (!(spellInfo->Attributes & (SPELL_ATTR0_ABILITY | SPELL_ATTR0_TRADESPELL)))
264  castTime = int32(castTime * spell->GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED));
265  else
266  {
267  if (spell->IsRangedSpell() && !spell->IsAutoRepeat())
268  castTime = int32(castTime * spell->GetCaster()->m_modAttackSpeedPct[RANGED_ATTACK]);
269  }
270  }
271 
272  if (spellInfo->Attributes & SPELL_ATTR0_RANGED && (!spell || !spell->IsAutoRepeat()))
273  castTime += 500;
274 
275  return (castTime > 0) ? uint32(castTime) : 0;
276 }
277 
278 bool IsPassiveSpell(uint32 spellId)
279 {
280  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
281  if (!spellInfo)
282  return false;
283  return IsPassiveSpell(spellInfo);
284 }
285 
286 bool IsPassiveSpell(SpellEntry const* spellInfo)
287 {
288  return (spellInfo->Attributes & SPELL_ATTR0_PASSIVE) != 0;
289 }
290 
292 {
293  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
294  if (!spellInfo)
295  return false;
296  if (spellInfo->Attributes & SPELL_ATTR0_PASSIVE)
297  return false;
299  return false;
300  return true;
301 }
302 
303 uint32 CalculatePowerCost(SpellEntry const* spellInfo, Unit const* caster, SpellSchoolMask schoolMask)
304 {
305  // Spell drain all exist power on cast (Only paladin lay of Hands)
306  if (spellInfo->AttributesEx & SPELL_ATTR1_DRAIN_ALL_POWER)
307  {
308  // If power type - health drain all
309  if (spellInfo->powerType == POWER_HEALTH)
310  return caster->GetHealth();
311  // Else drain all power
312  if (spellInfo->powerType < MAX_POWERS)
313  return caster->GetPower(Powers(spellInfo->powerType));
314  sLog.outError("CalculateManaCost: Unknown power type '%d' in spell %d", spellInfo->powerType, spellInfo->Id);
315  return 0;
316  }
317 
318  // Base powerCost
319  int32 powerCost = spellInfo->manaCost;
320  // PCT cost from total amount
321  if (spellInfo->ManaCostPercentage)
322  {
323  switch (spellInfo->powerType)
324  {
325  // health as power used
326  case POWER_HEALTH:
327  powerCost += spellInfo->ManaCostPercentage * caster->GetCreateHealth() / 100;
328  break;
329  case POWER_MANA:
330  powerCost += spellInfo->ManaCostPercentage * caster->GetCreateMana() / 100;
331  break;
332  case POWER_RAGE:
333  case POWER_FOCUS:
334  case POWER_ENERGY:
335  case POWER_HAPPINESS:
336  powerCost += spellInfo->ManaCostPercentage * caster->GetMaxPower(Powers(spellInfo->powerType)) / 100;
337  break;
338  default:
339  sLog.outError("CalculateManaCost: Unknown power type '%d' in spell %d", spellInfo->powerType, spellInfo->Id);
340  return 0;
341  }
342  }
343  SpellSchools school = GetFirstSchoolInMask(schoolMask);
344  // Flat mod from caster auras by spell school
345  powerCost += caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school);
346  // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
348  powerCost += caster->GetAttackTime(OFF_ATTACK) / 100;
349  // Apply cost mod by spell
350  if (Player* modOwner = caster->GetSpellModOwner())
351  modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, powerCost);
352 
354  {
355  GtNPCManaCostScalerEntry const* spellScaler = sGtNPCManaCostScalerStore.LookupEntry(spellInfo->spellLevel - 1);
356  GtNPCManaCostScalerEntry const* casterScaler = sGtNPCManaCostScalerStore.LookupEntry(caster->getLevel() - 1);
357  if (spellScaler && casterScaler)
358  powerCost *= casterScaler->ratio / spellScaler->ratio;
359  }
360 
361  // PCT mod from user auras by school
362  powerCost = int32(powerCost * (1.0f + caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER + school)));
363  if (powerCost < 0)
364  powerCost = 0;
365  return powerCost;
366 }
367 
368 /*bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
369 {
370  SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
371  SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
372  if (!spellInfo_1 || !spellInfo_2) return false;
373  if (spellInfo_1->Id == spellId_2) return false;
374 
375  if (spellInfo_1->Effect[effIndex_1] != spellInfo_2->Effect[effIndex_2] ||
376  spellInfo_1->EffectItemType[effIndex_1] != spellInfo_2->EffectItemType[effIndex_2] ||
377  spellInfo_1->EffectMiscValue[effIndex_1] != spellInfo_2->EffectMiscValue[effIndex_2] ||
378  spellInfo_1->EffectApplyAuraName[effIndex_1] != spellInfo_2->EffectApplyAuraName[effIndex_2])
379  return false;
380 
381  return true;
382 }*/
383 
384 int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
385 {
386  SpellEntry const* spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
387  SpellEntry const* spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
388  if (!spellInfo_1 || !spellInfo_2) return 0;
389  if (spellId_1 == spellId_2) return 0;
390 
391  int32 diff = spellInfo_1->EffectBasePoints[effIndex_1] - spellInfo_2->EffectBasePoints[effIndex_2];
392  if (spellInfo_1->EffectBasePoints[effIndex_1] + 1 < 0 && spellInfo_2->EffectBasePoints[effIndex_2] + 1 < 0) return -diff;
393  else return diff;
394 }
395 
397 {
398  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
399  if (!spellInfo)
400  return SPELL_SPECIFIC_NORMAL;
401 
402  switch (spellInfo->SpellFamilyName)
403  {
404  case SPELLFAMILY_GENERIC:
405  {
406  // Food / Drinks (mostly)
408  {
409  for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
410  {
411  if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_POWER_REGEN)
412  return SPELL_SPECIFIC_DRINK;
413 
414  if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_REGEN ||
416  return SPELL_SPECIFIC_FOOD;
417  }
418  }
419 
420  switch (spellInfo->Id)
421  {
422  case 12880: // warrior's Enrage rank 1
423  case 14201: // Enrage rank 2
424  case 14202: // Enrage rank 3
425  case 14203: // Enrage rank 4
426  case 14204: // Enrage rank 5
427  case 12292: // Death Wish
429  break;
430  default:
431  break;
432  }
433  break;
434  }
435  case SPELLFAMILY_MAGE:
436  {
437  // family flags 18(Molten), 25(Frost/Ice), 28(Mage)
438  if (spellInfo->SpellFamilyFlags & 0x12040000)
440 
441  if ((spellInfo->SpellFamilyFlags & 0x1000000) && spellInfo->EffectApplyAuraName[0] == SPELL_AURA_MOD_CONFUSE)
443 
444  break;
445  }
446  case SPELLFAMILY_WARRIOR:
447  {
448  // Sunder Armor (vs Expose Armor)
449  if (spellInfo->SpellFamilyFlags & 0x00000000004000LL)
451 
452  break;
453  }
454  case SPELLFAMILY_WARLOCK:
455  {
456  // only warlock curses have this
457  if (spellInfo->Dispel == DISPEL_CURSE)
458  return SPELL_SPECIFIC_CURSE;
459 
460  // family flag 37 (only part spells have family name)
461  if (spellInfo->SpellFamilyFlags & 0x2000000000LL)
463 
464  //seed of corruption and corruption
465  if (spellInfo->SpellFamilyFlags & 0x1000000002LL)
467  break;
468  }
469  case SPELLFAMILY_HUNTER:
470  {
471  // only hunter stings have this
472  if (spellInfo->Dispel == DISPEL_POISON)
473  return SPELL_SPECIFIC_STING;
474 
475  break;
476  }
477  case SPELLFAMILY_PALADIN:
478  {
479  if (IsSealSpell(spellInfo))
480  return SPELL_SPECIFIC_SEAL;
481 
482  if ((spellInfo->SpellFamilyFlags & 0x00000820180400LL) && (spellInfo->AttributesEx3 & 0x200))
484 
485  for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
486  {
487  // only paladin auras have this
488  if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
489  return SPELL_SPECIFIC_AURA;
490  }
491  break;
492  }
493  case SPELLFAMILY_SHAMAN:
494  {
495  if (IsElementalShield(spellInfo))
497 
498  break;
499  }
500  case SPELLFAMILY_ROGUE:
501  {
502  // Expose Armor (vs Sunder Armor)
503  if (spellInfo->SpellFamilyFlags & 0x00000000080000LL)
505  break;
506  }
507  }
508 
509  // only warlock armor/skin have this (in additional to family cases)
510  if (spellInfo->SpellVisual == 130 && spellInfo->SpellIconID == 89)
512 
513  // only hunter aspects have this (but not all aspects in hunter family)
514  if (spellInfo->activeIconID == 122 && (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NATURE) &&
515  (spellInfo->Attributes & 0x50000) != 0 && (spellInfo->Attributes & 0x9000010) == 0)
516  return SPELL_SPECIFIC_ASPECT;
517 
518  for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
519  {
520  if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
521  {
522  switch (spellInfo->EffectApplyAuraName[i])
523  {
527  return SPELL_SPECIFIC_CHARM;
531  return SPELL_SPECIFIC_TRACKER;
532  }
533  }
534  }
535 
536  return SPELL_SPECIFIC_NORMAL;
537 }
538 
539 bool IsPositiveTarget(uint32 targetA, uint32 targetB)
540 {
541  // non-positive targets
542  switch (targetA)
543  {
551  case TARGET_UNIT_CHANNEL:
552  return false;
553  default:
554  break;
555  }
556  if (targetB)
557  return IsPositiveTarget(targetB, 0);
558  return true;
559 }
560 
561 bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
562 {
563  SpellEntry const* spellproto = sSpellStore.LookupEntry(spellId);
564  if (!spellproto)
565  return false;
566 
567  // not found a single positive spell with this attribute
568  if (spellproto->Attributes & SPELL_ATTR0_NEGATIVE_1)
569  return false;
570 
571  switch (spellproto->SpellFamilyName)
572  {
573  case SPELLFAMILY_GENERIC:
574  switch (spellproto->Id)
575  {
576  case 6716: // Test of Faith
577  case 23333: // Warsong Flag
578  case 23335: // Silverwing Flag
579  case 34976: // Netherstorm Flag
580  return true;
581  case 1852: // Silenced (GM)
582  case 46392: // Focused Assault
583  case 46393: // Brutal Assault
584  case 43437: // Paralyzed
585  case 28441: // AB Effect 000
586  case 37675: // Chaos Blast
587  case 41519: // Mark of Stormrage
588  case 34877: // Custodian of Time
589  case 34700: // Allergic Reaction
590  case 31719: // Suspension
591  case 43501: // Siphon Soul (Hexlord Spell)
592  case 30457: // Complete vulnerability
593  case 30529: // Recently In Game - Chess Event
594  case 37465: // Rain of Fire
595  case 45661: // Encapsulate (Felmyst - Sunwell Plateau)
596  case 45662:
597  case 45665:
598  return false;
599  default:
600  break;
601  }
602  break;
603  case SPELLFAMILY_MAGE:
604  {
605  // Amplify Magic, Dampen Magic
606  if (spellproto->SpellFamilyFlags == 0x00002000)
607  return true;
608 
609  switch (spellproto->Id)
610  {
611  case 31579: // Arcane Empowerment Rank1 talent aura with one positive and one negative (check not needed in wotlk)
612  case 31582: // Arcane Empowerment Rank2
613  case 31583: // Arcane Empowerment Rank3
614  return true;
615  default:
616  break;
617  }
618  }
619  break;
620  default:
621  break;
622  }
623 
624  switch (spellproto->Mechanic)
625  {
627  return true;
628  default:
629  break;
630  }
631 
632  switch (spellproto->Effect[effIndex])
633  {
634  // always positive effects (check before target checks that provided non-positive result in some case for positive effects)
635  case SPELL_EFFECT_HEAL:
640  return true;
642  return false;
643 
644  // non-positive aura use
647  {
648  switch (spellproto->EffectApplyAuraName[effIndex])
649  {
650  case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from bas point sign (negative -> negative)
651  case SPELL_AURA_MOD_STAT:
657  if (spellproto->EffectBasePoints[effIndex] + int32(spellproto->EffectBaseDice[effIndex]) < 0)
658  return false;
659  break;
660  case SPELL_AURA_MOD_DAMAGE_TAKEN: // dependent from bas point sign (positive -> negative)
661  if (spellproto->EffectBasePoints[effIndex] + int32(spellproto->EffectBaseDice[effIndex]) > 0)
662  return false;
663  break;
665  if (spellproto->EffectBasePoints[effIndex] + int32(spellproto->EffectBaseDice[effIndex]) > 0)
666  return true; // some expected positive spells have SPELL_ATTR1_NEGATIVE
667  break;
669  return true;
672  if (spellId != spellproto->EffectTriggerSpell[effIndex])
673  {
674  uint32 spellTriggeredId = spellproto->EffectTriggerSpell[effIndex];
675  SpellEntry const* spellTriggeredProto = sSpellStore.LookupEntry(spellTriggeredId);
676 
677  if (spellTriggeredProto)
678  {
679  // non-positive targets of main spell return early
680  for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
681  {
682  // if non-positive trigger cast targeted to positive target this main cast is non-positive
683  // this will place this spell auras as debuffs
684  if (!IsPositiveTarget(spellTriggeredProto->EffectImplicitTargetA[i], spellTriggeredProto->EffectImplicitTargetB[i]) && !IsPositiveEffect(spellTriggeredId, i))
685  return false;
686  }
687  }
688  }
689  break;
691  // many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example)
692  break;
693  case SPELL_AURA_MOD_STUN: //have positive and negative spells, we can't sort its correctly at this moment.
694  if (effIndex == 0 && spellproto->Effect[1] == 0 && spellproto->Effect[2] == 0)
695  return false; // but all single stun aura spells is negative
696  break;
698  if (spellproto->Id == 24740) // Wisp Costume
699  return true;
700  return false;
701  case SPELL_AURA_MOD_ROOT:
703  case SPELL_AURA_GHOST:
707  return false;
708  case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also.
709  // part of negative spell if casted at self (prevent cancel)
710  if (spellproto->EffectImplicitTargetA[effIndex] == TARGET_UNIT_CASTER)
711  return false;
712  break;
713  case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also
714  // part of positive spell if casted at self
715  if (spellproto->EffectImplicitTargetA[effIndex] != TARGET_UNIT_CASTER)
716  return false;
717  // but not this if this first effect (didn't find better check)
718  if (spellproto->Attributes & SPELL_ATTR0_NEGATIVE_1 && effIndex == 0)
719  return false;
720  break;
722  {
723  // non-positive immunities
724  switch (spellproto->EffectMiscValue[effIndex])
725  {
726  case MECHANIC_BANDAGE:
727  case MECHANIC_SHIELD:
728  case MECHANIC_MOUNT:
730  return false;
731  default:
732  break;
733  }
734  break;
735  }
736  case SPELL_AURA_ADD_FLAT_MODIFIER: // mods
738  {
739  // non-positive mods
740  switch (spellproto->EffectMiscValue[effIndex])
741  {
742  case SPELLMOD_COST: // dependent from bas point sign (negative -> positive)
743  if (spellproto->EffectBasePoints[effIndex] + int32(spellproto->EffectBaseDice[effIndex]) > 0)
744  {
745  if (spellproto->Id == 12042) // Arcane Power is a positive spell
746  return true;
747 
748  return false;
749  }
750  break;
751  default:
752  break;
753  }
754  break;
755  }
756  default:
757  break;
758  }
759  break;
760  }
761  default:
762  break;
763  }
764 
765  // non-positive targets
766  if (!IsPositiveTarget(spellproto->EffectImplicitTargetA[effIndex], spellproto->EffectImplicitTargetB[effIndex]))
767  return false;
768 
769  // ok, positive
770  return true;
771 }
772 
773 bool IsPositiveSpell(uint32 spellId)
774 {
775  // spells with at least one negative effect are considered negative
776  // some self-applied spells have negative effects but in self casting case negative check ignored.
777  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
778  if (!IsPositiveEffect(spellId, i))
779  return false;
780  return true;
781 }
782 
783 bool IsSingleTargetSpell(SpellEntry const* spellInfo)
784 {
785  // all other single target spells have if it has AttributesEx5
787  return true;
788 
789  // TODO - need found Judgements rule
790  switch (GetSpellSpecific(spellInfo->Id))
791  {
793  return true;
794  default:
795  break;
796  }
797 
798  // single target triggered spell.
799  // Not real client side single target spell, but it' not triggered until prev. aura expired.
800  // This is allow store it in single target spells list for caster for spell proc checking
801  if (spellInfo->Id == 38324) // Regeneration (triggered by 38299 (HoTs on Heals))
802  return true;
803 
804  return false;
805 }
806 
807 bool IsSingleTargetSpells(SpellEntry const* spellInfo1, SpellEntry const* spellInfo2)
808 {
809  // TODO - need better check
810  // Equal icon and spellfamily
811  if (spellInfo1->SpellFamilyName == spellInfo2->SpellFamilyName &&
812  spellInfo1->SpellIconID == spellInfo2->SpellIconID)
813  return true;
814 
815  // TODO - need found Judgements rule
816  SpellSpecific spec1 = GetSpellSpecific(spellInfo1->Id);
817  // spell with single target specific types
818  switch (spec1)
819  {
822  if (GetSpellSpecific(spellInfo2->Id) == spec1)
823  return true;
824  default:
825  break;
826  }
827 
828  return false;
829 }
830 
831 bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId)
832 {
833  SpellEntry const* spellproto = sSpellStore.LookupEntry(spellId);
834  if (!spellproto) return false;
835 
836  for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
837  if (spellproto->EffectApplyAuraName[i] == auraType)
838  return true;
839  return false;
840 }
841 
843 {
844  // talents that learn spells can have stance requirements that need ignore
845  // (this requirement only for client-side stance show in talent description)
846  if (GetTalentSpellCost(spellInfo->Id) > 0 &&
847  (spellInfo->Effect[0] == SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[1] == SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[2] == SPELL_EFFECT_LEARN_SPELL))
848  return SPELL_CAST_OK;
849 
850  uint32 stanceMask = (form ? 1 << (form - 1) : 0);
851 
852  if (stanceMask & spellInfo->StancesNot) // can explicitly not be casted in this stance
854 
855  if (stanceMask & spellInfo->Stances) // can explicitly be casted in this stance
856  return SPELL_CAST_OK;
857 
858  bool actAsShifted = false;
859  if (form > 0)
860  {
861  SpellShapeshiftEntry const* shapeInfo = sSpellShapeshiftStore.LookupEntry(form);
862  if (!shapeInfo)
863  {
864  sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form);
865  return SPELL_CAST_OK;
866  }
867  actAsShifted = !(shapeInfo->flags1 & 1); // shapeshift acts as normal form for spells
868  }
869 
870  if (actAsShifted)
871  {
872  if (spellInfo->Attributes & SPELL_ATTR0_NOT_SHAPESHIFT) // not while shapeshifted
874  else if (spellInfo->Stances != 0) // needs other shapeshift
876  }
877  else
878  {
879  // needs shapeshift
880  if (!(spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_NEED_SHAPESHIFT) && spellInfo->Stances != 0)
882  }
883 
884  return SPELL_CAST_OK;
885 }
886 
888 {
889  mSpellTargetPositions.clear(); // need for reload case
890 
891  uint32 count = 0;
892 
893  // 0 1 2 3 4 5
894  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position");
895  if (!result)
896  {
897 
898 
899 
900  sLog.outString(">> Loaded %u spell target coordinates", count);
901  return;
902  }
903 
904 
905  do
906  {
907  Field* fields = result->Fetch();
908 
909 
910  uint32 Spell_ID = fields[0].GetUInt32();
911 
913 
914  st.target_mapId = fields[1].GetUInt32();
915  st.target_X = fields[2].GetFloat();
916  st.target_Y = fields[3].GetFloat();
917  st.target_Z = fields[4].GetFloat();
918  st.target_Orientation = fields[5].GetFloat();
919 
920  MapEntry const* mapEntry = sMapStore.LookupEntry(st.target_mapId);
921  if (!mapEntry)
922  {
923  sLog.outErrorDb("Spell (ID:%u) target map (ID: %u) does not exist in Map.dbc.", Spell_ID, st.target_mapId);
924  continue;
925  }
926 
927  if (st.target_X == 0 && st.target_Y == 0 && st.target_Z == 0)
928  {
929  sLog.outErrorDb("Spell (ID:%u) target coordinates not provided.", Spell_ID);
930  continue;
931  }
932 
933  SpellEntry const* spellInfo = sSpellStore.LookupEntry(Spell_ID);
934  if (!spellInfo)
935  {
936  sLog.outErrorDb("Spell (ID:%u) listed in spell_target_position does not exist.", Spell_ID);
937  continue;
938  }
939 
940  bool found = false;
941  for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
942  {
943  if (spellInfo->EffectImplicitTargetA[i] == TARGET_DST_DB || spellInfo->EffectImplicitTargetB[i] == TARGET_DST_DB)
944  {
945  found = true;
946  break;
947  }
948  }
949  if (!found)
950  {
951  sLog.outErrorDb("Spell (Id: %u) listed in spell_target_position does not have target TARGET_DST_DB (17).", Spell_ID);
952  continue;
953  }
954 
955  mSpellTargetPositions[Spell_ID] = st;
956  ++count;
957 
958  }
959  while (result->NextRow());
960 
961  sLog.outString(">> Loaded %u spell teleport coordinates", count);
962 }
963 
965 {
966  mSpellAffectMap.clear(); // need for reload case
967 
968  uint32 count = 0;
969 
970  // 0 1 2
971  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, effectId, SpellFamilyMask FROM spell_affect");
972  if (!result)
973  {
974 
975 
976 
977  sLog.outString(">> Loaded %u spell affect definitions", count);
978  return;
979  }
980 
981 
982  do
983  {
984  Field* fields = result->Fetch();
985 
986 
987  uint16 entry = fields[0].GetUInt16();
988  uint8 effectId = fields[1].GetUInt8();
989 
990  SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry);
991 
992  if (!spellInfo)
993  {
994  sLog.outErrorDb("Spell %u listed in spell_affect does not exist", entry);
995  continue;
996  }
997 
998  if (effectId >= 3)
999  {
1000  sLog.outErrorDb("Spell %u listed in spell_affect has invalid effect index (%u)", entry, effectId);
1001  continue;
1002  }
1003 
1004  if ((spellInfo->Effect[effectId] != SPELL_EFFECT_APPLY_AURA) ||
1005  (spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_FLAT_MODIFIER &&
1006  spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_PCT_MODIFIER &&
1007  spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER))
1008  {
1009  sLog.outErrorDb("Spell %u listed in spell_affect does not have 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);
1010  continue;
1011  }
1012 
1013  uint64 spellAffectMask = fields[2].GetUInt64();
1014 
1015  // Spell.dbc have own data for low part of SpellFamilyMask
1016  if (spellInfo->EffectItemType[effectId])
1017  {
1018  if (spellInfo->EffectItemType[effectId] == spellAffectMask)
1019  {
1020  sLog.outErrorDb("Spell %u listed in spell_affect has redundant (same with EffectItemType%d) data for effect index (%u), skipped.", entry, effectId + 1, effectId);
1021  continue;
1022  }
1023  }
1024 
1025  mSpellAffectMap.insert(SpellAffectMap::value_type((entry << 8) + effectId, spellAffectMask));
1026 
1027  ++count;
1028  }
1029  while (result->NextRow());
1030 
1031  sLog.outString(">> Loaded %u spell affect definitions", count);
1032 
1033  for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id)
1034  {
1035  SpellEntry const* spellInfo = sSpellStore.LookupEntry(id);
1036  if (!spellInfo)
1037  continue;
1038 
1039  for (int effectId = 0; effectId < MAX_SPELL_EFFECTS; ++effectId)
1040  {
1041  if (spellInfo->Effect[effectId] != SPELL_EFFECT_APPLY_AURA ||
1042  (spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_FLAT_MODIFIER &&
1043  spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_PCT_MODIFIER &&
1044  spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER))
1045  continue;
1046 
1047  if (spellInfo->EffectItemType[effectId] != 0)
1048  continue;
1049 
1050  if (mSpellAffectMap.find((id << 8) + effectId) != mSpellAffectMap.end())
1051  continue;
1052 
1053  sLog.outErrorDb("Spell %u (%s) misses spell_affect for effect %u", id, spellInfo->SpellName[sWorld.GetDefaultDbcLocale()], effectId);
1054  }
1055  }
1056 }
1057 
1058 bool SpellMgr::IsAffectedBySpell(SpellEntry const* spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const
1059 {
1060  // false for spellInfo == NULL
1061  if (!spellInfo)
1062  return false;
1063 
1064  SpellEntry const* affect_spell = sSpellStore.LookupEntry(spellId);
1065  // false for affect_spell == NULL
1066  if (!affect_spell)
1067  return false;
1068 
1069  // False if spellFamily not equal
1070  if (affect_spell->SpellFamilyName != spellInfo->SpellFamilyName)
1071  return false;
1072 
1073  // If familyFlags == 0
1074  if (!familyFlags)
1075  {
1076  // Get it from spellAffect table
1077  familyFlags = GetSpellAffectMask(spellId, effectId);
1078  // false if familyFlags == 0
1079  if (!familyFlags)
1080  return false;
1081  }
1082 
1083  // true
1084  if (familyFlags & spellInfo->SpellFamilyFlags)
1085  return true;
1086 
1087  return false;
1088 }
1089 
1091 {
1092  mSpellProcEventMap.clear(); // need for reload case
1093 
1094  uint32 count = 0;
1095 
1096  // 0 1 2 3 4 5 6 7 8
1097  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
1098  if (!result)
1099  {
1100  sLog.outString(">> Loaded %u spell proc event conditions", count);
1101  return;
1102  }
1103 
1104  uint32 customProc = 0;
1105  do
1106  {
1107  Field* fields = result->Fetch();
1108 
1109  uint16 entry = fields[0].GetUInt16();
1110 
1111  const SpellEntry* spell = sSpellStore.LookupEntry(entry);
1112  if (!spell)
1113  {
1114  sLog.outErrorDb("Spell %u listed in spell_proc_event does not exist", entry);
1115  continue;
1116  }
1117 
1118  SpellProcEventEntry spe;
1119 
1120  spe.schoolMask = fields[1].GetUInt32();
1121  spe.spellFamilyName = fields[2].GetUInt32();
1122  spe.spellFamilyMask = fields[3].GetUInt64();
1123  spe.procFlags = fields[4].GetUInt32();
1124  spe.procEx = fields[5].GetUInt32();
1125  spe.ppmRate = fields[6].GetFloat();
1126  spe.customChance = fields[7].GetFloat();
1127  spe.cooldown = fields[8].GetUInt32();
1128 
1129  mSpellProcEventMap[entry] = spe;
1130 
1131  if (spell->procFlags == 0)
1132  {
1133  if (spe.procFlags == 0)
1134  {
1135  sLog.outErrorDb("Spell %u listed in spell_proc_event probally not triggered spell", entry);
1136  continue;
1137  }
1138  customProc++;
1139  }
1140  ++count;
1141  }
1142  while (result->NextRow());
1143 
1144  if (customProc)
1145  sLog.outString(">> Loaded %u custom spell proc event conditions +%u custom", count, customProc);
1146  else
1147  sLog.outString(">> Loaded %u spell proc event conditions", count);
1148 }
1149 
1150 
1151 bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const* spellProcEvent, uint32 EventProcFlag, SpellEntry const* procSpell, uint32 procFlags, uint32 procExtra, bool active)
1152 {
1153  // No extra req need
1154  uint32 procEvent_procEx = PROC_EX_NONE;
1155 
1156  // check prockFlags for condition
1157  if ((procFlags & EventProcFlag) == 0)
1158  return false;
1159 
1160  /* Check Periodic Auras
1161 
1162  * Both hots and dots can trigger if spell has no PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS
1163  nor PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG
1164 
1165  * Only Hots can trigger if spell has PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS
1166 
1167  * Only dots can trigger if spell has both positivity flags or PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG
1168 
1169  */
1170 
1171  if (procFlags & PROC_FLAG_DONE_PERIODIC)
1172  {
1173  if (EventProcFlag & PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG)
1174  {
1175  if (!(procExtra & PROC_EX_INTERNAL_DOT))
1176  return false;
1177  }
1178  else if (EventProcFlag & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS
1179  && !(procExtra & PROC_EX_INTERNAL_HOT))
1180  return false;
1181  }
1182 
1183  if (procFlags & PROC_FLAG_TAKEN_PERIODIC)
1184  {
1185  if (EventProcFlag & PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG)
1186  {
1187  if (!(procExtra & PROC_EX_INTERNAL_DOT))
1188  return false;
1189  }
1190  else if (EventProcFlag & PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS
1191  && !(procExtra & PROC_EX_INTERNAL_HOT))
1192  return false;
1193  }
1194 
1195  // Always trigger for this
1197  return true;
1198 
1199  if (spellProcEvent) // Exist event data
1200  {
1201  // Store extra req
1202  procEvent_procEx = spellProcEvent->procEx;
1203 
1204  // For melee triggers
1205  if (procSpell == NULL)
1206  {
1207  // Check (if set) for school (melee attack have Normal school)
1208  if (spellProcEvent->schoolMask && (spellProcEvent->schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0)
1209  return false;
1210  }
1211  else // For spells need check school/spell family/family mask
1212  {
1213  // Potions can trigger only if spellfamily given
1214  if (procSpell->SpellFamilyName == SPELLFAMILY_POTION)
1215  {
1216  if (procSpell->SpellFamilyName == spellProcEvent->spellFamilyName)
1217  return true;
1218  return false;
1219  }
1220 
1221  // Check (if set) for school
1222  if (spellProcEvent->schoolMask && (spellProcEvent->schoolMask & procSpell->SchoolMask) == 0)
1223  return false;
1224 
1225  // Check (if set) for spellFamilyName
1226  if (spellProcEvent->spellFamilyName && (spellProcEvent->spellFamilyName != procSpell->SpellFamilyName))
1227  return false;
1228 
1229  // spellFamilyName is Ok need check for spellFamilyMask if present
1230  if (spellProcEvent->spellFamilyMask)
1231  {
1232  if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags) == 0)
1233  return false;
1234  active = true; // Spell added manualy -> so its active spell
1235  }
1236  }
1237  }
1238  // potions can trigger only if have spell_proc entry
1239  else if (procSpell && procSpell->SpellFamilyName == SPELLFAMILY_POTION)
1240  return false;
1241 
1242  // Check for extra req (if none) and hit/crit
1243  if (procEvent_procEx == PROC_EX_NONE)
1244  {
1245  // No extra req, so can trigger only for active (damage/healing present) and hit/crit
1246  if ((procExtra & (PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT)) && active)
1247  return true;
1248  }
1249  else // Passive spells hits here only if resist/reflect/immune/evade
1250  {
1251  // Exist req for PROC_EX_EX_TRIGGER_ALWAYS
1252  if (procEvent_procEx & PROC_EX_EX_TRIGGER_ALWAYS)
1253  return true;
1254  // Passive spells cant trigger if need hit
1255  if ((procEvent_procEx & PROC_EX_NORMAL_HIT) && !active)
1256  return false;
1257  // Check Extra Requirement like (hit/crit/miss/resist/parry/dodge/block/immune/reflect/absorb and other)
1258  if (procEvent_procEx & procExtra)
1259  return true;
1260  }
1261  return false;
1262 }
1263 
1265 {
1266  mSpellSpellGroup.clear(); // need for reload case
1267  mSpellGroupSpell.clear();
1268 
1269  uint32 count = 0;
1270 
1271  // 0 1
1272  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT id, spell_id FROM spell_group");
1273  if ( !result )
1274  {
1275  sLog.outString( ">> Loaded %u spell group definitions", count );
1276  return;
1277  }
1278 
1279  std::set<uint32> groups;
1280 
1281  do
1282  {
1283  Field* fields = result->Fetch();
1284 
1285  uint32 group_id = fields[0].GetUInt32();
1286  if (group_id <= SPELL_GROUP_DB_RANGE_MIN && group_id >= SPELL_GROUP_CORE_RANGE_MAX)
1287  {
1288  sLog.outErrorDb("SpellGroup id %u listed in `spell_groups` is in core range, but is not defined in core!", group_id);
1289  continue;
1290  }
1291  int32 spell_id = fields[1].GetInt32();
1292 
1293  groups.insert(std::set<uint32>::value_type(group_id));
1294  mSpellGroupSpell.insert(SpellGroupSpellMap::value_type((SpellGroup)group_id, spell_id));
1295 
1296  }
1297  while ( result->NextRow() );
1298 
1299  for (SpellGroupSpellMap::iterator itr = mSpellGroupSpell.begin(); itr != mSpellGroupSpell.end() ; )
1300  {
1301  if (itr->second < 0)
1302  {
1303  if (groups.find(abs(itr->second)) == groups.end())
1304  {
1305  sLog.outErrorDb("SpellGroup id %u listed in `spell_groups` does not exist", abs(itr->second));
1306  mSpellGroupSpell.erase(itr++);
1307  }
1308  else
1309  ++itr;
1310  }
1311  else
1312  {
1313  SpellEntry const* spellInfo = sSpellStore.LookupEntry(itr->second);
1314 
1315  if (!spellInfo)
1316  {
1317  sLog.outErrorDb("Spell %u listed in `spell_group` does not exist", itr->second);
1318  mSpellGroupSpell.erase(itr++);
1319  }
1320  else if (GetSpellRank(itr->second) > 1)
1321  {
1322  sLog.outErrorDb("Spell %u listed in `spell_group` is not first rank of spell", itr->second);
1323  mSpellGroupSpell.erase(itr++);
1324  }
1325  else
1326  ++itr;
1327  }
1328  }
1329 
1330  for (std::set<uint32>::iterator groupItr = groups.begin() ; groupItr != groups.end() ; ++groupItr)
1331  {
1332  std::set<uint32> spells;
1333  GetSetOfSpellsInSpellGroup(SpellGroup(*groupItr), spells);
1334 
1335  for (std::set<uint32>::iterator spellItr = spells.begin() ; spellItr != spells.end() ; ++spellItr)
1336  {
1337  ++count;
1338  mSpellSpellGroup.insert(SpellSpellGroupMap::value_type(*spellItr, SpellGroup(*groupItr)));
1339  }
1340  }
1341 
1342  sLog.outString( ">> Loaded %u spell group definitions", count );
1343 }
1344 
1346 {
1347  mSpellGroupStack.clear(); // need for reload case
1348 
1349  uint32 count = 0;
1350 
1351  // 0 1
1352  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT group_id, stack_rule FROM spell_group_stack_rules");
1353  if ( !result )
1354  {
1355  sLog.outString( ">> Loaded %u spell group stack rules", count );
1356  return;
1357  }
1358 
1359  do
1360  {
1361  Field* fields = result->Fetch();
1362 
1363  uint32 group_id = fields[0].GetUInt32();
1364  uint8 stack_rule = fields[1].GetUInt32();
1365  if (stack_rule >= SPELL_GROUP_STACK_RULE_MAX)
1366  {
1367  sLog.outErrorDb("SpellGroupStackRule %u listed in `spell_group_stack_rules` does not exist", stack_rule);
1368  continue;
1369  }
1370 
1372 
1373  if (spellGroup.first == spellGroup.second)
1374  {
1375  sLog.outErrorDb("SpellGroup id %u listed in `spell_group_stack_rules` does not exist", group_id);
1376  continue;
1377  }
1378 
1379  mSpellGroupStack[(SpellGroup)group_id] = (SpellGroupStackRule)stack_rule;
1380 
1381  ++count;
1382  }
1383  while ( result->NextRow() );
1384 
1385  sLog.outString( ">> Loaded %u spell group stack rules", count );
1386 }
1387 
1389 {
1390  mSpellThreatMap.clear(); // need for reload case
1391 
1392  uint32 count = 0;
1393 
1394  // 0 1 2 3
1395  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, flatMod, pctMod, apPctMod FROM spell_threat");
1396 
1397  if (!result)
1398  {
1399  sLog.outString( ">> Loaded %u aggro generating spells", count);
1400  return;
1401  }
1402 
1403  do
1404  {
1405  Field* fields = result->Fetch();
1406 
1407  uint32 entry = fields[0].GetUInt32();
1408 
1409  if (!sSpellStore.LookupEntry(entry))
1410  {
1411  sLog.outErrorDb("Spell %u listed in `spell_threat` does not exist", entry);
1412  continue;
1413  }
1414 
1415  SpellThreatEntry ste;
1416  ste.flatMod = fields[1].GetInt16();
1417  ste.pctMod = fields[2].GetFloat();
1418  ste.apPctMod = fields[3].GetFloat();
1419 
1420  mSpellThreatMap[entry] = ste;
1421  count++;
1422  }
1423  while (result->NextRow());
1424 
1425  sLog.outString(">> Loaded %u SpellThreatEntries.", count);
1426 }
1427 
1429 {
1430  mSpellEnchantProcEventMap.clear(); // need for reload case
1431 
1432  uint32 count = 0;
1433 
1434  // 0 1 2 3
1435  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, customChance, PPMChance, procEx FROM spell_enchant_proc_data");
1436  if (!result)
1437  {
1438  sLog.outString(">> Loaded %u spell enchant proc event conditions", count);
1439  return;
1440  }
1441 
1442  do
1443  {
1444  Field* fields = result->Fetch();
1445 
1446  uint32 enchantId = fields[0].GetUInt32();
1447 
1448  SpellItemEnchantmentEntry const* ench = sSpellItemEnchantmentStore.LookupEntry(enchantId);
1449  if (!ench)
1450  {
1451  sLog.outErrorDb("Enchancment %u listed in spell_enchant_proc_data does not exist", enchantId);
1452  continue;
1453  }
1454 
1456 
1457  spe.customChance = fields[1].GetUInt32();
1458  spe.PPMChance = fields[2].GetFloat();
1459  spe.procEx = fields[3].GetUInt32();
1460 
1461  mSpellEnchantProcEventMap[enchantId] = spe;
1462 
1463  ++count;
1464  }
1465  while (result->NextRow());
1466 
1467  sLog.outString(">> Loaded %u enchant proc data definitions", count);
1468 }
1469 
1471 {
1472  // 0 1 2 3 4 5 6 7 8 9 10 11 12
1473  if (QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT entry, effIndex, bitMaskCondition, condition0, data0, condition1, data1, condition2, data2, condition3, data3, condition4, data4 FROM spell_dummy_condition ORDER BY entry ASC"))
1474  {
1475  Field* field;
1476  SpellDummyConditionEntry sdcEntry;
1477 
1478  do
1479  {
1480  field = result->Fetch();
1481 
1482  sdcEntry.entry = field[0].GetUInt32();
1483  sdcEntry.effIndex = SpellEffIndex(field[1].GetUInt32());
1484  sdcEntry.bitMaskCondition = field[2].GetUInt32();
1485 
1486  for (uint32 i = 0; i < 5; i++) // 5 condition - data pairs
1487  {
1488  sdcEntry.conditions[i].condition = static_cast<SpellDummyCondition>(field[3 + i * 2].GetUInt32());
1489  sdcEntry.conditions[i].data = field[4 + i * 2].GetInt32();
1490  }
1491 
1492  mSpellDummyConditionMap.insert( std::pair<uint32, SpellDummyConditionEntry>(sdcEntry.entry, sdcEntry) );
1493  }
1494  while (result->NextRow());
1495 
1496  sLog.outString(">> Loaded %llu spell dummy conditions", result->GetRowCount());
1497  return;
1498  }
1499 
1500  sLog.outString(">> Loaded 0 spell dummy conditions");
1501 }
1502 
1503 bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const* spellInfo_1, uint32 spellId_2) const
1504 {
1505  SpellEntry const* spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
1506  if (!spellInfo_1 || !spellInfo_2) return false;
1507  if (spellInfo_1->Id == spellId_2) return false;
1508 
1509  return GetFirstSpellInChain(spellInfo_1->Id) == GetFirstSpellInChain(spellId_2);
1510 }
1511 
1519 {
1520  if (spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH)
1521  {
1522  // These spells do not cost energy/rage/focus and their cost does not
1523  // change between ranks so we will allow only the highest rank in spellbook
1524 
1525  // One exception - Faerie Fire (feral) need to stack in order to properly show
1526  // up in talent tree otherwise on higher rank it will be seen as not used
1527  if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID && spellInfo->SpellFamilyFlags & 0x400)
1528  return true;
1529 
1530  return false;
1531  }
1532 
1533  if (IsProfessionSpell(spellInfo->Id))
1534  return false;
1535 
1536  // All stance spells. if any better way, change it.
1537  for (int i = 0; i < MAX_SPELL_EFFECTS; i++)
1538  {
1539  // Paladin aura Spell
1540  if (spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN
1541  && spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY)
1542  return false;
1543  // Druid form Spell
1544  if (spellInfo->SpellFamilyName == SPELLFAMILY_DRUID
1545  && spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA
1546  && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
1547  return false;
1548  // Rogue Stealth
1549  if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE
1550  && spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA
1551  && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
1552  return false;
1553  }
1554  return true;
1555 }
1556 
1564 bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool sameCaster) const
1565 {
1566  SpellEntry const* spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
1567  SpellEntry const* spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
1568 
1569  if (!spellInfo_1 || !spellInfo_2)
1570  return false;
1571 
1572  SpellGroupStackRule stackRule = CheckSpellGroupStackRules(spellInfo_1->Id, spellInfo_2->Id);
1573  if (stackRule)
1574  {
1575  if (stackRule == SPELL_GROUP_STACK_RULE_EXCLUSIVE)
1576  return true;
1577  if (sameCaster && stackRule == SPELL_GROUP_STACK_RULE_EXCLUSIVE_FROM_SAME_CASTER)
1578  return true;
1579  if (stackRule != SPELL_GROUP_STACK_RULE_DEFAULT)
1580  return false;
1581  }
1582 
1583  if (spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
1584  return false;
1585 
1586  if (!sameCaster)
1587  {
1588  // Iterate through effects
1589  for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
1590  if (spellInfo_1->Effect[i] == SPELL_EFFECT_APPLY_AURA
1591  || spellInfo_1->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA)
1592  // not area auras (shaman totem)
1593  switch (spellInfo_1->EffectApplyAuraName[i])
1594  {
1595  // DOT or HOT from different casters will stack
1606  return false;
1607  default:
1608  break;
1609  }
1610  }
1611 
1612  // Iterate through specifics
1613  SpellSpecific spellSpec = GetSpellSpecific(spellId_1);
1614  switch (spellSpec)
1615  {
1616  case SPELL_SPECIFIC_STING:
1617  case SPELL_SPECIFIC_CURSE:
1618  case SPELL_SPECIFIC_ASPECT:
1621  return sameCaster == (spellSpec == GetSpellSpecific(spellId_2));
1622  default:
1623  break;
1624  }
1625 
1626  // generic spells
1627  if (!spellInfo_1->SpellFamilyName)
1628  {
1629  if (!spellInfo_1->SpellIconID
1630  || spellInfo_1->SpellIconID == 1
1631  || spellInfo_1->SpellIconID != spellInfo_2->SpellIconID)
1632  return false;
1633  }
1634 
1635  // check for class spells
1636  else
1637  {
1638  if (spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags)
1639  return false;
1640  }
1641 
1642  //use data of highest rank spell(needed for spells which ranks have different effects)
1643  spellInfo_1 = sSpellStore.LookupEntry(GetLastSpellInChain(spellId_1));
1644  spellInfo_2 = sSpellStore.LookupEntry(GetLastSpellInChain(spellId_2));
1645 
1646  //if spells have exactly the same effect they cannot stack
1647  for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
1648  if (spellInfo_1->Effect[i] != spellInfo_2->Effect[i]
1649  || spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i]
1650  || spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i]) // paladin resist aura
1651  return false; // need itemtype check? need an example to add that check
1652 
1653  return true;
1654 }
1655 
1657 {
1658  spell_id = GetFirstSpellInChain(spell_id);
1659  return mSpellSpellGroup.equal_range(spell_id);
1660 }
1661 
1663 {
1665  for (SpellSpellGroupMap::const_iterator itr = spellGroup.first; itr != spellGroup.second; ++itr)
1666  {
1667  if (itr->second == groupid)
1668  return true;
1669  }
1670  return false;
1671 }
1672 
1674 {
1675  return mSpellGroupSpell.equal_range(group_id);
1676 }
1677 
1678 void SpellMgr::GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set<uint32>& foundSpells) const
1679 {
1680  std::set<SpellGroup> usedGroups;
1681  GetSetOfSpellsInSpellGroup(group_id, foundSpells, usedGroups);
1682 }
1683 
1684 void SpellMgr::GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set<uint32>& foundSpells, std::set<SpellGroup>& usedGroups) const
1685 {
1686  if (usedGroups.find(group_id) != usedGroups.end())
1687  return;
1688  usedGroups.insert(group_id);
1689 
1691  for (SpellGroupSpellMap::const_iterator itr = groupSpell.first; itr != groupSpell.second; ++itr)
1692  {
1693  if (itr->second < 0)
1694  {
1695  SpellGroup currGroup = (SpellGroup)abs(itr->second);
1696  GetSetOfSpellsInSpellGroup(currGroup, foundSpells, usedGroups);
1697  }
1698  else
1699  {
1700  foundSpells.insert(itr->second);
1701  }
1702  }
1703 }
1704 
1706 {
1707  spellid_1 = GetFirstSpellInChain(spellid_1);
1708  spellid_2 = GetFirstSpellInChain(spellid_2);
1709  if (spellid_1 == spellid_2)
1711  // find SpellGroups which are common for both spells
1712  SpellSpellGroupMapBounds spellGroup1 = GetSpellSpellGroupMapBounds(spellid_1);
1713  std::set<SpellGroup> groups;
1714  for (SpellSpellGroupMap::const_iterator itr = spellGroup1.first; itr != spellGroup1.second; ++itr)
1715  {
1716  if (IsSpellMemberOfSpellGroup(spellid_2, itr->second))
1717  {
1718  bool add = true;
1719  SpellGroupSpellMapBounds groupSpell = GetSpellGroupSpellMapBounds(itr->second);
1720  for (SpellGroupSpellMap::const_iterator itr2 = groupSpell.first; itr2 != groupSpell.second; ++itr2)
1721  {
1722  if (itr2->second < 0)
1723  {
1724  SpellGroup currGroup = (SpellGroup)abs(itr2->second);
1725  if (IsSpellMemberOfSpellGroup(spellid_1, currGroup) && IsSpellMemberOfSpellGroup(spellid_2, currGroup))
1726  {
1727  add = false;
1728  break;
1729  }
1730  }
1731  }
1732  if (add)
1733  groups.insert(itr->second);
1734  }
1735  }
1736 
1738 
1739  for (std::set<SpellGroup>::iterator itr = groups.begin(); itr!= groups.end(); ++itr)
1740  {
1741  SpellGroupStackMap::const_iterator found = mSpellGroupStack.find(*itr);
1742  if (found != mSpellGroupStack.end())
1743  rule = found->second;
1744  if (rule)
1745  break;
1746  }
1747  return rule;
1748 }
1749 
1751 {
1752  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
1753  if (!spellInfo)
1754  return false;
1755 
1756  if (spellInfo->Effect[1] != SPELL_EFFECT_SKILL)
1757  return false;
1758 
1759  uint32 skill = spellInfo->EffectMiscValue[1];
1760 
1761  return IsProfessionSkill(skill);
1762 }
1763 
1765 {
1766  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spellId);
1767  if (!spellInfo)
1768  return false;
1769 
1770  if (spellInfo->Effect[1] != SPELL_EFFECT_SKILL)
1771  return false;
1772 
1773  uint32 skill = spellInfo->EffectMiscValue[1];
1774 
1775  return IsPrimaryProfessionSkill(skill);
1776 }
1777 
1779 {
1780  return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId) == 1;
1781 }
1782 
1783 SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const
1784 {
1785  // ignore passive spells
1786  if (IsPassiveSpell(spellInfo->Id))
1787  return spellInfo;
1788 
1789  bool needRankSelection = false;
1790  for (int i = 0; i < 3; i++)
1791  {
1792  if (IsPositiveEffect(spellInfo->Id, i) && (
1793  spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA ||
1795  ))
1796  {
1797  needRankSelection = true;
1798  break;
1799  }
1800  }
1801 
1802  // not required
1803  if (!needRankSelection)
1804  return spellInfo;
1805 
1806  for (uint32 nextSpellId = spellInfo->Id; nextSpellId != 0; nextSpellId = GetPrevSpellInChain(nextSpellId))
1807  {
1808  SpellEntry const* nextSpellInfo = sSpellStore.LookupEntry(nextSpellId);
1809  if (!nextSpellInfo)
1810  break;
1811 
1812  // if found appropriate level
1813  if (playerLevel + 10 >= nextSpellInfo->spellLevel)
1814  return nextSpellInfo;
1815 
1816  // one rank less then
1817  }
1818 
1819  // not found
1820  return NULL;
1821 }
1822 
1824 {
1825  mSpellsReqSpell.clear(); // need for reload case
1826  mSpellReq.clear(); // need for reload case
1827 
1828  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT spell_id, req_spell from spell_required");
1829 
1830  if (!result)
1831  {
1832  sLog.outString(">> Loaded 0 spell required records");
1833  sLog.outErrorDb("spell_required table is empty!");
1834  return;
1835  }
1836  uint32 rows = 0;
1837 
1838  do
1839  {
1840  Field* fields = result->Fetch();
1841 
1842  uint32 spell_id = fields[0].GetUInt32();
1843  uint32 spell_req = fields[1].GetUInt32();
1844 
1845  mSpellsReqSpell.insert (std::pair<uint32, uint32>(spell_req, spell_id));
1846  mSpellReq[spell_id] = spell_req;
1847  ++rows;
1848  }
1849  while (result->NextRow());
1850 
1851  sLog.outString(">> Loaded %u spell required records", rows);
1852 }
1853 
1855 {
1857  char const* SpellName;
1865 
1866  bool operator()(const SpellRankEntry& _Left, const SpellRankEntry& _Right)const
1867  {
1868  return (_Left.SkillId != _Right.SkillId ? _Left.SkillId < _Right.SkillId
1869  : _Left.SpellName != _Right.SpellName ? _Left.SpellName < _Right.SpellName
1870  : _Left.ProcFlags != _Right.ProcFlags ? _Left.ProcFlags < _Right.ProcFlags
1871  : _Left.SpellFamilyFlags != _Right.SpellFamilyFlags ? _Left.SpellFamilyFlags < _Right.SpellFamilyFlags
1872  : (_Left.SpellVisual != _Right.SpellVisual) && (!_Left.SpellVisual || !_Right.SpellVisual) ? _Left.SpellVisual < _Right.SpellVisual
1873  : (_Left.ManaCost != _Right.ManaCost) && (!_Left.ManaCost || !_Right.ManaCost) ? _Left.ManaCost < _Right.ManaCost
1874  : (_Left.DurationIndex != _Right.DurationIndex) && (!_Left.DurationIndex || !_Right.DurationIndex) ? _Left.DurationIndex < _Right.DurationIndex
1875  : (_Left.RangeIndex != _Right.RangeIndex) && (!_Left.RangeIndex || !_Right.RangeIndex || _Left.RangeIndex == 1 || !_Right.RangeIndex == 1) ? _Left.RangeIndex < _Right.RangeIndex
1876  : _Left.TargetAuraState < _Right.TargetAuraState
1877  );
1878  }
1879 };
1880 
1882 {
1884  char const* Rank;
1885 };
1886 
1888 {
1889  mSpellChains.clear(); // need for reload case
1890 
1891  std::vector<uint32> ChainedSpells;
1892  for (uint32 ability_id = 0; ability_id < sSkillLineAbilityStore.GetNumRows(); ability_id++)
1893  {
1894  SkillLineAbilityEntry const* AbilityInfo = sSkillLineAbilityStore.LookupEntry(ability_id);
1895  if (!AbilityInfo)
1896  continue;
1897  if (AbilityInfo->spellId == 20154) //exception to these rules (not needed in 3.0.3)
1898  continue;
1899  if (!AbilityInfo->forward_spellid)
1900  continue;
1901  ChainedSpells.push_back(AbilityInfo->forward_spellid);
1902  }
1903 
1904  std::multimap<SpellRankEntry, SpellRankValue, SpellRankEntry> RankMap;
1905 
1906  for (uint32 ability_id = 0; ability_id < sSkillLineAbilityStore.GetNumRows(); ability_id++)
1907  {
1908  SkillLineAbilityEntry const* AbilityInfo = sSkillLineAbilityStore.LookupEntry(ability_id);
1909  if (!AbilityInfo)
1910  continue;
1911 
1912  //get only spell with lowest ability_id to prevent doubles
1913  uint32 spell_id = AbilityInfo->spellId;
1914  if (spell_id == 20154) //exception to these rules (not needed in 3.0.3)
1915  continue;
1916  bool found = false;
1917  for (uint32 i = 0; i < ChainedSpells.size(); i++)
1918  {
1919  if (ChainedSpells.at(i) == spell_id)
1920  found = true;
1921  }
1922  if (found)
1923  continue;
1924 
1925  if (mSkillLineAbilityMap.lower_bound(spell_id)->second->id != ability_id)
1926  continue;
1927  SpellEntry const* SpellInfo = sSpellStore.LookupEntry(spell_id);
1928  if (!SpellInfo)
1929  continue;
1930  std::string sRank = SpellInfo->Rank[sWorld.GetDefaultDbcLocale()];
1931  if (sRank.empty())
1932  continue;
1933  //exception to polymorph spells-make pig and turtle other chain than sheep
1934  if ((SpellInfo->SpellFamilyName == SPELLFAMILY_MAGE) && (SpellInfo->SpellFamilyFlags & 0x1000000) && (SpellInfo->SpellIconID != 82))
1935  continue;
1936 
1937  SpellRankEntry entry;
1939  entry.SkillId = AbilityInfo->skillId;
1940  entry.SpellName = SpellInfo->SpellName[sWorld.GetDefaultDbcLocale()];
1941  entry.DurationIndex = SpellInfo->DurationIndex;
1942  entry.RangeIndex = SpellInfo->rangeIndex;
1943  entry.ProcFlags = SpellInfo->procFlags;
1944  entry.SpellFamilyFlags = SpellInfo->SpellFamilyFlags;
1945  entry.TargetAuraState = SpellInfo->TargetAuraState;
1946  entry.SpellVisual = SpellInfo->SpellVisual;
1947  entry.ManaCost = SpellInfo->manaCost;
1948 
1949  for (;;)
1950  {
1951  AbilityInfo = mSkillLineAbilityMap.lower_bound(spell_id)->second;
1952  value.Id = spell_id;
1953  value.Rank = SpellInfo->Rank[sWorld.GetDefaultDbcLocale()];
1954  RankMap.insert(std::pair<SpellRankEntry, SpellRankValue>(entry, value));
1955  spell_id = AbilityInfo->forward_spellid;
1956  SpellInfo = sSpellStore.LookupEntry(spell_id);
1957  if (!SpellInfo)
1958  break;
1959  }
1960  }
1961 
1962 
1963  uint32 count = 0;
1964 
1965  for (std::multimap<SpellRankEntry, SpellRankValue, SpellRankEntry>::iterator itr = RankMap.begin(); itr != RankMap.end();)
1966  {
1967  SpellRankEntry entry = itr->first;
1968  //trac errors in extracted data
1969  std::multimap<char const*, std::multimap<SpellRankEntry, SpellRankValue, SpellRankEntry>::iterator> RankErrorMap;
1970  for (std::multimap<SpellRankEntry, SpellRankValue, SpellRankEntry>::iterator itr2 = RankMap.lower_bound(entry); itr2 != RankMap.upper_bound(entry); itr2++)
1971  RankErrorMap.insert(std::pair<char const*, std::multimap<SpellRankEntry, SpellRankValue, SpellRankEntry>::iterator>(itr2->second.Rank, itr2));
1972  for (std::multimap<char const*, std::multimap<SpellRankEntry, SpellRankValue, SpellRankEntry>::iterator>::iterator itr2 = RankErrorMap.begin(); itr2 != RankErrorMap.end();)
1973  {
1974  char const* err_entry = itr2->first;
1975  uint32 rank_count = RankErrorMap.count(itr2->first);
1976  if (rank_count > 1)
1977  for (itr2 = RankErrorMap.lower_bound(err_entry); itr2 != RankErrorMap.upper_bound(err_entry); itr2++)
1978  {
1979  sLog.outDebug("There is a duplicate rank entry (%s) for spell: %u", itr2->first, itr2->second->second.Id);
1980  sLog.outDebug("Spell %u removed from chain data.", itr2->second->second.Id);
1981  RankMap.erase(itr2->second);
1982  itr = RankMap.lower_bound(entry);
1983  }
1984  else
1985  itr2++;
1986  }
1987  //do not proceed for spells with less than 2 ranks
1988  uint32 spell_max_rank = RankMap.count(entry);
1989  if (spell_max_rank < 2)
1990  {
1991  itr = RankMap.upper_bound(entry);
1992  continue;
1993  }
1994 
1995  itr = RankMap.upper_bound(entry);
1996 
1997  //order spells by spells by spellLevel
1998  std::list<uint32> RankedSpells;
1999  uint32 min_spell_lvl = 0;
2000  std::multimap<SpellRankEntry, SpellRankValue, SpellRankEntry>::iterator min_itr;
2001  for (; RankMap.count(entry);)
2002  {
2003  for (std::multimap<SpellRankEntry, SpellRankValue, SpellRankEntry>::iterator itr2 = RankMap.lower_bound(entry); itr2 != RankMap.upper_bound(entry); itr2++)
2004  {
2005  SpellEntry const* SpellInfo = sSpellStore.LookupEntry(itr2->second.Id);
2006  if (SpellInfo->spellLevel < min_spell_lvl || itr2 == RankMap.lower_bound(entry))
2007  {
2008  min_spell_lvl = SpellInfo->spellLevel;
2009  min_itr = itr2;
2010  }
2011  }
2012  RankedSpells.push_back(min_itr->second.Id);
2013  RankMap.erase(min_itr);
2014  }
2015 
2016  //use data from talent.dbc
2017  uint16 talent_id = 0;
2018  for (std::list<uint32>::iterator itr2 = RankedSpells.begin(); itr2 != RankedSpells.end();)
2019  {
2020  if (TalentSpellPos const* TalentPos = GetTalentSpellPos(*itr2))
2021  {
2022  talent_id = TalentPos->talent_id;
2023  RankedSpells.erase(itr2);
2024  itr2 = RankedSpells.begin();
2025  }
2026  else
2027  itr2++;
2028  }
2029  if (talent_id)
2030  {
2031  TalentEntry const* TalentInfo = sTalentStore.LookupEntry(talent_id);
2032  for (uint8 rank = 5; rank; rank--)
2033  {
2034  if (TalentInfo->RankID[rank - 1])
2035  RankedSpells.push_front(TalentInfo->RankID[rank - 1]);
2036  }
2037  }
2038 
2039  count++;
2040 
2041  itr = RankMap.upper_bound(entry);
2042  uint32 spell_rank = 1;
2043  for (std::list<uint32>::iterator itr2 = RankedSpells.begin(); itr2 != RankedSpells.end(); spell_rank++)
2044  {
2045  uint32 spell_id = *itr2;
2046  mSpellChains[spell_id].rank = spell_rank;
2047  mSpellChains[spell_id].first = RankedSpells.front();
2048  mSpellChains[spell_id].last = RankedSpells.back();
2049 
2050  itr2++;
2051 
2052  if (spell_rank < 2)
2053  mSpellChains[spell_id].prev = 0;
2054 
2055  if (spell_id == RankedSpells.back())
2056  mSpellChains[spell_id].next = 0;
2057  else
2058  {
2059  mSpellChains[*itr2].prev = spell_id;
2060  mSpellChains[spell_id].next = *itr2;
2061  }
2062  }
2063  }
2064 
2065  //uncomment these two lines to print yourself list of spell_chains on startup
2066  // for (UNORDERED_MAP<uint32, SpellChainNode>::iterator itr=mSpellChains.begin();itr != mSpellChains.end();itr++)
2067  // sLog.outString("Id: %u, Rank: %d , %s",itr->first,itr->second.rank, sSpellStore.LookupEntry(itr->first)->Rank[sWorld.GetDefaultDbcLocale()]);
2068 
2069  sLog.outString(">> Loaded %u spell chains", count);
2070 }
2071 
2073 {
2074  mSpellLearnSkills.clear(); // need for reload case
2075 
2076  // search auto-learned skills and add its to map also for use in unlearn spells/talents
2077  uint32 dbc_count = 0;
2078  for (uint32 spell = 0; spell < sSpellStore.GetNumRows(); ++spell)
2079  {
2080  SpellEntry const* entry = sSpellStore.LookupEntry(spell);
2081 
2082  if (!entry)
2083  continue;
2084 
2085  for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
2086  {
2087  if (entry->Effect[i] == SPELL_EFFECT_SKILL)
2088  {
2089  SpellLearnSkillNode dbc_node;
2090  dbc_node.skill = entry->EffectMiscValue[i];
2091  if (dbc_node.skill != SKILL_RIDING)
2092  dbc_node.value = 1;
2093  else
2094  dbc_node.value = (entry->EffectBasePoints[i] + 1) * 75;
2095  dbc_node.maxvalue = (entry->EffectBasePoints[i] + 1) * 75;
2096 
2097  mSpellLearnSkills[spell] = dbc_node;
2098  ++dbc_count;
2099  break;
2100  }
2101  }
2102  }
2103 
2104  sLog.outString(">> Loaded %u Spell Learn Skills from DBC", dbc_count);
2105 }
2106 
2108 {
2109  mSpellLearnSpells.clear(); // need for reload case
2110 
2111  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT entry, SpellID FROM spell_learn_spell");
2112  if (!result)
2113  {
2114 
2115  sLog.outString(">> Loaded 0 spell learn spells");
2116  sLog.outErrorDb("spell_learn_spell table is empty!");
2117  return;
2118  }
2119 
2120  uint32 count = 0;
2121 
2122  do
2123  {
2124  Field* fields = result->Fetch();
2125 
2126  uint32 spell_id = fields[0].GetUInt32();
2127 
2128  SpellLearnSpellNode node;
2129  node.spell = fields[1].GetUInt32();
2130  node.autoLearned = false;
2131 
2132  if (!sSpellStore.LookupEntry(spell_id))
2133  {
2134  sLog.outErrorDb("Spell %u listed in spell_learn_spell does not exist", spell_id);
2135  continue;
2136  }
2137 
2138  if (!sSpellStore.LookupEntry(node.spell))
2139  {
2140  sLog.outErrorDb("Spell %u listed in spell_learn_spell does not exist", node.spell);
2141  continue;
2142  }
2143 
2144  mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spell_id, node));
2145 
2146  ++count;
2147  }
2148  while (result->NextRow());
2149 
2150  // search auto-learned spells and add its to map also for use in unlearn spells/talents
2151  uint32 dbc_count = 0;
2152  for (uint32 spell = 0; spell < sSpellStore.GetNumRows(); ++spell)
2153  {
2154  SpellEntry const* entry = sSpellStore.LookupEntry(spell);
2155 
2156  if (!entry)
2157  continue;
2158 
2159  for (int i = 0; i < MAX_SPELL_EFFECTS; ++i)
2160  {
2161  if (entry->Effect[i] == SPELL_EFFECT_LEARN_SPELL)
2162  {
2163  SpellLearnSpellNode dbc_node;
2164  dbc_node.spell = entry->EffectTriggerSpell[i];
2165  dbc_node.autoLearned = true;
2166 
2167  SpellLearnSpellMap::const_iterator db_node_begin = GetBeginSpellLearnSpell(spell);
2168  SpellLearnSpellMap::const_iterator db_node_end = GetEndSpellLearnSpell(spell);
2169 
2170  bool found = false;
2171  for (SpellLearnSpellMap::const_iterator itr = db_node_begin; itr != db_node_end; ++itr)
2172  {
2173  if (itr->second.spell == dbc_node.spell)
2174  {
2175  sLog.outErrorDb("Spell %u auto-learn spell %u in spell.dbc then the record in spell_learn_spell is redundant, please fix DB.",
2176  spell, dbc_node.spell);
2177  found = true;
2178  break;
2179  }
2180  }
2181 
2182  if (!found) // add new spell-spell pair if not found
2183  {
2184  mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spell, dbc_node));
2185  ++dbc_count;
2186  }
2187  }
2188  }
2189  }
2190 
2191  sLog.outString(">> Loaded %u spell learn spells + %u found in DBC", count, dbc_count);
2192 }
2193 
2195 {
2196  mSpellPetAuraMap.clear(); // need for reload case
2197 
2198  uint32 count = 0;
2199 
2200  // 0 1 2
2201  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT spell, pet, aura FROM spell_pet_auras");
2202  if (!result)
2203  {
2204  sLog.outString(">> Loaded %u spell pet auras", count);
2205  return;
2206  }
2207 
2208 
2209  do
2210  {
2211  Field* fields = result->Fetch();
2212 
2213  uint16 spell = fields[0].GetUInt16();
2214  uint16 pet = fields[1].GetUInt16();
2215  uint16 aura = fields[2].GetUInt16();
2216 
2217  SpellPetAuraMap::iterator itr = mSpellPetAuraMap.find(spell);
2218  if (itr != mSpellPetAuraMap.end())
2219  itr->second.AddAura(pet, aura);
2220  else
2221  {
2222  SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
2223  if (!spellInfo)
2224  {
2225  sLog.outErrorDb("Spell %u listed in spell_pet_auras does not exist", spell);
2226  continue;
2227  }
2228  int i = 0;
2229  for (; i < MAX_SPELL_EFFECTS; ++i)
2230  if ((spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA &&
2231  spellInfo->EffectApplyAuraName[i] == SPELL_AURA_DUMMY) ||
2232  spellInfo->Effect[i] == SPELL_EFFECT_DUMMY)
2233  break;
2234 
2235  if (i == 3)
2236  {
2237  sLog.outError("Spell %u listed in spell_pet_auras does not have dummy aura or dummy effect", spell);
2238  continue;
2239  }
2240 
2241  SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(aura);
2242  if (!spellInfo2)
2243  {
2244  sLog.outErrorDb("Aura %u listed in spell_pet_auras does not exist", aura);
2245  continue;
2246  }
2247 
2248  PetAura pa(pet, aura, spellInfo->EffectImplicitTargetA[i] == TARGET_UNIT_PET, spellInfo->EffectBasePoints[i] + spellInfo->EffectBaseDice[i]);
2249  mSpellPetAuraMap[spell] = pa;
2250  }
2251 
2252  ++count;
2253  }
2254  while (result->NextRow());
2255 
2256  sLog.outString(">> Loaded %u spell pet auras", count);
2257 }
2258 
2259 // set data in core for now
2261 {
2262  mSpellCustomAttr.resize(GetSpellStore()->GetNumRows());
2263 
2264  SpellEntry* spellInfo;
2265  for (uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i)
2266  {
2267  mSpellCustomAttr[i] = 0;
2268  spellInfo = (SpellEntry*)GetSpellStore()->LookupEntry(i);
2269  if (!spellInfo)
2270  continue;
2271 
2272  bool auraSpell = true;
2273  for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
2274  {
2275  if (spellInfo->Effect[j])
2276  if (spellInfo->Effect[j] != SPELL_EFFECT_APPLY_AURA
2278  //ignore target party for now
2279  {
2280  auraSpell = false;
2281  break;
2282  }
2283  }
2284  if (auraSpell)
2286 
2287  for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
2288  {
2289  switch (spellInfo->EffectApplyAuraName[j])
2290  {
2295  break;
2299  break;
2300  case SPELL_AURA_MOD_ROOT:
2303  break;
2304  default:
2305  break;
2306  }
2307 
2308  switch (spellInfo->Effect[j])
2309  {
2315  case SPELL_EFFECT_HEAL:
2317  break;
2318  case SPELL_EFFECT_CHARGE:
2319  if (!spellInfo->speed && !spellInfo->SpellFamilyName)
2320  spellInfo->speed = SPEED_CHARGE;
2322  break;
2325  break;
2327  if (IsPositionTarget(spellInfo->EffectImplicitTargetA[j]) ||
2329  spellInfo->Effect[j] = SPELL_EFFECT_TRIGGER_MISSILE;
2330  break;
2332  // Self-Ressurect spells shouldn't be usable in arenas
2334  break;
2335  }
2336  }
2337 
2338  for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
2339  {
2340  switch (spellInfo->EffectApplyAuraName[j])
2341  {
2344  case SPELL_AURA_MOD_CHARM:
2345  case SPELL_AURA_MOD_FEAR:
2346  case SPELL_AURA_MOD_STUN:
2349  break;
2350  }
2351  }
2352 
2353  for (uint32 j = 0; j < 16; j++)
2354  {
2355  if (spellInfo->ToolTip[j] && *spellInfo->ToolTip[j])
2356  {
2358  break;
2359  }
2360  }
2361 
2362  if (spellInfo->SpellVisual == 3879)
2364 
2365  // Natural Shapeshifter
2366  if (spellInfo->Id == 16834 || spellInfo->Id == 16835)
2367  {
2368  SpellEntry const* baseInfo = sSpellStore.LookupEntry(16833);
2369  spellInfo->DurationIndex = baseInfo->DurationIndex;
2370  }
2371 
2372  switch (spellInfo->Category)
2373  {
2375  // these spells have 2min shared cooldown, But the time doesn't seem to be in dbcs.
2376  // I have really no idea from where client gets the data, perhaps hardcoded like this?
2377  spellInfo->RecoveryTime = 2 * 60 * IN_MILLISECONDS;
2378  spellInfo->StartRecoveryTime = 2 * 60 * IN_MILLISECONDS;
2379  spellInfo->StartRecoveryCategory = 2 * 60 * IN_MILLISECONDS;
2380  break;
2381  }
2382 
2383  switch (i)
2384  {
2385  case 26029: // dark glare
2386  case 37433: // spout
2387  case 43140:
2388  case 43215: // flame breath
2390  break;
2391  case 24340:
2392  case 26558:
2393  case 28884: // Meteor
2394  case 36837:
2395  case 38903:
2396  case 41276: // Meteor
2397  case 26789: // Shard of the Fallen Star
2398  case 31436: // Malevolent Cleave
2399  case 35181: // Dive Bomb
2400  case 40810:
2401  case 43267:
2402  case 43268: // Saber Lash
2403  case 42384: // Brutal Swipe
2404  case 45150: // Meteor Slash
2406  switch (i) // Saber Lash Targets
2407  {
2408  case 40810:
2409  spellInfo->MaxAffectedTargets = 3;
2410  break;
2411  case 43267:
2412  case 43268:
2413  spellInfo->MaxAffectedTargets = 2;
2414  break;
2415  }
2416  break;
2417  case 44978:
2418  case 45001:
2419  case 45002: // Wild Magic
2420  case 45004:
2421  case 45006:
2422  case 45010: // Wild Magic
2423  case 31347: // Doom
2424  case 41635: // Prayer of Mending
2425  case 44869: // Spectral Blast
2426  case 45027: // Revitalize
2427  case 45976: // Muru Portal Channel
2428  case 39365: // Thundering Storm
2429  case 41071: // Raise Dead
2430  case 41172: // Rapid Shot
2431  case 40834: // Agonizing Flames
2432  spellInfo->MaxAffectedTargets = 1;
2433  break;
2434  case 36384: // Skartax Purple Beam
2435  spellInfo->MaxAffectedTargets = 2;
2436  break;
2437  case 41357: // L1 Acane Charge
2438  case 41376: // Spite
2439  case 39992: // Needle Spine
2440  case 29576: // Multi-Shot
2441  case 37790: // Spread Shot
2442  case 45248: // Shadow Blades
2443  case 41303: // Soul Drain
2444  spellInfo->MaxAffectedTargets = 3;
2445  break;
2446  case 38310: // Multi-Shot
2447  spellInfo->MaxAffectedTargets = 4;
2448  break;
2449  case 32205: // Place Burning Blade Pyre
2450  spellInfo->AttributesEx2 |= SPELL_ATTR2_IGNORE_LOS;
2451  break;
2452  case 42005: // Bloodboil
2453  case 38296: // Spitfire Totem
2454  case 37676: // Insidious Whisper
2455  case 46008: // Negative Energy
2456  case 45641: // Fire Bloom
2457  case 5484: // Howl Of Terror
2458  case 46771: // Flame Sear
2459  spellInfo->MaxAffectedTargets = 5;
2460  break;
2461  case 15286: // Vampiric Embrace
2462  case 34914: // Vampiric Touch
2463  spellInfo->Attributes |= SPELL_ATTR0_NOT_SHAPESHIFT;
2465  spellInfo->Stances = FORM_SHADOW;
2466  break;
2467  case 40827: // Sinful Beam
2468  case 40859: // Sinister Beam
2469  case 40860: // Vile Beam
2470  case 40861: // Wicked Beam
2471  spellInfo->MaxAffectedTargets = 10;
2472  break;
2473  case 46841: // Escape to the Isle of Quel'Denas
2474  spellInfo->EffectImplicitTargetB[0] = TARGET_UNIT_CASTER;
2475  break;
2476  case 8122:
2477  case 8124:
2478  case 10888:
2479  case 10890: // Psychic Scream
2480  case 12494: // Frostbite
2482  break;
2483  case 38794:
2484  case 33711: //Murmur's Touch
2485  spellInfo->MaxAffectedTargets = 1;
2486  spellInfo->EffectTriggerSpell[0] = 33760;
2487  break;
2488  case 36350: //They Must Burn Bomb Aura (self)
2489  spellInfo->EffectTriggerSpell[0] = 36325; // They Must Burn Bomb Drop (DND)
2490  break;
2491  case 44949: // Whirlwind's offhand attack - @todo remove this (50% weapon damage effect)
2492  spellInfo->Effect[1] = 0;
2493  break;
2494  case 12723: // Sweeping Strikes proc
2497  break;
2498  case 24905: // Moonkin form -> elune's touch
2499  spellInfo->EffectImplicitTargetA[2] = TARGET_UNIT_CASTER;
2500  break;
2501  case 7922: // Charge stun
2502  case 25274: // Intercept stun
2503  case 2094: // Blind
2504  case 20424: // Seal of Command Trigger
2505  spellInfo->speed = 590.0f; // Minor delay
2506  break;
2507  case 32220: // Judgement of Blood
2508  spellInfo->speed = 5.0f; // Minor delay
2509  break;
2510  case 1833: // Cheap Shot
2511  spellInfo->speed = 1230.0f; // Tiny delay
2512  break;
2513  case 26679: // Deadly Throw
2514  spellInfo->speed = 0; // Instant
2515  break;
2516  case 41013: // Parasitic Shadowfiend Passive
2517  spellInfo->EffectApplyAuraName[0] = 4; // proc debuff, and summon infinite fiends
2518  break;
2519  case 1543: // Flare
2520  spellInfo->speed = 0;
2521  break;
2522  case 27892: // To Anchor 1
2523  case 27928: // To Anchor 1
2524  case 27935: // To Anchor 1
2525  case 27915: // Anchor to Skulls
2526  case 27931: // Anchor to Skulls
2527  case 27937: // Anchor to Skulls
2528  spellInfo->rangeIndex = 13;
2529  break;
2530  case 34580:
2532  break;
2533  case 39384:
2534  spellInfo->Effect[1] = 0; //Delete this effect, could be fixed also by implementing script_targets for each spell effect..
2535  spellInfo->rangeIndex = 16;//1y, don't know why, but with 5y (dbc value) all fields around are effected too, so somethings wrong in range check for those spells propably..
2536  break;
2537  case 6774:
2538  spellInfo->AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO; // slice and dice no longer gives combat or remove stealth
2540  break;
2541  case 29200: // Purify Helboar Meat
2542  spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_CASTER;
2543  spellInfo->EffectImplicitTargetB[0] = 0;
2544  break;
2545  case 35460: // Fury of the Dreghood Elders
2547  break;
2548  case 4073: // Mechanical Dragonling
2549  case 19804: // Arcanite Dragonling
2550  case 12749: // Mithril Mechanical Dragonling
2551  case 13258: // Summon Goblin Bomb
2552  case 13166: // Battle Chicken
2554  break;
2555  case 13279: // Gnomish Death Ray (Dummy Target)
2558  break;
2559  case 31828: // Blessed Life (Rank 1)
2560  case 31829: // Blessed Life (Rank 2)
2561  case 31830: // Blessed Life (Rank 3)
2563  break;
2564  case 39095: // Amplify Damage (Prince Malchaazar)
2566  spellInfo->EffectImplicitTargetB[0] = 0;
2567  break;
2568  case 42389: // Nalorakk's Mangle
2570  spellInfo->EffectImplicitTargetB[1] = 0;
2571  break;
2572  case 29955: // "Arcane Missiles implict correctly target"
2573  spellInfo->EffectImplicitTargetA[0] = TARGET_UNIT_CASTER;
2574  break;
2575  case 33206: // "Pain Suppression dispel resistance"
2577  break;
2578  case 19970: // Entangling Roots (Rank 6) -- Nature's Grasp Proc
2579  case 19971: // Entangling Roots (Rank 5) -- Nature's Grasp Proc
2580  case 19972: // Entangling Roots (Rank 4) -- Nature's Grasp Proc
2581  case 19973: // Entangling Roots (Rank 3) -- Nature's Grasp Proc
2582  case 19974: // Entangling Roots (Rank 2) -- Nature's Grasp Proc
2583  case 19975: // Entangling Roots (Rank 1) -- Nature's Grasp Proc
2584  case 27010: // Entangling Roots (Rank 7) -- Nature's Grasp Proc
2585  spellInfo->CastingTimeIndex = 1;
2586  break;
2587  case 19596: // Bestial Swiftness - append additional aura
2589  break;
2590  case 1206: // "REUSE" - we turn it into 30% outdoor movement speed bonus (for Bestial Swiftness)
2591  spellInfo->Effect[0] = SPELL_EFFECT_APPLY_AURA;
2593  spellInfo->EffectBasePoints[0] = 29; // all spells claiming they increase speed by 30% increase it just by 29%
2595  break;
2596  case 31789: // Righteous Defense
2597  spellInfo->EffectTriggerSpell[1] = 31790;
2598  break;
2599  case 47129: // Totemic Beacon
2600  spellInfo->EffectImplicitTargetA[1] = TARGET_NONE;
2601  break;
2602  case 40255: // Molten Flame
2603  // Molten Fire triggers itself, resulting in infinite cycling,
2604  // memory eating and a non-avoidable crash
2605  spellInfo->Effect[1] = 0;
2606  break;
2607  // Explosive Trap - fix initial dmg and proc
2608  case 13812: // rank 1
2609  case 14314: // rank 2
2610  case 14315: // rank 3
2611  case 27026: // rank 4
2613  break;
2614  // Frost Trap & Snake Trap - fix proc
2615  case 13810:
2616  case 45145:
2617  spellInfo->Effect[2] = SPELL_EFFECT_DUMMY;
2619  break;
2620  case 33778: // Lifebloom (rank 1)
2621  case 379: // Earth Shield
2622  case 38395: // Siphon Essence
2623  case 34299: // Improved Leader of the Pack (heal)
2624  case 27813: // Blessed Recovery rank 1
2625  case 27817: // Blessed Recovery rank 2
2626  case 27818: // Blessed Recovery rank 3
2627  case 28880: // Gift of Narru
2629  break;
2630  case 35372: // Protectorate Igniter
2633  break;
2634  case 30298: // Tree Disguise
2636  break;
2637  case 45391: // Vapor Select
2638  spellInfo->AttributesEx3 |= SPELL_ATTR3_CANT_MISS;
2639  spellInfo->MaxAffectedTargets = 1;
2640  break;
2641  case 45399: // Demonic Vapor Trail Periodic
2642  spellInfo->rangeIndex = 2;
2643  break;
2644  case 28730: // Arcane Torrent (mana)
2645  spellInfo->EffectImplicitTargetA[1] = TARGET_UNIT_CASTER;
2646  break;
2647  case 25046: // Arcane Torrent (energy)
2648  spellInfo->Effect[1] = SPELL_EFFECT_DUMMY;
2649  spellInfo->EffectImplicitTargetA[1] = TARGET_UNIT_CASTER;
2650  break;
2651  case 23505: // Berserking
2652  case 23451: // Speed
2653  spellInfo->Attributes |= SPELL_ATTR0_NEGATIVE_1;
2654  break;
2655  default:
2656  break;
2657  }
2658 
2659  switch (spellInfo->SpellFamilyName)
2660  {
2661  case SPELLFAMILY_WARRIOR:
2662  // Shout
2663  if (spellInfo->SpellFamilyFlags & 0x0000000000020000LL)
2665  break;
2666  case SPELLFAMILY_DRUID:
2667  // Roar
2668  if (spellInfo->SpellFamilyFlags & 0x0000000800000000LL)
2670  // Rake
2671  else if (spellInfo->SpellFamilyFlags & 0x1000LL)
2673  break;
2674  }
2675  }
2676 
2677  /* Fix some weird values in SpellItemEnchantment */
2678  for (uint32 i = 0; i <= 3340; i++)
2679  {
2680  if (SpellItemEnchantmentEntry* ench = const_cast<SpellItemEnchantmentEntry*>(sSpellItemEnchantmentStore.LookupEntry(i)))
2681  {
2682  switch (ench->ID)
2683  {
2684  // Flametongue Weapon
2685  case 5:
2686  ench->type[0] = ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL;
2687  ench->spellid[0] = 8026;
2688  break; // rank 1
2689  case 4:
2690  ench->type[0] = ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL;
2691  ench->spellid[0] = 8028;
2692  break; // rank 2
2693  case 3:
2694  ench->type[0] = ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL;
2695  ench->spellid[0] = 8029;
2696  break; // rank 3
2697  case 523:
2698  ench->type[0] = ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL;
2699  ench->spellid[0] = 10445;
2700  break; // rank 4
2701  case 1665:
2702  ench->type[0] = ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL;
2703  ench->spellid[0] = 16343;
2704  break; // rank 5
2705  case 1666:
2706  ench->type[0] = ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL;
2707  ench->spellid[0] = 16344;
2708  break; // rank 6
2709  case 2634:
2710  ench->type[0] = ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL;
2711  ench->spellid[0] = 25488;
2712  break; // rank 7
2713  }
2714  }
2715  }
2716 
2718 }
2719 
2721 {
2722  uint32 count = 0;
2723  SpellEntry* spellInfo;
2724 
2725  // 0 1
2726  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT spellid, cooldown FROM spell_cooldown");
2727  if (!result)
2728  {
2729  sLog.outString(">> Loaded %u custom spell cooldowns", count);
2730  return;
2731  }
2732 
2733  do
2734  {
2735  Field* fields = result->Fetch();
2736 
2737  int32 spellid = fields[0].GetInt32();
2738  uint32 cooldown = fields[1].GetUInt32();
2739 
2740  spellInfo = (SpellEntry*)GetSpellStore()->LookupEntry(spellid);
2741  if (!spellInfo)
2742  {
2743  sLog.outErrorDb("Spell %i listed in spell_cooldown does not exist", spellid);
2744  continue;
2745  }
2746 
2747  if (spellid > 0 && cooldown > 0)
2748  spellInfo->RecoveryTime = cooldown;
2749 
2750  ++count;
2751  }
2752  while (result->NextRow());
2753 
2754  sLog.outString(">> Loaded %u custom spell cooldowns", count);
2755 }
2756 
2758 {
2759  mSpellLinkedMap.clear(); // need for reload case
2760  uint32 count = 0;
2761 
2762  // 0 1 2
2763  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT spell_trigger, spell_effect, type FROM spell_linked_spell");
2764  if (!result)
2765  {
2766  sLog.outString(">> Loaded %u linked spells", count);
2767  return;
2768  }
2769 
2770  do
2771  {
2772  Field* fields = result->Fetch();
2773 
2774  int32 trigger = fields[0].GetInt32();
2775  int32 effect = fields[1].GetInt32();
2776  int32 type = fields[2].GetInt32();
2777 
2778  SpellEntry const* spellInfo = sSpellStore.LookupEntry(abs(trigger));
2779  if (!spellInfo)
2780  {
2781  sLog.outErrorDb("Spell Trigger %i listed in spell_linked_spell does not exist", trigger);
2782  continue;
2783  }
2784  spellInfo = sSpellStore.LookupEntry(abs(effect));
2785  if (!spellInfo)
2786  {
2787  sLog.outErrorDb("Spell Effect %i listed in spell_linked_spell does not exist", effect);
2788  continue;
2789  }
2790 
2791  if (trigger > 0)
2792  {
2793  switch (type)
2794  {
2795  case 0:
2797  break;
2798  case 1:
2800  break;
2801  case 2:
2803  break;
2804  }
2805  }
2806  else
2808 
2809  if (type) //we will find a better way when more types are needed
2810  {
2811  if (trigger > 0)
2812  trigger += SPELL_LINKED_MAX_SPELLS * type;
2813  else
2814  trigger -= SPELL_LINKED_MAX_SPELLS * type;
2815  }
2816  mSpellLinkedMap[trigger].push_back(effect);
2817 
2818  ++count;
2819  }
2820  while (result->NextRow());
2821 
2822  sLog.outString(">> Loaded %u linked spells", count);
2823 }
2824 
2825 // Some checks for spells, to prevent adding depricated/broken spells for trainers, spell book, etc
2826 bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg)
2827 {
2828  // not exist
2829  if (!spellInfo)
2830  return false;
2831 
2832  bool need_check_reagents = false;
2833 
2834  // check effects
2835  for (int i = 0; i < 3; ++i)
2836  {
2837  switch (spellInfo->Effect[i])
2838  {
2839  case 0:
2840  continue;
2841 
2842  // craft spell for crafting non-existed item (break client recipes list show)
2844  {
2845  if (!ObjectMgr::GetItemTemplate(spellInfo->EffectItemType[i]))
2846  {
2847  if (msg)
2848  {
2849  if (pl)
2850  ChatHandler(pl).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...", spellInfo->Id, spellInfo->EffectItemType[i]);
2851  else
2852  sLog.outErrorDb("Craft spell %u create not-exist in DB item (Entry: %u) and then...", spellInfo->Id, spellInfo->EffectItemType[i]);
2853  }
2854  return false;
2855  }
2856 
2857  need_check_reagents = true;
2858  break;
2859  }
2861  {
2862  SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(spellInfo->EffectTriggerSpell[i]);
2863  if (!IsSpellValid(spellInfo2, pl, msg))
2864  {
2865  if (msg)
2866  {
2867  if (pl)
2868  ChatHandler(pl).PSendSysMessage("Spell %u learn to broken spell %u, and then...", spellInfo->Id, spellInfo->EffectTriggerSpell[i]);
2869  else
2870  sLog.outErrorDb("Spell %u learn to invalid spell %u, and then...", spellInfo->Id, spellInfo->EffectTriggerSpell[i]);
2871  }
2872  return false;
2873  }
2874  break;
2875  }
2876  }
2877  }
2878 
2879  if (need_check_reagents)
2880  {
2881  for (int j = 0; j < 8; ++j)
2882  {
2883  if (spellInfo->Reagent[j] > 0 && !ObjectMgr::GetItemTemplate(spellInfo->Reagent[j]))
2884  {
2885  if (msg)
2886  {
2887  if (pl)
2888  ChatHandler(pl).PSendSysMessage("Craft spell %u has invalid reagent in DB item (Entry: %u) and then...", spellInfo->Id, spellInfo->Reagent[j]);
2889  else
2890  sLog.outErrorDb("Craft spell %u has invalid reagent in DB item (Entry: %u) and then...", spellInfo->Id, spellInfo->Reagent[j]);
2891  }
2892  return false;
2893  }
2894  }
2895  }
2896 
2897  return true;
2898 }
2899 
2900 bool IsSpellAllowedInLocation(SpellEntry const* spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id)
2901 {
2902  // normal case
2903  if (spellInfo->AreaId && spellInfo->AreaId != zone_id && spellInfo->AreaId != area_id)
2904  return false;
2905 
2906  // continent limitation (virtual continent)
2908  {
2909  uint32 v_map = GetVirtualMapForMapAndZone(map_id, zone_id);
2910  MapEntry const* mapEntry = sMapStore.LookupEntry(v_map);
2911  if (!mapEntry || mapEntry->addon < 1 || !mapEntry->IsContinent())
2913  }
2914 
2915  // raid instance limitation
2917  {
2918  MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2919  if (!mapEntry || mapEntry->IsRaid())
2921  }
2922 
2923  // special cases zone check (maps checked by multimap common id)
2924  switch (spellInfo->Id)
2925  {
2926  case 23333: // Warsong Flag
2927  case 23335: // Silverwing Flag
2928  case 46392: // Focused Assault
2929  case 46393: // Brutal Assault
2930  {
2931  MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2932  if (!mapEntry)
2933  return false;
2934 
2935  if (!mapEntry->IsBattleground())
2936  return false;
2937 
2938  if (zone_id == 3277)
2939  return true;
2940 
2941  return false;
2942  }
2943  case 34976: // Netherstorm Flag
2944  {
2945  MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2946  if (!mapEntry)
2947  return false;
2948 
2949  if (!mapEntry->IsBattleground())
2950  return false;
2951 
2952  if (zone_id == 3820)
2953  return true;
2954 
2955  return false;
2956  }
2957  case 32724: // Gold Team (Alliance)
2958  case 32725: // Green Team (Alliance)
2959  case 32727: // Arena Preparation
2960  case 35774: // Gold Team (Horde)
2961  case 35775: // Green Team (Horde)
2962  {
2963  MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2964  if (!mapEntry)
2965  return false;
2966 
2967  //the follow code doesn't work.
2968  //if (!mapEntry->IsBattleArena())
2969  // return false;
2970 
2971  //this is the working code, HACK
2972  if (zone_id == 3702 || zone_id == 3968 || zone_id == 3698)
2973  return true;
2974 
2975  return false;
2976  }
2977  case 41618: // Bottled Nethergon Energy
2978  case 41620: // Bottled Nethergon Vapor
2979  {
2980  MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2981  if (!mapEntry)
2982  return false;
2983 
2984  return mapEntry->multimap_id == 206;
2985  }
2986  case 41617: // Cenarion Mana Salve
2987  case 41619: // Cenarion Healing Salve
2988  {
2989  MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2990  if (!mapEntry)
2991  return false;
2992 
2993  return mapEntry->multimap_id == 207;
2994  }
2995  case 40216: // Dragonmaw Illusion
2996  case 42016: // Dragonmaw Illusion
2997  return area_id == 3759 || area_id == 3966 || area_id == 3939;
2998  case 2584: // Waiting to Resurrect
2999  case 22011: // Spirit Heal Channel
3000  case 22012: // Spirit Heal
3001  case 24171: // Resurrection Impact Visual
3002  case 42792: // Recently Dropped Flag
3003  case 43681: // Inactive
3004  case 44535: // Spirit Heal (mana)
3005  case 44521: // Preparation
3006  {
3007  MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
3008  if (!mapEntry)
3009  return false;
3010 
3011  if (!mapEntry->IsBattleground())
3012  return false;
3013  }
3014  }
3015 
3016  return true;
3017 }
3018 
3020 {
3021  mSkillLineAbilityMap.clear();
3022 
3023  uint32 count = 0;
3024 
3025  for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); i++)
3026  {
3027  SkillLineAbilityEntry const* SkillInfo = sSkillLineAbilityStore.LookupEntry(i);
3028  if (!SkillInfo)
3029  continue;
3030 
3031  mSkillLineAbilityMap.insert(SkillLineAbilityMap::value_type(SkillInfo->spellId, SkillInfo));
3032  ++count;
3033  }
3034 
3035  sLog.outString(">> Loaded %u SkillLineAbility MultiMap", count);
3036 }
3037 
3039 {
3040  if (!spellproto || IsPositiveSpell(spellproto->Id))
3041  return DIMINISHING_NONE;
3042 
3043  // Explicit Diminishing Groups
3044  switch (spellproto->SpellFamilyName)
3045  {
3046  // Event + General spells
3047  case SPELLFAMILY_UNK1:
3048  return DIMINISHING_NONE;
3049  case SPELLFAMILY_MAGE:
3050  {
3051  // Item "Magic Dust" shouldn't be limited in PvP and
3052  // does not share DR with other sleep mechanics.
3053  if (spellproto->SpellIconID == 44)
3054  return DIMINISHING_NONE;
3055  break;
3056  // Frost Nova / Freeze (Water Elemental)
3057  if (spellproto->SpellIconID == 193)
3059  break;
3060  }
3061  case SPELLFAMILY_WARRIOR:
3062  {
3063  // Hamstring - limit duration to 10s in PvP
3064  if (spellproto->SpellFamilyFlags & 0x00000000002LL)
3065  return DIMINISHING_LIMITONLY;
3066  break;
3067  }
3068  case SPELLFAMILY_WARLOCK:
3069  {
3070  // Death Coil
3071  if (spellproto->SpellFamilyFlags & 0x00000080000LL)
3072  return DIMINISHING_HORROR;
3073  // Seduction
3074  else if (spellproto->SpellFamilyFlags & 0x00040000000LL)
3075  return DIMINISHING_FEAR;
3076  // Curses/etc
3077  else if (spellproto->SpellFamilyFlags & 0x00080000000LL)
3078  return DIMINISHING_LIMITONLY;
3079  // Unstable affliction dispel silence
3080  else if (spellproto->Id == 31117)
3081  return DIMINISHING_SILENCE;
3082  break;
3083  }
3084  case SPELLFAMILY_DRUID:
3085  {
3086  // Cyclone
3087  if (spellproto->SpellFamilyFlags & 0x02000000000LL)
3089  // Nature's Grasp trigger
3090  if (spellproto->SpellFamilyFlags & 0x00000000200LL && spellproto->Attributes == 0x49010000)
3092  break;
3093  }
3094  case SPELLFAMILY_ROGUE:
3095  {
3096  // Kidney Shot
3097  if (spellproto->SpellFamilyFlags & 0x00000200000LL)
3098  return DIMINISHING_KIDNEYSHOT;
3099  // Gouge
3100  else if (spellproto->SpellFamilyFlags & 0x00000000008LL)
3101  return DIMINISHING_DISORIENT;
3102  // Blind
3103  else if (spellproto->SpellFamilyFlags & 0x00001000000LL)
3105  break;
3106  }
3107  case SPELLFAMILY_HUNTER:
3108  {
3109  // Freezing trap
3110  if (spellproto->SpellFamilyFlags & 0x00000000008LL)
3111  return DIMINISHING_FREEZE;
3112  // Intimidation
3113  else if (spellproto->Id == 24394)
3115  // Entrapment (own diminishing)
3116  else if (spellproto->SpellVisual == 7484 && spellproto->SpellIconID == 20)
3117  return DIMINISHING_ENTRAPMENT;
3118  break;
3119  }
3120  case SPELLFAMILY_PALADIN:
3121  {
3122  // Turn Evil shared diminishing with fear
3123  if (spellproto->Id == 10326)
3124  return DIMINISHING_FEAR;
3125  break;
3126  }
3127  default:
3128  {
3129  if (spellproto->Id == 12494) // frostbite
3130  return DIMINISHING_ROOT;
3131  break;
3132  }
3133  }
3134 
3135  // Lastly - Set diminishing depending on mechanic
3136  uint32 mechanic = spellproto->GetAllEffectsMechanicMask();
3137  if (mechanic & (1 << MECHANIC_CHARM))
3138  return DIMINISHING_MIND_CONTROL;
3139  if (mechanic & (1 << MECHANIC_SLEEP))
3140  return DIMINISHING_SLEEP;
3141  if (mechanic & ((1 << MECHANIC_SAPPED) | (1 << MECHANIC_POLYMORPH) | (1 << MECHANIC_SHACKLE)))
3142  return DIMINISHING_DISORIENT;
3143  if (mechanic & (1 << MECHANIC_KNOCKOUT))
3144  return DIMINISHING_DISORIENT;
3145  if (mechanic & (1 << MECHANIC_DISARM))
3146  return DIMINISHING_DISARM;
3147  if (mechanic & (1 << MECHANIC_FEAR))
3148  return DIMINISHING_FEAR;
3149  if (mechanic & (1 << MECHANIC_STUN))
3150  return triggered ? DIMINISHING_STUN : DIMINISHING_CONTROLLED_STUN;
3151  if (mechanic & (1 << MECHANIC_BANISH))
3152  return DIMINISHING_BANISH;
3153  if (mechanic & (1 << MECHANIC_ROOT))
3154  return triggered ? DIMINISHING_ROOT : DIMINISHING_CONTROLLED_ROOT;
3155  if (mechanic & (1 << MECHANIC_FREEZE))
3156  return DIMINISHING_FREEZE;
3157  if (mechanic & (1 << MECHANIC_HORROR))
3158  return DIMINISHING_HORROR;
3159 
3160  return DIMINISHING_NONE;
3161 }
3162 
3164 {
3165  switch (group)
3166  {
3168  case DIMINISHING_STUN:
3170  case DIMINISHING_SLEEP:
3172  case DIMINISHING_ROOT:
3173  case DIMINISHING_FEAR:
3176  case DIMINISHING_DISORIENT:
3177  case DIMINISHING_FREEZE:
3179  case DIMINISHING_BANISH:
3180  case DIMINISHING_LIMITONLY:
3181  return true;
3182  default:
3183  break;
3184  }
3185  return false;
3186 }
3187 
3189 {
3190  switch (group)
3191  {
3194  case DIMINISHING_STUN:
3196  return DRTYPE_ALL;
3197  case DIMINISHING_SLEEP:
3199  case DIMINISHING_ROOT:
3200  case DIMINISHING_FEAR:
3202  case DIMINISHING_DISORIENT:
3203  case DIMINISHING_DISARM:
3204  case DIMINISHING_HORROR:
3205  case DIMINISHING_FREEZE:
3206  case DIMINISHING_BANISH:
3208  case DIMINISHING_SILENCE:
3209  return DRTYPE_PLAYER;
3210  default:
3211  break;
3212  }
3213 
3214  return DRTYPE_NONE;
3215 }
bool IsProfessionSkill(uint32 skill)
Definition: SpellMgr.h:825
uint32 AuraInterruptFlags
Definition: DBCStructure.h:700
SpellPetAuraMap mSpellPetAuraMap
Definition: SpellMgr.h:1231
uint32 GetLastSpellInChain(uint32 spell_id) const
Definition: SpellMgr.h:1061
void LoadSpellLearnSkills()
Definition: SpellMgr.cpp:2072
uint32 GetCreateMana() const
Definition: Unit.h:1667
uint32 Category
Definition: DBCStructure.h:675
uint32 spellLevel
Definition: DBCStructure.h:707
SpellSchools GetFirstSchoolInMask(SpellSchoolMask mask)
uint32 AttributesEx
Definition: DBCStructure.h:680
DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const *spellproto, bool triggered)
Definition: SpellMgr.cpp:3038
bool IsPrimaryProfessionFirstRankSpell(uint32 spellId) const
Definition: SpellMgr.cpp:1778
DBCStorage< SpellEntry > const * GetSpellStore()
Definition: DBCStores.cpp:776
uint32 CalculatePowerCost(SpellEntry const *spellInfo, Unit const *caster, SpellSchoolMask schoolMask)
Definition: SpellMgr.cpp:303
bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2)
Definition: SpellMgr.cpp:807
#define SPELL_GROUP_STACK_RULE_MAX
Definition: SpellMgr.h:685
uint32 SpellVisual
Definition: SpellMgr.cpp:1860
bool IsRangedSpell() const
Definition: Spell.h:465
uint32 MaxAffectedTargets
Definition: DBCStructure.h:762
uint32 spellFamilyName
Definition: SpellMgr.h:639
SpellProcEventMap mSpellProcEventMap
Definition: SpellMgr.h:1229
uint32 EffectTriggerSpell[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:741
uint32 GetPrevSpellInChain(uint32 spell_id) const
Definition: SpellMgr.h:1037
static bool canStackSpellRanks(SpellEntry const *spellInfo)
Definition: SpellMgr.cpp:1518
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
Definition: DBCStores.cpp:652
bool IsSingleTargetSpell(SpellEntry const *spellInfo)
Definition: SpellMgr.cpp:783
static void ClearAISpellInfo()
Definition: UnitAI.cpp:325
DatabaseType WorldDatabase
Accessor to the world database.
Definition: Main.cpp:53
bool IsPassiveSpell(uint32 spellId)
Definition: SpellMgr.cpp:278
char const * SpellName
Definition: SpellMgr.cpp:1857
bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group)
Definition: SpellMgr.cpp:3163
uint32 RangeIndex
Definition: SpellMgr.cpp:1859
SpellSchoolMask
uint32 SpellVisual
Definition: DBCStructure.h:743
DBCStorage< SpellCastTimesEntry > sSpellCastTimesStore(SpellCastTimefmt)
bool IsControlledByPlayer() const
Definition: Unit.h:1492
uint32 Stances
Definition: DBCStructure.h:686
Unit * GetCaster() const
Definition: Spell.h:509
static bool IsPrimaryProfessionSpell(uint32 spellId)
Definition: SpellMgr.cpp:1764
void LoadSpellProcEvents()
Definition: SpellMgr.cpp:1090
SpellGroupSpellMapBounds GetSpellGroupSpellMapBounds(SpellGroup group_id) const
Definition: SpellMgr.cpp:1673
QueryResult_AutoPtr PQuery(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:400
SpellSpellGroupMap mSpellSpellGroup
Definition: SpellMgr.h:1227
SpellSchools
SpellSpecific
Definition: SpellMgr.h:95
Definition: Field.h:24
SpellRequiredMap mSpellReq
Definition: SpellMgr.h:1221
void LoadSpellPetAuras()
Definition: SpellMgr.cpp:2194
void LoadSpellTargetPositions()
Definition: SpellMgr.cpp:887
SpellEnchantProcEventMap mSpellEnchantProcEventMap
Definition: SpellMgr.h:1235
bool IsAreaEffectTarget[TOTAL_SPELL_TARGETS]
Definition: SpellMgr.cpp:28
DBCStorage< GtNPCManaCostScalerEntry > sGtNPCManaCostScalerStore(GtNPCManaCostScalerfmt)
int32 EffectBaseDice[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:726
bool IsContinent() const
Definition: DBCStructure.h:583
uint32 AttributesEx2
Definition: DBCStructure.h:681
uint32 InterruptFlags
Definition: DBCStructure.h:699
DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group)
Definition: SpellMgr.cpp:3188
bool IsAutoRepeat() const
Definition: Spell.h:449
#define sLog
Log class singleton.
Definition: Log.h:187
DiminishingGroup
SpellSelectTargetTypes SpellTargetType[TOTAL_SPELL_TARGETS]
Definition: SpellMgr.h:1181
SpellLearnSpellMap::const_iterator GetBeginSpellLearnSpell(uint32 spell_id) const
Definition: SpellMgr.h:1104
std::pair< SpellGroupSpellMap::const_iterator, SpellGroupSpellMap::const_iterator > SpellGroupSpellMapBounds
Definition: SpellMgr.h:676
int32 GetSpellMaxDuration(SpellEntry const *spellInfo)
Definition: SpellMgr.cpp:238
SpellGroupStackRule CheckSpellGroupStackRules(uint32 spellInfo1, uint32 spellInfo2) const
Definition: SpellMgr.cpp:1705
void LoadSpellRequired()
Definition: SpellMgr.cpp:1823
ACE_INT32 int32
Definition: Define.h:67
QueryResult_AutoPtr Query(const char *sql)
Definition: Database.cpp:383
uint32 powerType
Definition: DBCStructure.h:709
void LoadSpellCustomCooldowns()
Definition: SpellMgr.cpp:2720
SkillLineAbilityMap mSkillLineAbilityMap
Definition: SpellMgr.h:1230
SpellTargetPositionMap mSpellTargetPositions
Definition: SpellMgr.h:1224
uint32 GetSpellCastTime(SpellEntry const *spellInfo, Spell const *spell)
Definition: SpellMgr.cpp:248
uint32 addon
Definition: DBCStructure.h:542
uint32 Effect[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:724
void LoadSpellEnchantProcData()
Definition: SpellMgr.cpp:1428
static SpellMgr & Instance()
Definition: SpellMgr.cpp:222
int32 EffectBasePoints[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:729
#define MAX_POWERS
static ItemTemplate const * GetItemTemplate(uint32 id)
Definition: ObjectMgr.h:633
char * Rank[16]
Definition: DBCStructure.h:750
void LoadSpellLinked()
Definition: SpellMgr.cpp:2757
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
DBCStorage< SpellEntry > sSpellStore(SpellEntryfmt)
uint32 EffectApplyAuraName[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:734
uint32 rangeIndex
Definition: DBCStructure.h:714
void LoadSpellLearnSpells()
Definition: SpellMgr.cpp:2107
uint32 procFlags
Definition: DBCStructure.h:702
uint32 GetPower(Powers power) const
Definition: Unit.h:1076
uint32 multimap_id
Definition: DBCStructure.h:528
Spell is Pickpocket.
Definition: SpellMgr.h:851
uint32 GetAttackTime(WeaponAttackType att) const
Definition: Unit.h:1090
SpellSchoolMask GetSpellSchoolMask(SpellEntry const *spellInfo)
Definition: SpellMgr.h:481
uint32 CastingTimeIndex
Definition: DBCStructure.h:696
must ignore armor
Definition: SpellMgr.h:847
uint32 Attributes
Definition: DBCStructure.h:679
DBCStorage< TalentEntry > sTalentStore(TalentEntryfmt)
SpellGroup
Definition: SpellMgr.h:659
bool HasAttribute(SpellAttributes attribute) const
Definition: DBCStructure.h:774
bool IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2, bool sameCaster) const
Definition: SpellMgr.cpp:1564
uint32 Dispel
Definition: DBCStructure.h:677
char * SpellName[16]
Definition: DBCStructure.h:748
ACE_UINT8 uint8
Definition: Define.h:73
Powers
uint32 GetMaxPower(Powers power) const
Definition: Unit.h:1080
bool IsPrimaryProfessionSkill(uint32 skill)
Definition: SpellMgr.h:813
std::pair< SpellSpellGroupMap::const_iterator, SpellSpellGroupMap::const_iterator > SpellSpellGroupMapBounds
Definition: SpellMgr.h:672
uint32 AttributesEx3
Definition: DBCStructure.h:682
void LoadSpellChains()
Definition: SpellMgr.cpp:1887
uint32 TargetAuraState
Definition: SpellMgr.cpp:1863
#define TOTAL_SPELL_TARGETS
uint32 AttributesEx4
Definition: DBCStructure.h:683
bool IsBattleground() const
Definition: DBCStructure.h:562
void PSendSysMessage(const char *format,...) ATTR_PRINTF(2
Definition: Chat.cpp:855
bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
Definition: SpellMgr.cpp:561
SpellDummyConditionMap mSpellDummyConditionMap
Definition: SpellMgr.h:1236
uint32 StancesNot
Definition: DBCStructure.h:687
uint8 GetSpellRank(uint32 spell_id) const
Definition: SpellMgr.h:1053
SpellEffIndex effIndex
Definition: SpellMgr.h:911
bool IsAffectedBySpell(SpellEntry const *spellInfo, uint32 spellId, uint8 effectId, uint64 familyFlags) const
Definition: SpellMgr.cpp:1058
void LoadSpellGroupStackRules()
Definition: SpellMgr.cpp:1345
TalentSpellPos const * GetTalentSpellPos(uint32 spellId)
Definition: DBCStores.cpp:589
uint32 GetFirstSpellInChain(uint32 spell_id) const
Definition: SpellMgr.h:1020
char const * Rank
Definition: SpellMgr.cpp:1884
uint32 Targets
Definition: DBCStructure.h:688
uint64 spellFamilyMask
Definition: SpellMgr.h:640
char * ToolTip[16]
Definition: DBCStructure.h:754
uint32 EffectImplicitTargetB[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:732
uint32 ProcFlags
Definition: SpellMgr.cpp:1861
SpellEffIndex
Definition: SharedDefines.h:24
etc mysql my cnf *Then change max_allowed_packet to a bigger value
SpellCustomAttribute mSpellCustomAttr
Definition: SpellMgr.h:1232
bool IsRankSpellDueToSpell(SpellEntry const *spellInfo_1, uint32 spellId_2) const
Definition: SpellMgr.cpp:1503
uint64 SpellFamilyFlags
Definition: DBCStructure.h:761
SpellLinkedMap mSpellLinkedMap
Definition: SpellMgr.h:1233
float m_modAttackSpeedPct[3]
Definition: Unit.h:1741
uint32 SpellIconID
Definition: DBCStructure.h:745
uint32 EffectImplicitTargetA[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:731
DBCStorage< SpellItemEnchantmentEntry > sSpellItemEnchantmentStore(SpellItemEnchantmentfmt)
void GetSetOfSpellsInSpellGroup(SpellGroup group_id, std::set< uint32 > &foundSpells) const
Definition: SpellMgr.cpp:1678
uint32 EffectItemType[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:738
SpellAffectMap mSpellAffectMap
Definition: SpellMgr.h:1226
SpellCastResult GetErrorAtShapeshiftedCast(SpellEntry const *spellInfo, uint32 form)
Definition: SpellMgr.cpp:842
DiminishingReturnsType
void LoadSpellAffects()
Definition: SpellMgr.cpp:964
bool IsAutocastableSpell(uint32 spellId)
Definition: SpellMgr.cpp:291
int32 Reagent[8]
Definition: DBCStructure.h:719
uint32 SchoolMask
Definition: DBCStructure.h:772
SpellLearnSpellMap mSpellLearnSpells
Definition: SpellMgr.h:1223
SpellLearnSkillMap mSpellLearnSkills
Definition: SpellMgr.h:1222
SpellLearnSpellMap::const_iterator GetEndSpellLearnSpell(uint32 spell_id) const
Definition: SpellMgr.h:1109
static void FillAISpellInfo()
Definition: UnitAI.cpp:272
int32 EffectMiscValue[MAX_SPELL_EFFECTS]
Definition: DBCStructure.h:739
bool IsSpellMemberOfSpellGroup(uint32 spellid, SpellGroup groupid) const
Definition: SpellMgr.cpp:1662
static bool IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const *spellProcEvent, uint32 EventProcFlag, SpellEntry const *procSpell, uint32 procFlags, uint32 procExtra, bool active)
Definition: SpellMgr.cpp:1151
SpellGroupStackRule
Definition: SpellMgr.h:678
int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
Definition: SpellMgr.cpp:384
bool IsRaid() const
Definition: DBCStructure.h:558
bool IsPositiveSpell(uint32 spellId)
Definition: SpellMgr.cpp:773
uint64 GetSpellAffectMask(uint16 spellId, uint8 effectId) const
Definition: SpellMgr.h:934
bool IsSealSpell(SpellEntry const *spellInfo)
Definition: SpellMgr.h:215
SpellGroupStackMap mSpellGroupStack
Definition: SpellMgr.h:1234
SpellDummyCondition
Definition: SpellMgr.h:888
uint32 DurationIndex
Definition: DBCStructure.h:708
approves cast on any target, even when its non-attackable
Definition: SpellMgr.h:850
void LoadSkillLineAbilityMap()
Definition: SpellMgr.cpp:3019
uint32 TargetAuraState
Definition: DBCStructure.h:693
SpellGroupSpellMap mSpellGroupSpell
Definition: SpellMgr.h:1228
void LoadSpellThreats()
Definition: SpellMgr.cpp:1388
bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId)
Definition: SpellMgr.cpp:831
ACE_UINT64 uint64
Definition: Define.h:70
bool IsSpellAllowedInLocation(SpellEntry const *spellInfo, uint32 map_id, uint32 zone_id, uint32 area_id)
Definition: SpellMgr.cpp:2900
DBCStorage< SpellDurationEntry > sSpellDurationStore(SpellDurationfmt)
float target_Orientation
Definition: SpellMgr.h:722
uint32 GetAllEffectsMechanicMask() const
Definition: DBCStructure.h:807
SpellThreatMap mSpellThreatMap
Definition: SpellMgr.h:1225
uint32 RankID[5]
Definition: DBCStructure.h:934
SpellsRequiringSpellMap mSpellsReqSpell
Definition: SpellMgr.h:1220
void LoadSpellGroups()
Definition: SpellMgr.cpp:1264
uint32 RecoveryTime
Definition: DBCStructure.h:697
Player * GetSpellModOwner() const
Definition: Unit.cpp:11748
bool IsElementalShield(SpellEntry const *spellInfo)
Definition: SpellMgr.h:223
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
uint32 AreaId
Definition: DBCStructure.h:771
ignore bonus healing/damage
Definition: SpellMgr.h:849
uint32 SpellFamilyName
Definition: DBCStructure.h:760
struct SpellDummyConditionEntry::@256 conditions[5]
uint32 DurationIndex
Definition: SpellMgr.cpp:1858
SpellEntry const * SelectAuraRankForPlayerLevel(SpellEntry const *spellInfo, uint32 playerLevel) const
Definition: SpellMgr.cpp:1783
uint32 GetCreateHealth() const
Definition: Unit.h:1659
static bool IsProfessionSpell(uint32 spellId)
Definition: SpellMgr.cpp:1750
#define SPEED_CHARGE
Definition: MotionMaster.h:80
bool IsPositionTarget(uint32 target)
Definition: SpellMgr.h:944
uint32 Mechanic
Definition: DBCStructure.h:678
bool operator()(const SpellRankEntry &_Left, const SpellRankEntry &_Right) const
Definition: SpellMgr.cpp:1866
SpellChainMap mSpellChains
Definition: SpellMgr.h:1219
uint32 GetTalentSpellCost(uint32 spellId)
Definition: DBCStores.cpp:598
#define MAX_SPELL_EFFECTS
Definition: DBCStructure.h:670
void LoadSpellCustomAttr()
Definition: SpellMgr.cpp:2260
SpellCastResult
const int32 & GetInt32Value(uint16 index) const
Definition: Object.h:222
related to movement impiaring effects
Definition: SpellMgr.h:846
uint32 StartRecoveryTime
Definition: DBCStructure.h:758
#define sWorld
Definition: World.h:860
SpellSpellGroupMapBounds GetSpellSpellGroupMapBounds(uint32 spell_id) const
Definition: SpellMgr.cpp:1656
uint32 ManaCostPercentage
Definition: DBCStructure.h:756
ACE_UINT16 uint16
Definition: Define.h:72
bool IsPositiveTarget(uint32 targetA, uint32 targetB)
Definition: SpellMgr.cpp:539
ACE_UINT32 uint32
Definition: Define.h:71
uint32 activeIconID
Definition: DBCStructure.h:746
must be cast from item, never directly
Definition: SpellMgr.h:848
SpellEffectTargetTypes EffectTargetType[TOTAL_SPELL_EFFECTS]
Definition: SpellMgr.h:1180
uint32 GetHealth() const
Definition: Unit.h:1051
uint32 AttributesEx5
Definition: DBCStructure.h:684
void LoadSpellDummyCondition()
Definition: SpellMgr.cpp:1470
Definition: Unit.h:884
uint32 getLevel() const
Definition: Unit.h:1029
#define SPELL_LINKED_MAX_SPELLS
Definition: SpellMgr.h:117
Definition: Player.h:922
static bool IsSpellValid(SpellEntry const *spellInfo, Player *pl=NULL, bool msg=true)
Definition: SpellMgr.cpp:2826
DBCStorage< SpellShapeshiftEntry > sSpellShapeshiftStore(SpellShapeshiftfmt)
uint64 SpellFamilyFlags
Definition: SpellMgr.cpp:1862
int32 GetSpellDuration(SpellEntry const *spellInfo)
Definition: SpellMgr.cpp:228
SpellDummyCondition condition
Definition: SpellMgr.h:916
uint32 manaCost
Definition: DBCStructure.h:710
SpellMgr()
Definition: SpellMgr.cpp:30
DBCStorage< SkillLineAbilityEntry > sSkillLineAbilityStore(SkillLineAbilityfmt)
SpellSpecific GetSpellSpecific(uint32 spellId)
Definition: SpellMgr.cpp:396
uint32 StartRecoveryCategory
Definition: DBCStructure.h:757
const float & GetFloatValue(uint16 index) const
Definition: Object.h:240
Definition: Spell.h:249