Fixed typo in SpellMgr::GetSpellAllowedInLocationError. This should fix problems...
[getmangos.git] / src / game / SpellMgr.cpp
blob06fe60522df9b2b26ba247a68b0c6b9c83653414
1 /*
2 * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #include "SpellMgr.h"
20 #include "ObjectMgr.h"
21 #include "SpellAuraDefines.h"
22 #include "ProgressBar.h"
23 #include "Database/DBCStores.h"
24 #include "World.h"
25 #include "Chat.h"
26 #include "Spell.h"
28 SpellMgr::SpellMgr()
32 SpellMgr::~SpellMgr()
36 SpellMgr& SpellMgr::Instance()
38 static SpellMgr spellMgr;
39 return spellMgr;
42 int32 GetSpellDuration(SpellEntry const *spellInfo)
44 if(!spellInfo)
45 return 0;
46 SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex);
47 if(!du)
48 return 0;
49 return (du->Duration[0] == -1) ? -1 : abs(du->Duration[0]);
52 int32 GetSpellMaxDuration(SpellEntry const *spellInfo)
54 if(!spellInfo)
55 return 0;
56 SpellDurationEntry const *du = sSpellDurationStore.LookupEntry(spellInfo->DurationIndex);
57 if(!du)
58 return 0;
59 return (du->Duration[2] == -1) ? -1 : abs(du->Duration[2]);
62 uint32 GetSpellCastTime(SpellEntry const* spellInfo, Spell const* spell)
64 SpellCastTimesEntry const *spellCastTimeEntry = sSpellCastTimesStore.LookupEntry(spellInfo->CastingTimeIndex);
66 // not all spells have cast time index and this is all is pasiive abilities
67 if(!spellCastTimeEntry)
68 return 0;
70 int32 castTime = spellCastTimeEntry->CastTime;
72 if (spell)
74 if(Player* modOwner = spell->GetCaster()->GetSpellModOwner())
75 modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_CASTING_TIME, castTime, spell);
77 if( !(spellInfo->Attributes & (SPELL_ATTR_UNK4|SPELL_ATTR_UNK5)) )
78 castTime = int32(castTime * spell->GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED));
79 else
81 if (spell->IsRangedSpell() && !spell->IsAutoRepeat())
82 castTime = int32(castTime * spell->GetCaster()->m_modAttackSpeedPct[RANGED_ATTACK]);
86 if (spellInfo->Attributes & SPELL_ATTR_RANGED && (!spell || !(spell->IsAutoRepeat())))
87 castTime += 500;
89 return (castTime > 0) ? uint32(castTime) : 0;
92 bool IsPassiveSpell(uint32 spellId)
94 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
95 if (!spellInfo)
96 return false;
97 return (spellInfo->Attributes & SPELL_ATTR_PASSIVE) != 0;
100 bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
102 SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
103 SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
104 if(!spellInfo_1 || !spellInfo_2) return false;
105 if(spellInfo_1->Id == spellId_2) return false;
107 if (spellInfo_1->Effect[effIndex_1] != spellInfo_2->Effect[effIndex_2] ||
108 spellInfo_1->EffectItemType[effIndex_1] != spellInfo_2->EffectItemType[effIndex_2] ||
109 spellInfo_1->EffectMiscValue[effIndex_1] != spellInfo_2->EffectMiscValue[effIndex_2] ||
110 spellInfo_1->EffectApplyAuraName[effIndex_1] != spellInfo_2->EffectApplyAuraName[effIndex_2])
111 return false;
113 return true;
116 int32 CompareAuraRanks(uint32 spellId_1, uint32 effIndex_1, uint32 spellId_2, uint32 effIndex_2)
118 SpellEntry const*spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
119 SpellEntry const*spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
120 if(!spellInfo_1 || !spellInfo_2) return 0;
121 if (spellId_1 == spellId_2) return 0;
123 int32 diff = spellInfo_1->EffectBasePoints[effIndex_1] - spellInfo_2->EffectBasePoints[effIndex_2];
124 if (spellInfo_1->EffectBasePoints[effIndex_1]+1 < 0 && spellInfo_2->EffectBasePoints[effIndex_2]+1 < 0) return -diff;
125 else return diff;
128 SpellSpecific GetSpellSpecific(uint32 spellId)
130 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
131 if(!spellInfo)
132 return SPELL_NORMAL;
134 switch(spellInfo->SpellFamilyName)
136 case SPELLFAMILY_MAGE:
138 // family flags 18(Molten), 25(Frost/Ice), 28(Mage)
139 if (spellInfo->SpellFamilyFlags & 0x12040000)
140 return SPELL_MAGE_ARMOR;
142 if ((spellInfo->SpellFamilyFlags & 0x1000000) && spellInfo->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE)
143 return SPELL_MAGE_POLYMORPH;
145 break;
147 case SPELLFAMILY_WARRIOR:
149 if (spellInfo->SpellFamilyFlags & 0x00008000010000LL)
150 return SPELL_POSITIVE_SHOUT;
152 break;
154 case SPELLFAMILY_WARLOCK:
156 // only warlock curses have this
157 if (spellInfo->Dispel == DISPEL_CURSE)
158 return SPELL_CURSE;
160 // family flag 37 (only part spells have family name)
161 if (spellInfo->SpellFamilyFlags & 0x2000000000LL)
162 return SPELL_WARLOCK_ARMOR;
164 break;
166 case SPELLFAMILY_HUNTER:
168 // only hunter stings have this
169 if (spellInfo->Dispel == DISPEL_POISON)
170 return SPELL_STING;
172 break;
174 case SPELLFAMILY_PALADIN:
176 if (IsSealSpell(spellInfo))
177 return SPELL_SEAL;
179 if (spellInfo->SpellFamilyFlags & 0x0000000011010002LL)
180 return SPELL_BLESSING;
182 if ((spellInfo->SpellFamilyFlags & 0x00000820180400LL) && (spellInfo->AttributesEx3 & 0x200))
183 return SPELL_JUDGEMENT;
185 for (int i = 0; i < 3; i++)
187 // only paladin auras have this (for palaldin class family)
188 if (spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID)
189 return SPELL_AURA;
191 break;
193 case SPELLFAMILY_SHAMAN:
195 if (IsElementalShield(spellInfo))
196 return SPELL_ELEMENTAL_SHIELD;
198 break;
201 case SPELLFAMILY_POTION:
202 return spellmgr.GetSpellElixirSpecific(spellInfo->Id);
204 case SPELLFAMILY_DEATHKNIGHT:
205 if ((spellInfo->Attributes & 0x10) && (spellInfo->AttributesEx2 & 0x10) && (spellInfo->AttributesEx4 & 0x200000))
206 return SPELL_PRESENCE;
207 break;
210 // only warlock armor/skin have this (in additional to family cases)
211 if( spellInfo->SpellVisual[0] == 130 && spellInfo->SpellIconID == 89)
213 return SPELL_WARLOCK_ARMOR;
216 // only hunter aspects have this (but not all aspects in hunter family)
217 if( spellInfo->activeIconID == 122 && (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_NATURE) &&
218 (spellInfo->Attributes & 0x50000) != 0 && (spellInfo->Attributes & 0x9000010) == 0)
220 return SPELL_ASPECT;
223 for(int i = 0; i < 3; i++)
224 if( spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA && (
225 spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_CREATURES ||
226 spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_RESOURCES ||
227 spellInfo->EffectApplyAuraName[i] == SPELL_AURA_TRACK_STEALTHED ) )
228 return SPELL_TRACKER;
230 // elixirs can have different families, but potion most ofc.
231 if(SpellSpecific sp = spellmgr.GetSpellElixirSpecific(spellInfo->Id))
232 return sp;
234 return SPELL_NORMAL;
237 bool IsSingleFromSpellSpecificPerCaster(uint32 spellSpec1,uint32 spellSpec2)
239 switch(spellSpec1)
241 case SPELL_SEAL:
242 case SPELL_BLESSING:
243 case SPELL_AURA:
244 case SPELL_STING:
245 case SPELL_CURSE:
246 case SPELL_ASPECT:
247 case SPELL_TRACKER:
248 case SPELL_WARLOCK_ARMOR:
249 case SPELL_MAGE_ARMOR:
250 case SPELL_MAGE_POLYMORPH:
251 case SPELL_POSITIVE_SHOUT:
252 case SPELL_JUDGEMENT:
253 case SPELL_PRESENCE:
254 return spellSpec1==spellSpec2;
255 case SPELL_BATTLE_ELIXIR:
256 return spellSpec2==SPELL_BATTLE_ELIXIR
257 || spellSpec2==SPELL_FLASK_ELIXIR;
258 case SPELL_GUARDIAN_ELIXIR:
259 return spellSpec2==SPELL_GUARDIAN_ELIXIR
260 || spellSpec2==SPELL_FLASK_ELIXIR;
261 case SPELL_FLASK_ELIXIR:
262 return spellSpec2==SPELL_BATTLE_ELIXIR
263 || spellSpec2==SPELL_GUARDIAN_ELIXIR
264 || spellSpec2==SPELL_FLASK_ELIXIR;
265 default:
266 return false;
270 bool IsPositiveTarget(uint32 targetA, uint32 targetB)
272 // non-positive targets
273 switch(targetA)
275 case TARGET_CHAIN_DAMAGE:
276 case TARGET_ALL_ENEMY_IN_AREA:
277 case TARGET_ALL_ENEMY_IN_AREA_INSTANT:
278 case TARGET_IN_FRONT_OF_CASTER:
279 case TARGET_ALL_ENEMY_IN_AREA_CHANNELED:
280 case TARGET_CURRENT_ENEMY_COORDINATES:
281 case TARGET_SINGLE_ENEMY:
282 return false;
283 case TARGET_ALL_AROUND_CASTER:
284 return (targetB == TARGET_ALL_PARTY || targetB == TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER);
285 default:
286 break;
288 if (targetB)
289 return IsPositiveTarget(targetB, 0);
290 return true;
293 bool IsPositiveEffect(uint32 spellId, uint32 effIndex)
295 SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId);
296 if (!spellproto) return false;
298 switch(spellId)
300 case 23333: // BG spell
301 case 23335: // BG spell
302 case 34976: // BG spell
303 return true;
304 case 28441: // not positive dummy spell
305 case 37675: // Chaos Blast
306 return false;
309 switch(spellproto->Effect[effIndex])
311 // always positive effects (check before target checks that provided non-positive result in some case for positive effects)
312 case SPELL_EFFECT_HEAL:
313 case SPELL_EFFECT_LEARN_SPELL:
314 case SPELL_EFFECT_SKILL_STEP:
315 case SPELL_EFFECT_HEAL_PCT:
316 case SPELL_EFFECT_ENERGIZE_PCT:
317 return true;
319 // non-positive aura use
320 case SPELL_EFFECT_APPLY_AURA:
321 case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
323 switch(spellproto->EffectApplyAuraName[effIndex])
325 case SPELL_AURA_DUMMY:
327 // dummy aura can be positive or negative dependent from casted spell
328 switch(spellproto->Id)
330 case 13139: // net-o-matic special effect
331 case 23445: // evil twin
332 case 38637: // Nether Exhaustion (red)
333 case 38638: // Nether Exhaustion (green)
334 case 38639: // Nether Exhaustion (blue)
335 return false;
336 default:
337 break;
339 } break;
340 case SPELL_AURA_MOD_STAT:
341 case SPELL_AURA_MOD_DAMAGE_DONE: // dependent from bas point sign (negative -> negative)
342 case SPELL_AURA_MOD_HEALING_DONE:
344 if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) < 0)
345 return false;
346 break;
348 case SPELL_AURA_ADD_TARGET_TRIGGER:
349 return true;
350 case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
351 if(spellId != spellproto->EffectTriggerSpell[effIndex])
353 uint32 spellTriggeredId = spellproto->EffectTriggerSpell[effIndex];
354 SpellEntry const *spellTriggeredProto = sSpellStore.LookupEntry(spellTriggeredId);
356 if(spellTriggeredProto)
358 // non-positive targets of main spell return early
359 for(int i = 0; i < 3; ++i)
361 // if non-positive trigger cast targeted to positive target this main cast is non-positive
362 // this will place this spell auras as debuffs
363 if(IsPositiveTarget(spellTriggeredProto->EffectImplicitTargetA[effIndex],spellTriggeredProto->EffectImplicitTargetB[effIndex]) && !IsPositiveEffect(spellTriggeredId,i))
364 return false;
368 break;
369 case SPELL_AURA_PROC_TRIGGER_SPELL:
370 // many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example)
371 break;
372 case SPELL_AURA_MOD_STUN: //have positive and negative spells, we can't sort its correctly at this moment.
373 if(effIndex==0 && spellproto->Effect[1]==0 && spellproto->Effect[2]==0)
374 return false; // but all single stun aura spells is negative
376 // Petrification
377 if(spellproto->Id == 17624)
378 return false;
379 break;
380 case SPELL_AURA_MOD_ROOT:
381 case SPELL_AURA_MOD_SILENCE:
382 case SPELL_AURA_GHOST:
383 case SPELL_AURA_PERIODIC_LEECH:
384 case SPELL_AURA_MOD_PACIFY_SILENCE:
385 case SPELL_AURA_MOD_STALKED:
386 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT:
387 return false;
388 case SPELL_AURA_PERIODIC_DAMAGE: // used in positive spells also.
389 // part of negative spell if casted at self (prevent cancel)
390 if(spellproto->EffectImplicitTargetA[effIndex] == TARGET_SELF)
391 return false;
392 break;
393 case SPELL_AURA_MOD_DECREASE_SPEED: // used in positive spells also
394 // part of positive spell if casted at self
395 if(spellproto->EffectImplicitTargetA[effIndex] != TARGET_SELF)
396 return false;
397 // but not this if this first effect (don't found batter check)
398 if(spellproto->Attributes & 0x4000000 && effIndex==0)
399 return false;
400 break;
401 case SPELL_AURA_TRANSFORM:
402 // some spells negative
403 switch(spellproto->Id)
405 case 36897: // Transporter Malfunction (race mutation to horde)
406 case 36899: // Transporter Malfunction (race mutation to alliance)
407 return false;
409 break;
410 case SPELL_AURA_MOD_SCALE:
411 // some spells negative
412 switch(spellproto->Id)
414 case 36900: // Soul Split: Evil!
415 case 36901: // Soul Split: Good
416 case 36893: // Transporter Malfunction (decrease size case)
417 case 36895: // Transporter Malfunction (increase size case)
418 return false;
420 break;
421 case SPELL_AURA_MECHANIC_IMMUNITY:
423 // non-positive immunities
424 switch(spellproto->EffectMiscValue[effIndex])
426 case MECHANIC_BANDAGE:
427 case MECHANIC_SHIELD:
428 case MECHANIC_MOUNT:
429 case MECHANIC_INVULNERABILITY:
430 return false;
431 default:
432 break;
434 } break;
435 case SPELL_AURA_ADD_FLAT_MODIFIER: // mods
436 case SPELL_AURA_ADD_PCT_MODIFIER:
438 // non-positive mods
439 switch(spellproto->EffectMiscValue[effIndex])
441 case SPELLMOD_COST: // dependent from bas point sign (negative -> positive)
442 if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) > 0)
443 return false;
444 break;
445 default:
446 break;
448 } break;
449 case SPELL_AURA_MOD_HEALING_PCT:
450 if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) < 0)
451 return false;
452 break;
453 case SPELL_AURA_MOD_SKILL:
454 if(spellproto->EffectBasePoints[effIndex]+int32(spellproto->EffectBaseDice[effIndex]) < 0)
455 return false;
456 break;
457 case SPELL_AURA_FORCE_REACTION:
458 if(spellproto->Id==42792) // Recently Dropped Flag (prevent cancel)
459 return false;
460 break;
461 default:
462 break;
464 break;
466 default:
467 break;
470 // non-positive targets
471 if(!IsPositiveTarget(spellproto->EffectImplicitTargetA[effIndex],spellproto->EffectImplicitTargetB[effIndex]))
472 return false;
474 // AttributesEx check
475 if(spellproto->AttributesEx & (1<<7))
476 return false;
478 // ok, positive
479 return true;
482 bool IsPositiveSpell(uint32 spellId)
484 SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId);
485 if (!spellproto) return false;
487 // spells with atleast one negative effect are considered negative
488 // some self-applied spells have negative effects but in self casting case negative check ignored.
489 for (int i = 0; i < 3; i++)
490 if (!IsPositiveEffect(spellId, i))
491 return false;
492 return true;
495 bool IsSingleTargetSpell(SpellEntry const *spellInfo)
497 // all other single target spells have if it has AttributesEx5
498 if ( spellInfo->AttributesEx5 & SPELL_ATTR_EX5_SINGLE_TARGET_SPELL )
499 return true;
501 // TODO - need found Judgements rule
502 switch(GetSpellSpecific(spellInfo->Id))
504 case SPELL_JUDGEMENT:
505 return true;
508 // single target triggered spell.
509 // Not real client side single target spell, but it' not triggered until prev. aura expired.
510 // This is allow store it in single target spells list for caster for spell proc checking
511 if(spellInfo->Id==38324) // Regeneration (triggered by 38299 (HoTs on Heals))
512 return true;
514 return false;
517 bool IsSingleTargetSpells(SpellEntry const *spellInfo1, SpellEntry const *spellInfo2)
519 // TODO - need better check
520 // Equal icon and spellfamily
521 if( spellInfo1->SpellFamilyName == spellInfo2->SpellFamilyName &&
522 spellInfo1->SpellIconID == spellInfo2->SpellIconID )
523 return true;
525 // TODO - need found Judgements rule
526 SpellSpecific spec1 = GetSpellSpecific(spellInfo1->Id);
527 // spell with single target specific types
528 switch(spec1)
530 case SPELL_JUDGEMENT:
531 if(GetSpellSpecific(spellInfo2->Id) == spec1)
532 return true;
533 break;
536 return false;
539 bool IsAuraAddedBySpell(uint32 auraType, uint32 spellId)
541 SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId);
542 if (!spellproto) return false;
544 for (int i = 0; i < 3; i++)
545 if (spellproto->EffectApplyAuraName[i] == auraType)
546 return true;
547 return false;
550 uint8 GetErrorAtShapeshiftedCast (SpellEntry const *spellInfo, uint32 form)
552 // talents that learn spells can have stance requirements that need ignore
553 // (this requirement only for client-side stance show in talent description)
554 if( GetTalentSpellCost(spellInfo->Id) > 0 &&
555 (spellInfo->Effect[0]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[1]==SPELL_EFFECT_LEARN_SPELL || spellInfo->Effect[2]==SPELL_EFFECT_LEARN_SPELL) )
556 return 0;
558 uint32 stanceMask = (form ? 1 << (form - 1) : 0);
560 if (stanceMask & spellInfo->StancesNot) // can explicitly not be casted in this stance
561 return SPELL_FAILED_NOT_SHAPESHIFT;
563 if (stanceMask & spellInfo->Stances) // can explicitly be casted in this stance
564 return 0;
566 bool actAsShifted = false;
567 if (form > 0)
569 SpellShapeshiftEntry const *shapeInfo = sSpellShapeshiftStore.LookupEntry(form);
570 if (!shapeInfo)
572 sLog.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form);
573 return 0;
575 actAsShifted = !(shapeInfo->flags1 & 1); // shapeshift acts as normal form for spells
578 if(actAsShifted)
580 if (spellInfo->Attributes & SPELL_ATTR_NOT_SHAPESHIFT) // not while shapeshifted
581 return SPELL_FAILED_NOT_SHAPESHIFT;
582 else if (spellInfo->Stances != 0) // needs other shapeshift
583 return SPELL_FAILED_ONLY_SHAPESHIFT;
585 else
587 // needs shapeshift
588 if(!(spellInfo->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) && spellInfo->Stances != 0)
589 return SPELL_FAILED_ONLY_SHAPESHIFT;
592 return 0;
595 void SpellMgr::LoadSpellTargetPositions()
597 mSpellTargetPositions.clear(); // need for reload case
599 uint32 count = 0;
601 // 0 1 2 3 4 5
602 QueryResult *result = WorldDatabase.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position");
603 if( !result )
606 barGoLink bar( 1 );
608 bar.step();
610 sLog.outString();
611 sLog.outString( ">> Loaded %u spell target coordinates", count );
612 return;
615 barGoLink bar( result->GetRowCount() );
619 Field *fields = result->Fetch();
621 bar.step();
623 ++count;
625 uint32 Spell_ID = fields[0].GetUInt32();
627 SpellTargetPosition st;
629 st.target_mapId = fields[1].GetUInt32();
630 st.target_X = fields[2].GetFloat();
631 st.target_Y = fields[3].GetFloat();
632 st.target_Z = fields[4].GetFloat();
633 st.target_Orientation = fields[5].GetFloat();
635 SpellEntry const* spellInfo = sSpellStore.LookupEntry(Spell_ID);
636 if(!spellInfo)
638 sLog.outErrorDb("Spell (ID:%u) listed in `spell_target_position` does not exist.",Spell_ID);
639 continue;
642 bool found = false;
643 for(int i = 0; i < 3; ++i)
645 if( spellInfo->EffectImplicitTargetA[i]==TARGET_TABLE_X_Y_Z_COORDINATES || spellInfo->EffectImplicitTargetB[i]==TARGET_TABLE_X_Y_Z_COORDINATES )
647 found = true;
648 break;
651 if(!found)
653 sLog.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID);
654 continue;
657 MapEntry const* mapEntry = sMapStore.LookupEntry(st.target_mapId);
658 if(!mapEntry)
660 sLog.outErrorDb("Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Spell_ID,st.target_mapId);
661 continue;
664 if(st.target_X==0 && st.target_Y==0 && st.target_Z==0)
666 sLog.outErrorDb("Spell (ID:%u) target coordinates not provided.",Spell_ID);
667 continue;
670 mSpellTargetPositions[Spell_ID] = st;
672 } while( result->NextRow() );
674 delete result;
676 sLog.outString();
677 sLog.outString( ">> Loaded %u spell teleport coordinates", count );
680 void SpellMgr::LoadSpellAffects()
682 mSpellAffectMap.clear(); // need for reload case
684 uint32 count = 0;
686 // 0 1 2 3 4
687 QueryResult *result = WorldDatabase.Query("SELECT entry, effectId, SpellClassMask0, SpellClassMask1, SpellClassMask2 FROM spell_affect");
688 if( !result )
691 barGoLink bar( 1 );
693 bar.step();
695 sLog.outString();
696 sLog.outString( ">> Loaded %u spell affect definitions", count );
697 return;
700 barGoLink bar( result->GetRowCount() );
704 Field *fields = result->Fetch();
706 bar.step();
708 uint16 entry = fields[0].GetUInt16();
709 uint8 effectId = fields[1].GetUInt8();
711 SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry);
713 if (!spellInfo)
715 sLog.outErrorDb("Spell %u listed in `spell_affect` does not exist", entry);
716 continue;
719 if (effectId >= 3)
721 sLog.outErrorDb("Spell %u listed in `spell_affect` have invalid effect index (%u)", entry,effectId);
722 continue;
725 if( spellInfo->Effect[effectId] != SPELL_EFFECT_APPLY_AURA ||
726 spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_FLAT_MODIFIER &&
727 spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_PCT_MODIFIER &&
728 spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER )
730 sLog.outErrorDb("Spell %u listed in `spell_affect` have not SPELL_AURA_ADD_FLAT_MODIFIER (%u) or SPELL_AURA_ADD_PCT_MODIFIER (%u) or SPELL_AURA_ADD_TARGET_TRIGGER (%u) for effect index (%u)", entry,SPELL_AURA_ADD_FLAT_MODIFIER,SPELL_AURA_ADD_PCT_MODIFIER,SPELL_AURA_ADD_TARGET_TRIGGER,effectId);
731 continue;
734 SpellAffectEntry affect;
735 affect.SpellClassMask[0] = fields[2].GetUInt32();
736 affect.SpellClassMask[1] = fields[3].GetUInt32();
737 affect.SpellClassMask[2] = fields[4].GetUInt32();
739 // Spell.dbc have own data
740 uint32 const *ptr = 0;
741 switch (effectId)
743 case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break;
744 case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break;
745 case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break;
746 default:
747 continue;
749 if(ptr[0] == affect.SpellClassMask[0] || ptr[1] == affect.SpellClassMask[1] || ptr[2] == affect.SpellClassMask[2])
751 char text[]="ABC";
752 sLog.outErrorDb("Spell %u listed in `spell_affect` have redundant (same with EffectSpellClassMask%c) data for effect index (%u) and not needed, skipped.", entry, text[effectId], effectId);
753 continue;
756 mSpellAffectMap[(entry<<8) + effectId] = affect;
758 ++count;
759 } while( result->NextRow() );
761 delete result;
763 sLog.outString();
764 sLog.outString( ">> Loaded %u custom spell affect definitions", count );
766 for (uint32 id = 0; id < sSpellStore.GetNumRows(); ++id)
768 SpellEntry const* spellInfo = sSpellStore.LookupEntry(id);
769 if (!spellInfo)
770 continue;
772 for (int effectId = 0; effectId < 3; ++effectId)
774 if( spellInfo->Effect[effectId] != SPELL_EFFECT_APPLY_AURA ||
775 (spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_FLAT_MODIFIER &&
776 spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_PCT_MODIFIER &&
777 spellInfo->EffectApplyAuraName[effectId] != SPELL_AURA_ADD_TARGET_TRIGGER) )
778 continue;
780 uint32 const *ptr = 0;
781 switch (effectId)
783 case 0: ptr = &spellInfo->EffectSpellClassMaskA[0]; break;
784 case 1: ptr = &spellInfo->EffectSpellClassMaskB[0]; break;
785 case 2: ptr = &spellInfo->EffectSpellClassMaskC[0]; break;
786 default:
787 continue;
789 if(ptr[0] || ptr[1] || ptr[2])
790 continue;
792 if(mSpellAffectMap.find((id<<8) + effectId) != mSpellAffectMap.end())
793 continue;
795 sLog.outErrorDb("Spell %u (%s) misses spell_affect for effect %u",id,spellInfo->SpellName[sWorld.GetDefaultDbcLocale()], effectId);
800 bool SpellMgr::IsAffectedByMod(SpellEntry const *spellInfo, SpellModifier *mod) const
802 // false for spellInfo == NULL
803 if (!spellInfo || !mod)
804 return false;
806 SpellEntry const *affect_spell = sSpellStore.LookupEntry(mod->spellId);
807 // False if affect_spell == NULL or spellFamily not equal
808 if (!affect_spell || affect_spell->SpellFamilyName != spellInfo->SpellFamilyName)
809 return false;
811 // true
812 if (mod->mask & spellInfo->SpellFamilyFlags ||
813 mod->mask2 & spellInfo->SpellFamilyFlags2)
814 return true;
816 return false;
819 void SpellMgr::LoadSpellProcEvents()
821 mSpellProcEventMap.clear(); // need for reload case
823 uint32 count = 0;
825 // 0 1 2 3 4 5 6 7 8 9 10
826 QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
827 if( !result )
829 barGoLink bar( 1 );
830 bar.step();
831 sLog.outString();
832 sLog.outString( ">> Loaded %u spell proc event conditions", count );
833 return;
836 barGoLink bar( result->GetRowCount() );
837 uint32 customProc = 0;
840 Field *fields = result->Fetch();
842 bar.step();
844 uint16 entry = fields[0].GetUInt16();
846 const SpellEntry *spell = sSpellStore.LookupEntry(entry);
847 if (!spell)
849 sLog.outErrorDb("Spell %u listed in `spell_proc_event` does not exist", entry);
850 continue;
853 SpellProcEventEntry spe;
855 spe.schoolMask = fields[1].GetUInt32();
856 spe.spellFamilyName = fields[2].GetUInt32();
857 spe.spellFamilyMask = (uint64)fields[3].GetUInt32()|((uint64)fields[4].GetUInt32()<<32);
858 spe.spellFamilyMask2= fields[5].GetUInt32();
859 spe.procFlags = fields[6].GetUInt32();
860 spe.procEx = fields[7].GetUInt32();
861 spe.ppmRate = fields[8].GetFloat();
862 spe.customChance = fields[9].GetFloat();
863 spe.cooldown = fields[10].GetUInt32();
865 mSpellProcEventMap[entry] = spe;
867 if (spell->procFlags==0)
869 if (spe.procFlags == 0)
871 sLog.outErrorDb("Spell %u listed in `spell_proc_event` probally not triggered spell", entry);
872 continue;
874 customProc++;
876 ++count;
877 } while( result->NextRow() );
879 delete result;
881 sLog.outString();
882 if (customProc)
883 sLog.outString( ">> Loaded %u extra spell proc event conditions +%u custom", count, customProc );
884 else
885 sLog.outString( ">> Loaded %u extra spell proc event conditions", count );
888 bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active)
890 // No extra req need
891 uint32 procEvent_procEx = PROC_EX_NONE;
893 // check prockFlags for condition
894 if((procFlags & EventProcFlag) == 0)
895 return false;
897 // Always trigger for this
898 if (EventProcFlag & (PROC_FLAG_KILLED | PROC_FLAG_KILL))
899 return true;
901 if (spellProcEvent) // Exist event data
903 // Store extra req
904 procEvent_procEx = spellProcEvent->procEx;
906 // For melee triggers
907 if (procSpell == NULL)
909 // Check (if set) for school (melee attack have Normal school)
910 if(spellProcEvent->schoolMask && (spellProcEvent->schoolMask & SPELL_SCHOOL_MASK_NORMAL) == 0)
911 return false;
913 else // For spells need check school/spell family/family mask
915 // Check (if set) for school
916 if(spellProcEvent->schoolMask && (spellProcEvent->schoolMask & procSpell->SchoolMask) == 0)
917 return false;
919 // Check (if set) for spellFamilyName
920 if(spellProcEvent->spellFamilyName && (spellProcEvent->spellFamilyName != procSpell->SpellFamilyName))
921 return false;
923 // spellFamilyName is Ok need check for spellFamilyMask if present
924 if(spellProcEvent->spellFamilyMask || spellProcEvent->spellFamilyMask2)
926 if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags ) == 0 &&
927 (spellProcEvent->spellFamilyMask2 & procSpell->SpellFamilyFlags2) == 0)
928 return false;
929 active = true; // Spell added manualy -> so its active spell
933 // Check for extra req (if none) and hit/crit
934 if (procEvent_procEx == PROC_EX_NONE)
936 // No extra req, so can trigger only for active (damage/healing present) and hit/crit
937 if((procExtra & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) && active)
938 return true;
940 else // Passive spells hits here only if resist/reflect/immune/evade
942 // Exist req for PROC_EX_EX_TRIGGER_ALWAYS
943 if (procEvent_procEx & PROC_EX_EX_TRIGGER_ALWAYS)
944 return true;
945 // Passive spells can`t trigger if need hit
946 if ((procEvent_procEx & PROC_EX_NORMAL_HIT) && !active)
947 return false;
948 // Check Extra Requirement like (hit/crit/miss/resist/parry/dodge/block/immune/reflect/absorb and other)
949 if (procEvent_procEx & procExtra)
950 return true;
952 return false;
955 void SpellMgr::LoadSpellElixirs()
957 mSpellElixirs.clear(); // need for reload case
959 uint32 count = 0;
961 // 0 1
962 QueryResult *result = WorldDatabase.Query("SELECT entry, mask FROM spell_elixir");
963 if( !result )
966 barGoLink bar( 1 );
968 bar.step();
970 sLog.outString();
971 sLog.outString( ">> Loaded %u spell elixir definitions", count );
972 return;
975 barGoLink bar( result->GetRowCount() );
979 Field *fields = result->Fetch();
981 bar.step();
983 uint16 entry = fields[0].GetUInt16();
984 uint8 mask = fields[1].GetUInt8();
986 SpellEntry const* spellInfo = sSpellStore.LookupEntry(entry);
988 if (!spellInfo)
990 sLog.outErrorDb("Spell %u listed in `spell_elixir` does not exist", entry);
991 continue;
994 mSpellElixirs[entry] = mask;
996 ++count;
997 } while( result->NextRow() );
999 delete result;
1001 sLog.outString();
1002 sLog.outString( ">> Loaded %u spell elixir definitions", count );
1005 void SpellMgr::LoadSpellThreats()
1007 sSpellThreatStore.Free(); // for reload
1009 sSpellThreatStore.Load();
1011 sLog.outString( ">> Loaded %u aggro generating spells", sSpellThreatStore.RecordCount );
1012 sLog.outString();
1015 bool SpellMgr::IsRankSpellDueToSpell(SpellEntry const *spellInfo_1,uint32 spellId_2) const
1017 SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
1018 if(!spellInfo_1 || !spellInfo_2) return false;
1019 if(spellInfo_1->Id == spellId_2) return false;
1021 return GetFirstSpellInChain(spellInfo_1->Id)==GetFirstSpellInChain(spellId_2);
1024 bool SpellMgr::canStackSpellRanks(SpellEntry const *spellInfo)
1026 if(spellInfo->powerType != POWER_MANA && spellInfo->powerType != POWER_HEALTH)
1027 return false;
1028 if(IsProfessionSpell(spellInfo->Id))
1029 return false;
1031 // All stance spells. if any better way, change it.
1032 for (int i = 0; i < 3; i++)
1034 // Paladin aura Spell
1035 if(spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN
1036 && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AREA_AURA_RAID)
1037 return false;
1038 // Druid form Spell
1039 if(spellInfo->SpellFamilyName == SPELLFAMILY_DRUID
1040 && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
1041 && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
1042 return false;
1043 // Rogue Stealth
1044 if(spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE
1045 && spellInfo->Effect[i]==SPELL_EFFECT_APPLY_AURA
1046 && spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_SHAPESHIFT)
1047 return false;
1049 return true;
1052 bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1, uint32 spellId_2) const
1054 SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
1055 SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
1057 if(!spellInfo_1 || !spellInfo_2)
1058 return false;
1060 if(spellInfo_1->Id == spellId_2)
1061 return false;
1063 //I think we don't check this correctly because i need a exception for spell:
1064 //72,11327,18461...(called from 1856,1857...) Call Aura 16,31, after trigger another spell who call aura 77 and 77 remove 16 and 31, this should not happen.
1065 if(spellInfo_2->SpellFamilyFlags == 2048)
1066 return false;
1068 // Resurrection sickness
1069 if((spellInfo_1->Id == SPELL_ID_PASSIVE_RESURRECTION_SICKNESS) != (spellInfo_2->Id==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS))
1070 return false;
1072 // Specific spell family spells
1073 switch(spellInfo_1->SpellFamilyName)
1075 case SPELLFAMILY_GENERIC:
1076 switch(spellInfo_2->SpellFamilyName)
1078 case SPELLFAMILY_GENERIC: // same family case
1080 // Thunderfury
1081 if( spellInfo_1->Id == 21992 && spellInfo_2->Id == 27648 || spellInfo_2->Id == 21992 && spellInfo_1->Id == 27648 )
1082 return false;
1084 // Lightning Speed (Mongoose) and Fury of the Crashing Waves (Tsunami Talisman)
1085 if( spellInfo_1->Id == 28093 && spellInfo_2->Id == 42084 ||
1086 spellInfo_2->Id == 28093 && spellInfo_1->Id == 42084 )
1087 return false;
1089 // Soulstone Resurrection and Twisting Nether (resurrector)
1090 if( spellInfo_1->SpellIconID == 92 && spellInfo_2->SpellIconID == 92 && (
1091 spellInfo_1->SpellVisual[0] == 99 && spellInfo_2->SpellVisual[0] == 0 ||
1092 spellInfo_2->SpellVisual[0] == 99 && spellInfo_1->SpellVisual[0] == 0 ) )
1093 return false;
1095 // Heart of the Wild and (Primal Instinct (Idol of Terror) triggering spell or Agility)
1096 if( spellInfo_1->SpellIconID == 240 && spellInfo_2->SpellIconID == 240 && (
1097 spellInfo_1->SpellVisual[0] == 0 && spellInfo_2->SpellVisual[0] == 78 ||
1098 spellInfo_2->SpellVisual[0] == 0 && spellInfo_1->SpellVisual[0] == 78 ) )
1099 return false;
1101 // Personalized Weather (thunder effect should overwrite rainy aura)
1102 if(spellInfo_1->SpellIconID == 2606 && spellInfo_2->SpellIconID == 2606)
1103 return false;
1105 // Brood Affliction: Bronze
1106 if( (spellInfo_1->Id == 23170 && spellInfo_2->Id == 23171) ||
1107 (spellInfo_2->Id == 23170 && spellInfo_1->Id == 23171) )
1108 return false;
1110 break;
1112 case SPELLFAMILY_WARRIOR:
1114 // Scroll of Protection and Defensive Stance (multi-family check)
1115 if( spellInfo_1->SpellIconID == 276 && spellInfo_1->SpellVisual[0] == 196 && spellInfo_2->Id == 71)
1116 return false;
1118 // Improved Hamstring -> Hamstring (multi-family check)
1119 if( (spellInfo_2->SpellFamilyFlags & 2) && spellInfo_1->Id == 23694 )
1120 return false;
1122 break;
1124 case SPELLFAMILY_DRUID:
1126 // Scroll of Stamina and Leader of the Pack (multi-family check)
1127 if( spellInfo_1->SpellIconID == 312 && spellInfo_1->SpellVisual[0] == 216 && spellInfo_2->Id == 24932 )
1128 return false;
1130 // Dragonmaw Illusion (multi-family check)
1131 if (spellId_1 == 40216 && spellId_2 == 42016 )
1132 return false;
1134 break;
1136 case SPELLFAMILY_ROGUE:
1138 // Garrote-Silence -> Garrote (multi-family check)
1139 if( spellInfo_1->SpellIconID == 498 && spellInfo_1->SpellVisual[0] == 0 && spellInfo_2->SpellIconID == 498 )
1140 return false;
1142 break;
1144 case SPELLFAMILY_HUNTER:
1146 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1147 if( spellInfo_1->Id == 19410 && spellInfo_2->Id == 5116 )
1148 return false;
1150 // Improved Wing Clip -> Wing Clip (multi-family check)
1151 if( (spellInfo_2->SpellFamilyFlags & 0x40) && spellInfo_1->Id == 19229 )
1152 return false;
1153 break;
1155 case SPELLFAMILY_PALADIN:
1157 // Unstable Currents and other -> *Sanctity Aura (multi-family check)
1158 if( spellInfo_2->SpellIconID==502 && spellInfo_1->SpellIconID==502 && spellInfo_1->SpellVisual[0]==969 )
1159 return false;
1161 // *Band of Eternal Champion and Seal of Command(multi-family check)
1162 if( spellId_1 == 35081 && spellInfo_2->SpellIconID==561 && spellInfo_2->SpellVisual[0]==7992)
1163 return false;
1165 break;
1168 break;
1169 case SPELLFAMILY_MAGE:
1170 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_MAGE )
1172 // Blizzard & Chilled (and some other stacked with blizzard spells
1173 if( (spellInfo_1->SpellFamilyFlags & 0x80) && (spellInfo_2->SpellFamilyFlags & 0x100000) ||
1174 (spellInfo_2->SpellFamilyFlags & 0x80) && (spellInfo_1->SpellFamilyFlags & 0x100000) )
1175 return false;
1177 // Blink & Improved Blink
1178 if( (spellInfo_1->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_2->SpellVisual[0] == 72 && spellInfo_2->SpellIconID == 1499) ||
1179 (spellInfo_2->SpellFamilyFlags & 0x0000000000010000LL) && (spellInfo_1->SpellVisual[0] == 72 && spellInfo_1->SpellIconID == 1499) )
1180 return false;
1182 // Detect Invisibility and Mana Shield (multi-family check)
1183 if( spellInfo_2->Id == 132 && spellInfo_1->SpellIconID == 209 && spellInfo_1->SpellVisual[0] == 968 )
1184 return false;
1186 // Combustion and Fire Protection Aura (multi-family check)
1187 if( spellInfo_1->Id == 11129 && spellInfo_2->SpellIconID == 33 && spellInfo_2->SpellVisual[0] == 321 )
1188 return false;
1190 break;
1191 case SPELLFAMILY_WARLOCK:
1192 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_WARLOCK )
1194 // Siphon Life and Drain Life
1195 if( spellInfo_1->SpellIconID == 152 && spellInfo_2->SpellIconID == 546 ||
1196 spellInfo_2->SpellIconID == 152 && spellInfo_1->SpellIconID == 546 )
1197 return false;
1199 //Corruption & Seed of corruption
1200 if( spellInfo_1->SpellIconID == 313 && spellInfo_2->SpellIconID == 1932 ||
1201 spellInfo_2->SpellIconID == 313 && spellInfo_1->SpellIconID == 1932 )
1202 if(spellInfo_1->SpellVisual[0] != 0 && spellInfo_2->SpellVisual[0] != 0)
1203 return true; // can't be stacked
1205 // Corruption and Unstable Affliction
1206 if( spellInfo_1->SpellIconID == 313 && spellInfo_2->SpellIconID == 2039 ||
1207 spellInfo_2->SpellIconID == 313 && spellInfo_1->SpellIconID == 2039 )
1208 return false;
1210 // (Corruption or Unstable Affliction) and (Curse of Agony or Curse of Doom)
1211 if( (spellInfo_1->SpellIconID == 313 || spellInfo_1->SpellIconID == 2039) && (spellInfo_2->SpellIconID == 544 || spellInfo_2->SpellIconID == 91) ||
1212 (spellInfo_2->SpellIconID == 313 || spellInfo_2->SpellIconID == 2039) && (spellInfo_1->SpellIconID == 544 || spellInfo_1->SpellIconID == 91) )
1213 return false;
1215 // Detect Invisibility and Mana Shield (multi-family check)
1216 if( spellInfo_1->Id == 132 && spellInfo_2->SpellIconID == 209 && spellInfo_2->SpellVisual[0] == 968 )
1217 return false;
1218 break;
1219 case SPELLFAMILY_WARRIOR:
1220 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_WARRIOR )
1222 // Rend and Deep Wound
1223 if( (spellInfo_1->SpellFamilyFlags & 0x20) && (spellInfo_2->SpellFamilyFlags & 0x1000000000LL) ||
1224 (spellInfo_2->SpellFamilyFlags & 0x20) && (spellInfo_1->SpellFamilyFlags & 0x1000000000LL) )
1225 return false;
1227 // Battle Shout and Rampage
1228 if( (spellInfo_1->SpellIconID == 456 && spellInfo_2->SpellIconID == 2006) ||
1229 (spellInfo_2->SpellIconID == 456 && spellInfo_1->SpellIconID == 2006) )
1230 return false;
1233 // Hamstring -> Improved Hamstring (multi-family check)
1234 if( (spellInfo_1->SpellFamilyFlags & 2) && spellInfo_2->Id == 23694 )
1235 return false;
1237 // Defensive Stance and Scroll of Protection (multi-family check)
1238 if( spellInfo_1->Id == 71 && spellInfo_2->SpellIconID == 276 && spellInfo_2->SpellVisual[0] == 196 )
1239 return false;
1241 // Bloodlust and Bloodthirst (multi-family check)
1242 if( spellInfo_2->Id == 2825 && spellInfo_1->SpellIconID == 38 && spellInfo_1->SpellVisual[0] == 0 )
1243 return false;
1245 break;
1246 case SPELLFAMILY_PRIEST:
1247 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PRIEST )
1249 //Devouring Plague and Shadow Vulnerability
1250 if( (spellInfo_1->SpellFamilyFlags & 0x2000000) && (spellInfo_2->SpellFamilyFlags & 0x800000000LL) ||
1251 (spellInfo_2->SpellFamilyFlags & 0x2000000) && (spellInfo_1->SpellFamilyFlags & 0x800000000LL) )
1252 return false;
1254 //StarShards and Shadow Word: Pain
1255 if( (spellInfo_1->SpellFamilyFlags & 0x200000) && (spellInfo_2->SpellFamilyFlags & 0x8000) ||
1256 (spellInfo_2->SpellFamilyFlags & 0x200000) && (spellInfo_1->SpellFamilyFlags & 0x8000) )
1257 return false;
1259 break;
1260 case SPELLFAMILY_DRUID:
1261 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_DRUID )
1263 //Omen of Clarity and Blood Frenzy
1264 if( (spellInfo_1->SpellFamilyFlags == 0x0 && spellInfo_1->SpellIconID == 108) && (spellInfo_2->SpellFamilyFlags & 0x20000000000000LL) ||
1265 (spellInfo_2->SpellFamilyFlags == 0x0 && spellInfo_2->SpellIconID == 108) && (spellInfo_1->SpellFamilyFlags & 0x20000000000000LL) )
1266 return false;
1268 // Tree of Life (Shapeshift) and 34123 Tree of Life (Passive)
1269 if ((spellId_1 == 33891 && spellId_2 == 34123) ||
1270 (spellId_2 == 33891 && spellId_1 == 34123))
1271 return false;
1273 // Wrath of Elune and Nature's Grace
1274 if( spellInfo_1->Id == 16886 && spellInfo_2->Id == 46833 || spellInfo_2->Id == 16886 && spellInfo_1->Id == 46833 )
1275 return false;
1277 // Bear Rage (Feral T4 (2)) and Omen of Clarity
1278 if( spellInfo_1->Id == 16864 && spellInfo_2->Id == 37306 || spellInfo_2->Id == 16864 && spellInfo_1->Id == 37306 )
1279 return false;
1281 // Cat Energy (Feral T4 (2)) and Omen of Clarity
1282 if( spellInfo_1->Id == 16864 && spellInfo_2->Id == 37311 || spellInfo_2->Id == 16864 && spellInfo_1->Id == 37311 )
1283 return false;
1286 // Leader of the Pack and Scroll of Stamina (multi-family check)
1287 if( spellInfo_1->Id == 24932 && spellInfo_2->SpellIconID == 312 && spellInfo_2->SpellVisual[0] == 216 )
1288 return false;
1290 // Dragonmaw Illusion (multi-family check)
1291 if (spellId_1 == 42016 && spellId_2 == 40216 )
1292 return false;
1294 break;
1295 case SPELLFAMILY_ROGUE:
1296 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_ROGUE )
1298 // Master of Subtlety
1299 if (spellId_1 == 31665 && spellId_2 == 31666 || spellId_1 == 31666 && spellId_2 == 31665 )
1300 return false;
1303 // Garrote -> Garrote-Silence (multi-family check)
1304 if( spellInfo_1->SpellIconID == 498 && spellInfo_2->SpellIconID == 498 && spellInfo_2->SpellVisual[0] == 0 )
1305 return false;
1306 break;
1307 case SPELLFAMILY_HUNTER:
1308 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_HUNTER )
1310 // Rapid Fire & Quick Shots
1311 if( (spellInfo_1->SpellFamilyFlags & 0x20) && (spellInfo_2->SpellFamilyFlags & 0x20000000000LL) ||
1312 (spellInfo_2->SpellFamilyFlags & 0x20) && (spellInfo_1->SpellFamilyFlags & 0x20000000000LL) )
1313 return false;
1315 // Serpent Sting & (Immolation/Explosive Trap Effect)
1316 if( (spellInfo_1->SpellFamilyFlags & 0x4) && (spellInfo_2->SpellFamilyFlags & 0x00000004000LL) ||
1317 (spellInfo_2->SpellFamilyFlags & 0x4) && (spellInfo_1->SpellFamilyFlags & 0x00000004000LL) )
1318 return false;
1320 // Bestial Wrath
1321 if( spellInfo_1->SpellIconID == 1680 && spellInfo_2->SpellIconID == 1680 )
1322 return false;
1325 // Wing Clip -> Improved Wing Clip (multi-family check)
1326 if( (spellInfo_1->SpellFamilyFlags & 0x40) && spellInfo_2->Id == 19229 )
1327 return false;
1329 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1330 if( spellInfo_2->Id == 19410 && spellInfo_1->Id == 5116 )
1331 return false;
1332 break;
1333 case SPELLFAMILY_PALADIN:
1334 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_PALADIN )
1336 // Paladin Seals
1337 if( IsSealSpell(spellInfo_1) && IsSealSpell(spellInfo_2) )
1338 return true;
1340 // Combustion and Fire Protection Aura (multi-family check)
1341 if( spellInfo_2->Id == 11129 && spellInfo_1->SpellIconID == 33 && spellInfo_1->SpellVisual[0] == 321 )
1342 return false;
1344 // *Sanctity Aura -> Unstable Currents and other (multi-family check)
1345 if( spellInfo_1->SpellIconID==502 && spellInfo_2->SpellFamilyName == SPELLFAMILY_GENERIC && spellInfo_2->SpellIconID==502 && spellInfo_2->SpellVisual[0]==969 )
1346 return false;
1348 // *Seal of Command and Band of Eternal Champion (multi-family check)
1349 if( spellInfo_1->SpellIconID==561 && spellInfo_1->SpellVisual[0]==7992 && spellId_2 == 35081)
1350 return false;
1351 break;
1352 case SPELLFAMILY_SHAMAN:
1353 if( spellInfo_2->SpellFamilyName == SPELLFAMILY_SHAMAN )
1355 // shaman shields
1356 if( IsElementalShield(spellInfo_1) && IsElementalShield(spellInfo_2) )
1357 return true;
1359 // Windfury weapon
1360 if( spellInfo_1->SpellIconID==220 && spellInfo_2->SpellIconID==220 &&
1361 spellInfo_1->SpellFamilyFlags != spellInfo_2->SpellFamilyFlags )
1362 return false;
1364 // Bloodlust and Bloodthirst (multi-family check)
1365 if( spellInfo_1->Id == 2825 && spellInfo_2->SpellIconID == 38 && spellInfo_2->SpellVisual[0] == 0 )
1366 return false;
1367 break;
1368 default:
1369 break;
1372 // more generic checks
1373 if (spellInfo_1->SpellIconID == spellInfo_2->SpellIconID &&
1374 spellInfo_1->SpellIconID != 0 && spellInfo_2->SpellIconID != 0)
1376 bool isModifier = false;
1377 for (int i = 0; i < 3; i++)
1379 if (spellInfo_1->EffectApplyAuraName[i] == SPELL_AURA_ADD_FLAT_MODIFIER ||
1380 spellInfo_1->EffectApplyAuraName[i] == SPELL_AURA_ADD_PCT_MODIFIER ||
1381 spellInfo_2->EffectApplyAuraName[i] == SPELL_AURA_ADD_FLAT_MODIFIER ||
1382 spellInfo_2->EffectApplyAuraName[i] == SPELL_AURA_ADD_PCT_MODIFIER )
1383 isModifier = true;
1386 if (!isModifier)
1387 return true;
1390 if (IsRankSpellDueToSpell(spellInfo_1, spellId_2))
1391 return true;
1393 if (spellInfo_1->SpellFamilyName == 0 || spellInfo_2->SpellFamilyName == 0)
1394 return false;
1396 if (spellInfo_1->SpellFamilyName != spellInfo_2->SpellFamilyName)
1397 return false;
1399 for (int i = 0; i < 3; ++i)
1400 if (spellInfo_1->Effect[i] != spellInfo_2->Effect[i] ||
1401 spellInfo_1->EffectItemType[i] != spellInfo_2->EffectItemType[i] ||
1402 spellInfo_1->EffectMiscValue[i] != spellInfo_2->EffectMiscValue[i] ||
1403 spellInfo_1->EffectApplyAuraName[i] != spellInfo_2->EffectApplyAuraName[i])
1404 return false;
1406 return true;
1409 bool SpellMgr::IsProfessionSpell(uint32 spellId)
1411 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
1412 if(!spellInfo)
1413 return false;
1415 if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL)
1416 return false;
1418 uint32 skill = spellInfo->EffectMiscValue[1];
1420 return IsProfessionSkill(skill);
1423 bool SpellMgr::IsPrimaryProfessionSpell(uint32 spellId)
1425 SpellEntry const *spellInfo = sSpellStore.LookupEntry(spellId);
1426 if(!spellInfo)
1427 return false;
1429 if(spellInfo->Effect[1] != SPELL_EFFECT_SKILL)
1430 return false;
1432 uint32 skill = spellInfo->EffectMiscValue[1];
1434 return IsPrimaryProfessionSkill(skill);
1437 bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId) const
1439 return IsPrimaryProfessionSpell(spellId) && GetSpellRank(spellId)==1;
1442 SpellEntry const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry const* spellInfo, uint32 playerLevel) const
1444 // ignore passive spells
1445 if(IsPassiveSpell(spellInfo->Id))
1446 return spellInfo;
1448 bool needRankSelection = false;
1449 for(int i=0;i<3;i++)
1451 if( IsPositiveEffect(spellInfo->Id, i) && (
1452 spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA ||
1453 spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY ||
1454 spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_RAID
1457 needRankSelection = true;
1458 break;
1462 // not required
1463 if(!needRankSelection)
1464 return spellInfo;
1466 for(uint32 nextSpellId = spellInfo->Id; nextSpellId != 0; nextSpellId = GetPrevSpellInChain(nextSpellId))
1468 SpellEntry const *nextSpellInfo = sSpellStore.LookupEntry(nextSpellId);
1469 if(!nextSpellInfo)
1470 break;
1472 // if found appropriate level
1473 if(playerLevel + 10 >= nextSpellInfo->spellLevel)
1474 return nextSpellInfo;
1476 // one rank less then
1479 // not found
1480 return NULL;
1483 void SpellMgr::LoadSpellChains()
1485 mSpellChains.clear(); // need for reload case
1486 mSpellChainsNext.clear(); // need for reload case
1488 QueryResult *result = WorldDatabase.Query("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain");
1489 if(result == NULL)
1491 barGoLink bar( 1 );
1492 bar.step();
1494 sLog.outString();
1495 sLog.outString( ">> Loaded 0 spell chain records" );
1496 sLog.outErrorDb("`spell_chains` table is empty!");
1497 return;
1500 uint32 count = 0;
1502 barGoLink bar( result->GetRowCount() );
1505 bar.step();
1506 Field *fields = result->Fetch();
1508 uint32 spell_id = fields[0].GetUInt32();
1510 SpellChainNode node;
1511 node.prev = fields[1].GetUInt32();
1512 node.first = fields[2].GetUInt32();
1513 node.rank = fields[3].GetUInt8();
1514 node.req = fields[4].GetUInt32();
1516 if(!sSpellStore.LookupEntry(spell_id))
1518 sLog.outErrorDb("Spell %u listed in `spell_chain` does not exist",spell_id);
1519 continue;
1522 if(node.prev!=0 && !sSpellStore.LookupEntry(node.prev))
1524 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existed previous rank spell.",
1525 spell_id,node.prev,node.first,node.rank,node.req);
1526 continue;
1529 if(!sSpellStore.LookupEntry(node.first))
1531 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing first rank spell.",
1532 spell_id,node.prev,node.first,node.rank,node.req);
1533 continue;
1536 // check basic spell chain data integrity (note: rank can be equal 0 or 1 for first/single spell)
1537 if( (spell_id == node.first) != (node.rank <= 1) ||
1538 (spell_id == node.first) != (node.prev == 0) ||
1539 (node.rank <= 1) != (node.prev == 0) )
1541 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not compatible chain data.",
1542 spell_id,node.prev,node.first,node.rank,node.req);
1543 continue;
1546 if(node.req!=0 && !sSpellStore.LookupEntry(node.req))
1548 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing required spell.",
1549 spell_id,node.prev,node.first,node.rank,node.req);
1550 continue;
1553 // talents not required data in spell chain for work, but must be checked if present for intergrity
1554 if(TalentSpellPos const* pos = GetTalentSpellPos(spell_id))
1556 if(node.rank!=pos->rank+1)
1558 sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong rank.",
1559 spell_id,node.prev,node.first,node.rank,node.req);
1560 continue;
1563 if(TalentEntry const* talentEntry = sTalentStore.LookupEntry(pos->talent_id))
1565 if(node.first!=talentEntry->RankID[0])
1567 sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong first rank spell.",
1568 spell_id,node.prev,node.first,node.rank,node.req);
1569 continue;
1572 if(node.rank > 1 && node.prev != talentEntry->RankID[node.rank-1-1])
1574 sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong prev rank spell.",
1575 spell_id,node.prev,node.first,node.rank,node.req);
1576 continue;
1579 /*if(node.req!=talentEntry->DependsOnSpell)
1581 sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong required spell.",
1582 spell_id,node.prev,node.first,node.rank,node.req);
1583 continue;
1588 mSpellChains[spell_id] = node;
1590 if(node.prev)
1591 mSpellChainsNext.insert(SpellChainMapNext::value_type(node.prev,spell_id));
1593 if(node.req)
1594 mSpellChainsNext.insert(SpellChainMapNext::value_type(node.req,spell_id));
1596 ++count;
1597 } while( result->NextRow() );
1599 delete result;
1601 // additional integrity checks
1602 for(SpellChainMap::iterator i = mSpellChains.begin(); i != mSpellChains.end(); ++i)
1604 if(i->second.prev)
1606 SpellChainMap::iterator i_prev = mSpellChains.find(i->second.prev);
1607 if(i_prev == mSpellChains.end())
1609 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found previous rank spell in table.",
1610 i->first,i->second.prev,i->second.first,i->second.rank,i->second.req);
1612 else if( i_prev->second.first != i->second.first )
1614 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has different first spell in chain compared to previous rank spell (prev: %u, first: %u, rank: %d, req: %u).",
1615 i->first,i->second.prev,i->second.first,i->second.rank,i->second.req,
1616 i_prev->second.prev,i_prev->second.first,i_prev->second.rank,i_prev->second.req);
1618 else if( i_prev->second.rank+1 != i->second.rank )
1620 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has different rank compared to previous rank spell (prev: %u, first: %u, rank: %d, req: %u).",
1621 i->first,i->second.prev,i->second.first,i->second.rank,i->second.req,
1622 i_prev->second.prev,i_prev->second.first,i_prev->second.rank,i_prev->second.req);
1626 if(i->second.req)
1628 SpellChainMap::iterator i_req = mSpellChains.find(i->second.req);
1629 if(i_req == mSpellChains.end())
1631 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found required rank spell in table.",
1632 i->first,i->second.prev,i->second.first,i->second.rank,i->second.req);
1634 else if( i_req->second.first == i->second.first )
1636 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has required rank spell from same spell chain (prev: %u, first: %u, rank: %d, req: %u).",
1637 i->first,i->second.prev,i->second.first,i->second.rank,i->second.req,
1638 i_req->second.prev,i_req->second.first,i_req->second.rank,i_req->second.req);
1640 else if( i_req->second.req )
1642 sLog.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has required rank spell with required spell (prev: %u, first: %u, rank: %d, req: %u).",
1643 i->first,i->second.prev,i->second.first,i->second.rank,i->second.req,
1644 i_req->second.prev,i_req->second.first,i_req->second.rank,i_req->second.req);
1649 sLog.outString();
1650 sLog.outString( ">> Loaded %u spell chain records", count );
1653 void SpellMgr::LoadSpellLearnSkills()
1655 mSpellLearnSkills.clear(); // need for reload case
1657 // search auto-learned skills and add its to map also for use in unlearn spells/talents
1658 uint32 dbc_count = 0;
1659 for(uint32 spell = 0; spell < sSpellStore.GetNumRows(); ++spell)
1661 SpellEntry const* entry = sSpellStore.LookupEntry(spell);
1663 if(!entry)
1664 continue;
1666 for(int i = 0; i < 3; ++i)
1668 if(entry->Effect[i]==SPELL_EFFECT_SKILL)
1670 SpellLearnSkillNode dbc_node;
1671 dbc_node.skill = entry->EffectMiscValue[i];
1672 if ( dbc_node.skill != SKILL_RIDING )
1673 dbc_node.value = 1;
1674 else
1675 dbc_node.value = (entry->EffectBasePoints[i]+1)*75;
1676 dbc_node.maxvalue = (entry->EffectBasePoints[i]+1)*75;
1678 mSpellLearnSkills[spell] = dbc_node;
1679 ++dbc_count;
1680 break;
1685 sLog.outString();
1686 sLog.outString( ">> Loaded %u Spell Learn Skills from DBC", dbc_count );
1689 void SpellMgr::LoadSpellLearnSpells()
1691 mSpellLearnSpells.clear(); // need for reload case
1693 QueryResult *result = WorldDatabase.Query("SELECT entry, SpellID FROM spell_learn_spell");
1694 if(!result)
1696 barGoLink bar( 1 );
1697 bar.step();
1699 sLog.outString();
1700 sLog.outString( ">> Loaded 0 spell learn spells" );
1701 sLog.outErrorDb("`spell_learn_spell` table is empty!");
1702 return;
1705 uint32 count = 0;
1707 barGoLink bar( result->GetRowCount() );
1710 bar.step();
1711 Field *fields = result->Fetch();
1713 uint32 spell_id = fields[0].GetUInt32();
1715 SpellLearnSpellNode node;
1716 node.spell = fields[1].GetUInt32();
1717 node.autoLearned= false;
1719 if(!sSpellStore.LookupEntry(spell_id))
1721 sLog.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",spell_id);
1722 continue;
1725 if(!sSpellStore.LookupEntry(node.spell))
1727 sLog.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",node.spell);
1728 continue;
1731 mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spell_id,node));
1733 ++count;
1734 } while( result->NextRow() );
1736 delete result;
1738 // search auto-learned spells and add its to map also for use in unlearn spells/talents
1739 uint32 dbc_count = 0;
1740 for(uint32 spell = 0; spell < sSpellStore.GetNumRows(); ++spell)
1742 SpellEntry const* entry = sSpellStore.LookupEntry(spell);
1744 if(!entry)
1745 continue;
1747 for(int i = 0; i < 3; ++i)
1749 if(entry->Effect[i]==SPELL_EFFECT_LEARN_SPELL)
1751 SpellLearnSpellNode dbc_node;
1752 dbc_node.spell = entry->EffectTriggerSpell[i];
1754 // ignore learning not existed spells (broken/outdated/or generic learnig spell 483
1755 if(!sSpellStore.LookupEntry(dbc_node.spell))
1756 continue;
1758 // talent or passive spells or skill-step spells auto-casted and not need dependent learning,
1759 // pet teaching spells don't must be dependent learning (casted)
1760 // other required explicit dependent learning
1761 dbc_node.autoLearned = entry->EffectImplicitTargetA[i]==TARGET_PET || GetTalentSpellCost(spell) > 0 || IsPassiveSpell(spell) || IsSpellHaveEffect(entry,SPELL_EFFECT_SKILL_STEP);
1763 SpellLearnSpellMap::const_iterator db_node_begin = GetBeginSpellLearnSpell(spell);
1764 SpellLearnSpellMap::const_iterator db_node_end = GetEndSpellLearnSpell(spell);
1766 bool found = false;
1767 for(SpellLearnSpellMap::const_iterator itr = db_node_begin; itr != db_node_end; ++itr)
1769 if(itr->second.spell == dbc_node.spell)
1771 sLog.outErrorDb("Spell %u auto-learn spell %u in spell.dbc then the record in `spell_learn_spell` is redundant, please fix DB.",
1772 spell,dbc_node.spell);
1773 found = true;
1774 break;
1778 if(!found) // add new spell-spell pair if not found
1780 mSpellLearnSpells.insert(SpellLearnSpellMap::value_type(spell,dbc_node));
1781 ++dbc_count;
1787 sLog.outString();
1788 sLog.outString( ">> Loaded %u spell learn spells + %u found in DBC", count, dbc_count );
1791 void SpellMgr::LoadSpellScriptTarget()
1793 mSpellScriptTarget.clear(); // need for reload case
1795 uint32 count = 0;
1797 QueryResult *result = WorldDatabase.Query("SELECT entry,type,targetEntry FROM spell_script_target");
1799 if(!result)
1801 barGoLink bar(1);
1803 bar.step();
1805 sLog.outString();
1806 sLog.outErrorDb(">> Loaded 0 SpellScriptTarget. DB table `spell_script_target` is empty.");
1807 return;
1810 barGoLink bar(result->GetRowCount());
1814 Field *fields = result->Fetch();
1815 bar.step();
1817 uint32 spellId = fields[0].GetUInt32();
1818 uint32 type = fields[1].GetUInt32();
1819 uint32 targetEntry = fields[2].GetUInt32();
1821 SpellEntry const* spellProto = sSpellStore.LookupEntry(spellId);
1823 if(!spellProto)
1825 sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not exist.",spellId,targetEntry);
1826 continue;
1829 bool targetfound = false;
1830 for(int i = 0; i <3; ++i)
1832 if( spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT ||
1833 spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT ||
1834 spellProto->EffectImplicitTargetA[i]==TARGET_SCRIPT_COORDINATES ||
1835 spellProto->EffectImplicitTargetB[i]==TARGET_SCRIPT_COORDINATES )
1837 targetfound = true;
1838 break;
1841 if(!targetfound)
1843 sLog.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not have any implicit target TARGET_SCRIPT(38) or TARGET_SCRIPT_COORDINATES (46).",spellId,targetEntry);
1844 continue;
1847 if( type >= MAX_SPELL_TARGET_TYPE )
1849 sLog.outErrorDb("Table `spell_script_target`: target type %u for TargetEntry %u is incorrect.",type,targetEntry);
1850 continue;
1853 switch(type)
1855 case SPELL_TARGET_TYPE_GAMEOBJECT:
1857 if( targetEntry==0 )
1858 break;
1860 if(!sGOStorage.LookupEntry<GameObjectInfo>(targetEntry))
1862 sLog.outErrorDb("Table `spell_script_target`: gameobject template entry %u does not exist.",targetEntry);
1863 continue;
1865 break;
1867 default:
1869 if( targetEntry==0 )
1871 sLog.outErrorDb("Table `spell_script_target`: target entry == 0 for not GO target type (%u).",type);
1872 continue;
1874 if(!sCreatureStorage.LookupEntry<CreatureInfo>(targetEntry))
1876 sLog.outErrorDb("Table `spell_script_target`: creature template entry %u does not exist.",targetEntry);
1877 continue;
1879 const CreatureInfo* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(targetEntry);
1881 if(spellId == 30427 && !cInfo->SkinLootId)
1883 sLog.outErrorDb("Table `spell_script_target` has creature %u as a target of spellid 30427, but this creature has no skinlootid. Gas extraction will not work!", cInfo->Entry);
1884 continue;
1886 break;
1890 mSpellScriptTarget.insert(SpellScriptTarget::value_type(spellId,SpellTargetEntry(SpellTargetType(type),targetEntry)));
1892 ++count;
1893 } while (result->NextRow());
1895 delete result;
1897 // Check all spells
1898 /* Disabled (lot errors at this moment)
1899 for(uint32 i = 1; i < sSpellStore.nCount; ++i)
1901 SpellEntry const * spellInfo = sSpellStore.LookupEntry(i);
1902 if(!spellInfo)
1903 continue;
1905 bool found = false;
1906 for(int j=0; j<3; ++j)
1908 if( spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || spellInfo->EffectImplicitTargetA[j] != TARGET_SELF && spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT )
1910 SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(spellInfo->Id);
1911 SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(spellInfo->Id);
1912 if(lower==upper)
1914 sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = %u (TARGET_SCRIPT), but does not have record in `spell_script_target`",spellInfo->Id,TARGET_SCRIPT);
1915 break; // effects of spell
1922 sLog.outString();
1923 sLog.outString(">> Loaded %u Spell Script Targets", count);
1926 void SpellMgr::LoadSpellPetAuras()
1928 mSpellPetAuraMap.clear(); // need for reload case
1930 uint32 count = 0;
1932 // 0 1 2
1933 QueryResult *result = WorldDatabase.Query("SELECT spell, pet, aura FROM spell_pet_auras");
1934 if( !result )
1937 barGoLink bar( 1 );
1939 bar.step();
1941 sLog.outString();
1942 sLog.outString( ">> Loaded %u spell pet auras", count );
1943 return;
1946 barGoLink bar( result->GetRowCount() );
1950 Field *fields = result->Fetch();
1952 bar.step();
1954 uint16 spell = fields[0].GetUInt16();
1955 uint16 pet = fields[1].GetUInt16();
1956 uint16 aura = fields[2].GetUInt16();
1958 SpellPetAuraMap::iterator itr = mSpellPetAuraMap.find(spell);
1959 if(itr != mSpellPetAuraMap.end())
1961 itr->second.AddAura(pet, aura);
1963 else
1965 SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell);
1966 if (!spellInfo)
1968 sLog.outErrorDb("Spell %u listed in `spell_pet_auras` does not exist", spell);
1969 continue;
1971 int i = 0;
1972 for(; i < 3; ++i)
1973 if((spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA &&
1974 spellInfo->EffectApplyAuraName[i] == SPELL_AURA_DUMMY) ||
1975 spellInfo->Effect[i] == SPELL_EFFECT_DUMMY)
1976 break;
1978 if(i == 3)
1980 sLog.outError("Spell %u listed in `spell_pet_auras` does not have dummy aura or dummy effect", spell);
1981 continue;
1984 SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(aura);
1985 if (!spellInfo2)
1987 sLog.outErrorDb("Aura %u listed in `spell_pet_auras` does not exist", aura);
1988 continue;
1991 PetAura pa(pet, aura, spellInfo->EffectImplicitTargetA[i] == TARGET_PET, spellInfo->EffectBasePoints[i] + spellInfo->EffectBaseDice[i]);
1992 mSpellPetAuraMap[spell] = pa;
1995 ++count;
1996 } while( result->NextRow() );
1998 delete result;
2000 sLog.outString();
2001 sLog.outString( ">> Loaded %u spell pet auras", count );
2004 void SpellMgr::LoadPetLevelupSpellMap()
2006 CreatureFamilyEntry const *creatureFamily;
2007 SpellEntry const *spell;
2008 uint32 count = 0;
2010 for (uint32 i = 0; i < sCreatureFamilyStore.GetNumRows(); ++i)
2012 creatureFamily = sCreatureFamilyStore.LookupEntry(i);
2014 if(!creatureFamily) // not exist
2015 continue;
2017 if(creatureFamily->petTalentType < 0) // not hunter pet family
2018 continue;
2020 for(uint32 j = 0; j < sSpellStore.GetNumRows(); ++j)
2022 spell = sSpellStore.LookupEntry(j);
2024 // not exist
2025 if(!spell)
2026 continue;
2028 // not hunter spell
2029 if(spell->SpellFamilyName != SPELLFAMILY_HUNTER)
2030 continue;
2032 // not pet spell
2033 if(!(spell->SpellFamilyFlags & 0x1000000000000000LL))
2034 continue;
2036 // not Growl or Cower (generics)
2037 if(spell->SpellIconID != 201 && spell->SpellIconID != 958)
2039 switch(creatureFamily->ID)
2041 case CREATURE_FAMILY_BAT: // Bite and Sonic Blast
2042 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1577)
2043 continue;
2044 break;
2045 case CREATURE_FAMILY_BEAR: // Claw and Swipe
2046 if(spell->SpellIconID != 262 && spell->SpellIconID != 1562)
2047 continue;
2048 break;
2049 case CREATURE_FAMILY_BIRD_OF_PREY: // Claw and Snatch
2050 if(spell->SpellIconID != 262 && spell->SpellIconID != 168)
2051 continue;
2052 break;
2053 case CREATURE_FAMILY_BOAR: // Bite and Gore
2054 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1578)
2055 continue;
2056 break;
2057 case CREATURE_FAMILY_CARRION_BIRD: // Bite and Demoralizing Screech
2058 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1579)
2059 continue;
2060 break;
2061 case CREATURE_FAMILY_CAT: // Claw and Prowl and Rake
2062 if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 494)
2063 continue;
2064 break;
2065 case CREATURE_FAMILY_CHIMAERA: // Bite and Froststorm Breath
2066 if(spell->SpellIconID != 1680 && spell->SpellIconID != 62)
2067 continue;
2068 break;
2069 case CREATURE_FAMILY_CORE_HOUND: // Bite and Lava Breath
2070 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1197)
2071 continue;
2072 break;
2073 case CREATURE_FAMILY_CRAB: // Claw and Pin
2074 if(spell->SpellIconID != 262 && spell->SpellIconID != 2679)
2075 continue;
2076 break;
2077 case CREATURE_FAMILY_CROCOLISK: // Bite and Bad Attitude
2078 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1581)
2079 continue;
2080 break;
2081 case CREATURE_FAMILY_DEVILSAUR: // Bite and Monstrous Bite
2082 if(spell->SpellIconID != 1680 && spell->SpellIconID != 599)
2083 continue;
2084 break;
2085 case CREATURE_FAMILY_DRAGONHAWK: // Bite and Fire Breath
2086 if(spell->SpellIconID != 1680 && spell->SpellIconID != 2128)
2087 continue;
2088 break;
2089 case CREATURE_FAMILY_GORILLA: // Smack and Thunderstomp
2090 if(spell->SpellIconID != 473 && spell->SpellIconID != 148)
2091 continue;
2092 break;
2093 case CREATURE_FAMILY_HYENA: // Bite and Tendon Rip
2094 if(spell->SpellIconID != 1680 && spell->SpellIconID != 138)
2095 continue;
2096 break;
2097 case CREATURE_FAMILY_MOTH: // Serenity Dust and Smack
2098 if(spell->SpellIconID != 1714 && spell->SpellIconID != 473)
2099 continue;
2100 break;
2101 case CREATURE_FAMILY_NETHER_RAY: // Bite and Nether Shock
2102 if(spell->SpellIconID != 1680 && spell->SpellIconID != 2027)
2103 continue;
2104 break;
2105 case CREATURE_FAMILY_RAPTOR: // Claw and Savage Rend
2106 if(spell->SpellIconID != 262 && spell->SpellIconID != 245)
2107 continue;
2108 break;
2109 case CREATURE_FAMILY_RAVAGER: // Bite and Ravage
2110 if(spell->SpellIconID != 1680 && spell->SpellIconID != 2253)
2111 continue;
2112 break;
2113 case CREATURE_FAMILY_RHINO: // Smack and Stampede
2114 if(spell->SpellIconID != 473 && spell->SpellIconID != 3066)
2115 continue;
2116 break;
2117 case CREATURE_FAMILY_SCORPID: // Claw and Scorpid Poison
2118 if(spell->SpellIconID != 262 && spell->SpellIconID != 163)
2119 continue;
2120 break;
2121 case CREATURE_FAMILY_SERPENT: // Bite and Poison Spit
2122 if(spell->SpellIconID != 1680 && spell->SpellIconID != 68)
2123 continue;
2124 break;
2125 case CREATURE_FAMILY_SILITHID: // Claw and Venom Web Spray
2126 if(spell->SpellIconID != 262 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 12013))
2127 continue;
2128 break;
2129 case CREATURE_FAMILY_SPIDER: // Bite and Web
2130 if(spell->SpellIconID != 1680 && (spell->SpellIconID != 272 && spell->SpellVisual[0] != 684))
2131 continue;
2132 break;
2133 case CREATURE_FAMILY_SPIRIT_BEAST: // Claw and Prowl and Spirit Strike
2134 if(spell->SpellIconID != 262 && spell->SpellIconID != 495 && spell->SpellIconID != 255)
2135 continue;
2136 break;
2137 case CREATURE_FAMILY_SPOREBAT: // Smack and Spore Cloud
2138 if(spell->SpellIconID != 473 && spell->SpellIconID != 2681)
2139 continue;
2140 break;
2141 case CREATURE_FAMILY_TALLSTRIDER: // Claw and Dust Cloud
2142 if(spell->SpellIconID != 262 && (spell->SpellIconID != 157 && !(spell->Attributes & 0x4000000)))
2143 continue;
2144 break;
2145 case CREATURE_FAMILY_TURTLE: // Bite and Shell Shield
2146 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1588)
2147 continue;
2148 break;
2149 case CREATURE_FAMILY_WARP_STALKER: // Bite and Warp
2150 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1952)
2151 continue;
2152 break;
2153 case CREATURE_FAMILY_WASP: // Smack and Sting
2154 if(spell->SpellIconID != 473 && spell->SpellIconID != 110)
2155 continue;
2156 break;
2157 case CREATURE_FAMILY_WIND_SERPENT: // Bite and Lightning Breath
2158 if(spell->SpellIconID != 1680 && spell->SpellIconID != 62)
2159 continue;
2160 break;
2161 case CREATURE_FAMILY_WOLF: // Bite and Furious Howl
2162 if(spell->SpellIconID != 1680 && spell->SpellIconID != 1573)
2163 continue;
2164 break;
2165 case CREATURE_FAMILY_WORM: // Acid Spit and Bite
2166 if(spell->SpellIconID != 636 && spell->SpellIconID != 1680)
2167 continue;
2168 break;
2169 default:
2170 sLog.outError("LoadPetLevelupSpellMap: Unhandled creature family %u", creatureFamily->ID);
2171 continue;
2175 mPetLevelupSpellMap[creatureFamily->ID][spell->spellLevel] = spell->Id;
2176 count++;
2180 sLog.outString();
2181 sLog.outString( ">> Loaded %u pet levelup spells", count );
2184 /// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc
2185 bool SpellMgr::IsSpellValid(SpellEntry const* spellInfo, Player* pl, bool msg)
2187 // not exist
2188 if(!spellInfo)
2189 return false;
2191 bool need_check_reagents = false;
2193 // check effects
2194 for(int i=0; i<3; ++i)
2196 switch(spellInfo->Effect[i])
2198 case 0:
2199 continue;
2201 // craft spell for crafting non-existed item (break client recipes list show)
2202 case SPELL_EFFECT_CREATE_ITEM:
2204 if(!ObjectMgr::GetItemPrototype( spellInfo->EffectItemType[i] ))
2206 if(msg)
2208 if(pl)
2209 ChatHandler(pl).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->EffectItemType[i]);
2210 else
2211 sLog.outErrorDb("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->EffectItemType[i]);
2213 return false;
2216 need_check_reagents = true;
2217 break;
2219 case SPELL_EFFECT_LEARN_SPELL:
2221 SpellEntry const* spellInfo2 = sSpellStore.LookupEntry(spellInfo->EffectTriggerSpell[i]);
2222 if( !IsSpellValid(spellInfo2,pl,msg) )
2224 if(msg)
2226 if(pl)
2227 ChatHandler(pl).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[i]);
2228 else
2229 sLog.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo->Id,spellInfo->EffectTriggerSpell[i]);
2231 return false;
2233 break;
2238 if(need_check_reagents)
2240 for(int j = 0; j < 8; ++j)
2242 if(spellInfo->Reagent[j] > 0 && !ObjectMgr::GetItemPrototype( spellInfo->Reagent[j] ))
2244 if(msg)
2246 if(pl)
2247 ChatHandler(pl).PSendSysMessage("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->Reagent[j]);
2248 else
2249 sLog.outErrorDb("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo->Id,spellInfo->Reagent[j]);
2251 return false;
2256 return true;
2259 uint8 GetSpellAllowedInLocationError(SpellEntry const *spellInfo,uint32 map_id,uint32 zone_id,uint32 area_id)
2261 // normal case
2262 if( spellInfo->AreaGroupId > 0)
2264 bool found = false;
2266 AreaGroupEntry const* groupEntry = sAreaGroupStore.LookupEntry(spellInfo->AreaGroupId);
2267 if(groupEntry)
2269 for (uint8 i=0; i<7; i++)
2270 if( groupEntry->AreaId[i] == zone_id || groupEntry->AreaId[i] == area_id )
2271 found = true;
2274 if(!found)
2275 return SPELL_FAILED_INCORRECT_AREA;
2278 // elixirs (all area dependent elixirs have family SPELLFAMILY_POTION, use this for speedup)
2279 if(spellInfo->SpellFamilyName==SPELLFAMILY_POTION)
2281 if(uint32 mask = spellmgr.GetSpellElixirMask(spellInfo->Id))
2283 if(mask & ELIXIR_BATTLE_MASK)
2285 if(spellInfo->Id==45373) // Bloodberry Elixir
2286 return zone_id==4075 ? 0 : SPELL_FAILED_REQUIRES_AREA;
2288 if(mask & ELIXIR_UNSTABLE_MASK)
2290 // in the Blade's Edge Mountains Plateaus and Gruul's Lair.
2291 return zone_id ==3522 || map_id==565 ? 0 : SPELL_FAILED_INCORRECT_AREA;
2293 if(mask & ELIXIR_SHATTRATH_MASK)
2295 // in Tempest Keep, Serpentshrine Cavern, Caverns of Time: Mount Hyjal, Black Temple, Sunwell Plateau
2296 if(zone_id ==3607 || map_id==534 || map_id==564 || zone_id==4075)
2297 return 0;
2299 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2300 if(!mapEntry)
2301 return SPELL_FAILED_INCORRECT_AREA;
2303 return mapEntry->multimap_id==206 ? 0 : SPELL_FAILED_INCORRECT_AREA;
2306 // elixirs not have another limitations
2307 return 0;
2311 // special cases zone check (maps checked by multimap common id)
2312 switch(spellInfo->Id)
2314 case 41618: // Bottled Nethergon Energy
2315 case 41620: // Bottled Nethergon Vapor
2317 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2318 if(!mapEntry)
2319 return SPELL_FAILED_INCORRECT_AREA;
2321 return mapEntry->multimap_id==206 ? 0 : SPELL_FAILED_REQUIRES_AREA;
2323 case 41617: // Cenarion Mana Salve
2324 case 41619: // Cenarion Healing Salve
2326 MapEntry const* mapEntry = sMapStore.LookupEntry(map_id);
2327 if(!mapEntry)
2328 return SPELL_FAILED_INCORRECT_AREA;
2330 return mapEntry->multimap_id==207 ? 0 : SPELL_FAILED_REQUIRES_AREA;
2332 case 40216: // Dragonmaw Illusion
2333 case 42016: // Dragonmaw Illusion
2334 return area_id == 3759 || area_id == 3966 || area_id == 3939 ? 0 : SPELL_FAILED_INCORRECT_AREA;
2335 case 51721: // Dominion Over Acherus
2336 case 54055: // Dominion Over Acherus
2337 return area_id == 4281 || area_id == 4342 ? 0 : SPELL_FAILED_INCORRECT_AREA;
2340 return 0;
2343 void SpellMgr::LoadSkillLineAbilityMap()
2345 mSkillLineAbilityMap.clear();
2347 uint32 count = 0;
2349 for (uint32 i = 0; i < sSkillLineAbilityStore.GetNumRows(); i++)
2351 SkillLineAbilityEntry const *SkillInfo = sSkillLineAbilityStore.LookupEntry(i);
2352 if(!SkillInfo)
2353 continue;
2355 mSkillLineAbilityMap.insert(SkillLineAbilityMap::value_type(SkillInfo->spellId,SkillInfo));
2356 ++count;
2359 sLog.outString();
2360 sLog.outString(">> Loaded %u SkillLineAbility MultiMap", count);
2363 DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellEntry const* spellproto, bool triggered)
2365 // Explicit Diminishing Groups
2366 switch(spellproto->SpellFamilyName)
2368 case SPELLFAMILY_MAGE:
2370 // Polymorph
2371 if ((spellproto->SpellFamilyFlags & 0x00001000000LL) && spellproto->EffectApplyAuraName[0]==SPELL_AURA_MOD_CONFUSE)
2372 return DIMINISHING_POLYMORPH;
2373 break;
2375 case SPELLFAMILY_ROGUE:
2377 // Kidney Shot
2378 if (spellproto->SpellFamilyFlags & 0x00000200000LL)
2379 return DIMINISHING_KIDNEYSHOT;
2380 // Blind
2381 else if (spellproto->SpellFamilyFlags & 0x00001000000LL)
2382 return DIMINISHING_BLIND_CYCLONE;
2383 break;
2385 case SPELLFAMILY_WARLOCK:
2387 // Death Coil
2388 if (spellproto->SpellFamilyFlags & 0x00000080000LL)
2389 return DIMINISHING_DEATHCOIL;
2390 // Fear
2391 else if (spellproto->SpellFamilyFlags & 0x40840000000LL)
2392 return DIMINISHING_WARLOCK_FEAR;
2393 // Curses/etc
2394 else if (spellproto->SpellFamilyFlags & 0x00080000000LL)
2395 return DIMINISHING_LIMITONLY;
2396 break;
2398 case SPELLFAMILY_DRUID:
2400 // Cyclone
2401 if (spellproto->SpellFamilyFlags & 0x02000000000LL)
2402 return DIMINISHING_BLIND_CYCLONE;
2403 break;
2405 case SPELLFAMILY_WARRIOR:
2407 // Hamstring - limit duration to 10s in PvP
2408 if (spellproto->SpellFamilyFlags & 0x00000000002LL)
2409 return DIMINISHING_LIMITONLY;
2410 break;
2412 default:
2413 break;
2416 // Get by mechanic
2417 for (uint8 i=0;i<3;++i)
2419 if (spellproto->Mechanic == MECHANIC_STUN || spellproto->EffectMechanic[i] == MECHANIC_STUN)
2420 return triggered ? DIMINISHING_TRIGGER_STUN : DIMINISHING_CONTROL_STUN;
2421 else if (spellproto->Mechanic == MECHANIC_SLEEP || spellproto->EffectMechanic[i] == MECHANIC_SLEEP)
2422 return DIMINISHING_SLEEP;
2423 else if (spellproto->Mechanic == MECHANIC_ROOT || spellproto->EffectMechanic[i] == MECHANIC_ROOT)
2424 return triggered ? DIMINISHING_TRIGGER_ROOT : DIMINISHING_CONTROL_ROOT;
2425 else if (spellproto->Mechanic == MECHANIC_FEAR || spellproto->EffectMechanic[i] == MECHANIC_FEAR)
2426 return DIMINISHING_FEAR;
2427 else if (spellproto->Mechanic == MECHANIC_CHARM || spellproto->EffectMechanic[i] == MECHANIC_CHARM)
2428 return DIMINISHING_CHARM;
2429 else if (spellproto->Mechanic == MECHANIC_SILENCE || spellproto->EffectMechanic[i] == MECHANIC_SILENCE)
2430 return DIMINISHING_SILENCE;
2431 else if (spellproto->Mechanic == MECHANIC_DISARM || spellproto->EffectMechanic[i] == MECHANIC_DISARM)
2432 return DIMINISHING_DISARM;
2433 else if (spellproto->Mechanic == MECHANIC_FREEZE || spellproto->EffectMechanic[i] == MECHANIC_FREEZE)
2434 return DIMINISHING_FREEZE;
2435 else if (spellproto->Mechanic == MECHANIC_KNOCKOUT|| spellproto->EffectMechanic[i] == MECHANIC_KNOCKOUT ||
2436 spellproto->Mechanic == MECHANIC_SAPPED || spellproto->EffectMechanic[i] == MECHANIC_SAPPED)
2437 return DIMINISHING_KNOCKOUT;
2438 else if (spellproto->Mechanic == MECHANIC_BANISH || spellproto->EffectMechanic[i] == MECHANIC_BANISH)
2439 return DIMINISHING_BANISH;
2442 return DIMINISHING_NONE;
2445 bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group)
2447 switch(group)
2449 case DIMINISHING_CONTROL_STUN:
2450 case DIMINISHING_TRIGGER_STUN:
2451 case DIMINISHING_KIDNEYSHOT:
2452 case DIMINISHING_SLEEP:
2453 case DIMINISHING_CONTROL_ROOT:
2454 case DIMINISHING_TRIGGER_ROOT:
2455 case DIMINISHING_FEAR:
2456 case DIMINISHING_WARLOCK_FEAR:
2457 case DIMINISHING_CHARM:
2458 case DIMINISHING_POLYMORPH:
2459 case DIMINISHING_FREEZE:
2460 case DIMINISHING_KNOCKOUT:
2461 case DIMINISHING_BLIND_CYCLONE:
2462 case DIMINISHING_BANISH:
2463 case DIMINISHING_LIMITONLY:
2464 return true;
2466 return false;
2469 DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group)
2471 switch(group)
2473 case DIMINISHING_BLIND_CYCLONE:
2474 case DIMINISHING_CONTROL_STUN:
2475 case DIMINISHING_TRIGGER_STUN:
2476 case DIMINISHING_KIDNEYSHOT:
2477 return DRTYPE_ALL;
2478 case DIMINISHING_SLEEP:
2479 case DIMINISHING_CONTROL_ROOT:
2480 case DIMINISHING_TRIGGER_ROOT:
2481 case DIMINISHING_FEAR:
2482 case DIMINISHING_CHARM:
2483 case DIMINISHING_POLYMORPH:
2484 case DIMINISHING_SILENCE:
2485 case DIMINISHING_DISARM:
2486 case DIMINISHING_DEATHCOIL:
2487 case DIMINISHING_FREEZE:
2488 case DIMINISHING_BANISH:
2489 case DIMINISHING_WARLOCK_FEAR:
2490 case DIMINISHING_KNOCKOUT:
2491 return DRTYPE_PLAYER;
2494 return DRTYPE_NONE;