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
20 #include "ObjectMgr.h"
21 #include "SpellAuraDefines.h"
22 #include "ProgressBar.h"
23 #include "DBCStores.h"
27 #include "BattleGroundMgr.h"
37 SpellMgr
& SpellMgr::Instance()
39 static SpellMgr spellMgr
;
43 int32
GetSpellDuration(SpellEntry
const *spellInfo
)
47 SpellDurationEntry
const *du
= sSpellDurationStore
.LookupEntry(spellInfo
->DurationIndex
);
50 return (du
->Duration
[0] == -1) ? -1 : abs(du
->Duration
[0]);
53 int32
GetSpellMaxDuration(SpellEntry
const *spellInfo
)
57 SpellDurationEntry
const *du
= sSpellDurationStore
.LookupEntry(spellInfo
->DurationIndex
);
60 return (du
->Duration
[2] == -1) ? -1 : abs(du
->Duration
[2]);
63 uint32
GetSpellCastTime(SpellEntry
const* spellInfo
, Spell
const* spell
)
65 SpellCastTimesEntry
const *spellCastTimeEntry
= sSpellCastTimesStore
.LookupEntry(spellInfo
->CastingTimeIndex
);
67 // not all spells have cast time index and this is all is pasiive abilities
68 if(!spellCastTimeEntry
)
71 int32 castTime
= spellCastTimeEntry
->CastTime
;
75 if(Player
* modOwner
= spell
->GetCaster()->GetSpellModOwner())
76 modOwner
->ApplySpellMod(spellInfo
->Id
, SPELLMOD_CASTING_TIME
, castTime
, spell
);
78 if( !(spellInfo
->Attributes
& (SPELL_ATTR_UNK4
|SPELL_ATTR_UNK5
)) )
79 castTime
= int32(castTime
* spell
->GetCaster()->GetFloatValue(UNIT_MOD_CAST_SPEED
));
82 if (spell
->IsRangedSpell() && !spell
->IsAutoRepeat())
83 castTime
= int32(castTime
* spell
->GetCaster()->m_modAttackSpeedPct
[RANGED_ATTACK
]);
87 if (spellInfo
->Attributes
& SPELL_ATTR_RANGED
&& (!spell
|| !(spell
->IsAutoRepeat())))
90 return (castTime
> 0) ? uint32(castTime
) : 0;
93 bool IsPassiveSpell(uint32 spellId
)
95 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
98 return (spellInfo
->Attributes
& SPELL_ATTR_PASSIVE
) != 0;
101 bool IsNoStackAuraDueToAura(uint32 spellId_1
, uint32 effIndex_1
, uint32 spellId_2
, uint32 effIndex_2
)
103 SpellEntry
const *spellInfo_1
= sSpellStore
.LookupEntry(spellId_1
);
104 SpellEntry
const *spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
105 if(!spellInfo_1
|| !spellInfo_2
) return false;
106 if(spellInfo_1
->Id
== spellId_2
) return false;
108 if (spellInfo_1
->Effect
[effIndex_1
] != spellInfo_2
->Effect
[effIndex_2
] ||
109 spellInfo_1
->EffectItemType
[effIndex_1
] != spellInfo_2
->EffectItemType
[effIndex_2
] ||
110 spellInfo_1
->EffectMiscValue
[effIndex_1
] != spellInfo_2
->EffectMiscValue
[effIndex_2
] ||
111 spellInfo_1
->EffectApplyAuraName
[effIndex_1
] != spellInfo_2
->EffectApplyAuraName
[effIndex_2
])
117 int32
CompareAuraRanks(uint32 spellId_1
, uint32 effIndex_1
, uint32 spellId_2
, uint32 effIndex_2
)
119 SpellEntry
const*spellInfo_1
= sSpellStore
.LookupEntry(spellId_1
);
120 SpellEntry
const*spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
121 if(!spellInfo_1
|| !spellInfo_2
) return 0;
122 if (spellId_1
== spellId_2
) return 0;
124 int32 diff
= spellInfo_1
->EffectBasePoints
[effIndex_1
] - spellInfo_2
->EffectBasePoints
[effIndex_2
];
125 if (spellInfo_1
->CalculateSimpleValue(effIndex_1
) < 0 && spellInfo_2
->CalculateSimpleValue(effIndex_2
) < 0)
130 SpellSpecific
GetSpellSpecific(uint32 spellId
)
132 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
136 switch(spellInfo
->SpellFamilyName
)
138 case SPELLFAMILY_MAGE
:
140 // family flags 18(Molten), 25(Frost/Ice), 28(Mage)
141 if (spellInfo
->SpellFamilyFlags
& 0x12040000)
142 return SPELL_MAGE_ARMOR
;
144 if ((spellInfo
->SpellFamilyFlags
& 0x1000000) && spellInfo
->EffectApplyAuraName
[0]==SPELL_AURA_MOD_CONFUSE
)
145 return SPELL_MAGE_POLYMORPH
;
149 case SPELLFAMILY_WARRIOR
:
151 if (spellInfo
->SpellFamilyFlags
& 0x00008000010000LL
)
152 return SPELL_POSITIVE_SHOUT
;
156 case SPELLFAMILY_WARLOCK
:
158 // only warlock curses have this
159 if (spellInfo
->Dispel
== DISPEL_CURSE
)
162 // Warlock (Demon Armor | Demon Skin | Fel Armor)
163 if (spellInfo
->SpellFamilyFlags
& 0x2000002000000000LL
|| spellInfo
->SpellFamilyFlags2
& 0x00000010)
164 return SPELL_WARLOCK_ARMOR
;
168 case SPELLFAMILY_HUNTER
:
170 // only hunter stings have this
171 if (spellInfo
->Dispel
== DISPEL_POISON
)
174 // only hunter aspects have this (but not all aspects in hunter family)
175 if( spellInfo
->SpellFamilyFlags
& 0x0044000000380000LL
|| spellInfo
->SpellFamilyFlags2
& 0x00003010)
178 if( spellInfo
->SpellFamilyFlags2
& 0x00000002 )
179 return SPELL_TRACKER
;
183 case SPELLFAMILY_PALADIN
:
185 if (IsSealSpell(spellInfo
))
188 if (spellInfo
->SpellFamilyFlags
& 0x0000000011010002LL
)
189 return SPELL_BLESSING
;
191 if ((spellInfo
->SpellFamilyFlags
& 0x00000820180400LL
) && (spellInfo
->AttributesEx3
& 0x200))
192 return SPELL_JUDGEMENT
;
194 for (int i
= 0; i
< 3; ++i
)
196 // only paladin auras have this (for palaldin class family)
197 if (spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AREA_AURA_RAID
)
202 case SPELLFAMILY_SHAMAN
:
204 if (IsElementalShield(spellInfo
))
205 return SPELL_ELEMENTAL_SHIELD
;
210 case SPELLFAMILY_POTION
:
211 return spellmgr
.GetSpellElixirSpecific(spellInfo
->Id
);
213 case SPELLFAMILY_DEATHKNIGHT
:
214 if ((spellInfo
->Attributes
& 0x10) && (spellInfo
->AttributesEx2
& 0x10) && (spellInfo
->AttributesEx4
& 0x200000))
215 return SPELL_PRESENCE
;
219 // elixirs can have different families, but potion most ofc.
220 if(SpellSpecific sp
= spellmgr
.GetSpellElixirSpecific(spellInfo
->Id
))
226 bool IsSingleFromSpellSpecificPerCaster(SpellSpecific spellSpec1
,SpellSpecific spellSpec2
)
237 case SPELL_WARLOCK_ARMOR
:
238 case SPELL_MAGE_ARMOR
:
239 case SPELL_MAGE_POLYMORPH
:
240 case SPELL_POSITIVE_SHOUT
:
241 case SPELL_JUDGEMENT
:
243 return spellSpec1
==spellSpec2
;
244 case SPELL_BATTLE_ELIXIR
:
245 return spellSpec2
==SPELL_BATTLE_ELIXIR
246 || spellSpec2
==SPELL_FLASK_ELIXIR
;
247 case SPELL_GUARDIAN_ELIXIR
:
248 return spellSpec2
==SPELL_GUARDIAN_ELIXIR
249 || spellSpec2
==SPELL_FLASK_ELIXIR
;
250 case SPELL_FLASK_ELIXIR
:
251 return spellSpec2
==SPELL_BATTLE_ELIXIR
252 || spellSpec2
==SPELL_GUARDIAN_ELIXIR
253 || spellSpec2
==SPELL_FLASK_ELIXIR
;
259 bool IsSingleFromSpellSpecificRanksPerTarget(SpellSpecific spellId_spec
, SpellSpecific i_spellId_spec
)
266 return spellId_spec
==i_spellId_spec
;
272 bool IsPositiveTarget(uint32 targetA
, uint32 targetB
)
274 // non-positive targets
277 case TARGET_CHAIN_DAMAGE
:
278 case TARGET_ALL_ENEMY_IN_AREA
:
279 case TARGET_ALL_ENEMY_IN_AREA_INSTANT
:
280 case TARGET_IN_FRONT_OF_CASTER
:
281 case TARGET_ALL_ENEMY_IN_AREA_CHANNELED
:
282 case TARGET_CURRENT_ENEMY_COORDINATES
:
283 case TARGET_SINGLE_ENEMY
:
285 case TARGET_CASTER_COORDINATES
:
286 return (targetB
== TARGET_ALL_PARTY
|| targetB
== TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER
);
291 return IsPositiveTarget(targetB
, 0);
295 bool IsPositiveEffect(uint32 spellId
, uint32 effIndex
)
297 SpellEntry
const *spellproto
= sSpellStore
.LookupEntry(spellId
);
298 if (!spellproto
) return false;
302 case 28441: // not positive dummy spell
303 case 37675: // Chaos Blast
307 switch(spellproto
->Effect
[effIndex
])
309 // always positive effects (check before target checks that provided non-positive result in some case for positive effects)
310 case SPELL_EFFECT_HEAL
:
311 case SPELL_EFFECT_LEARN_SPELL
:
312 case SPELL_EFFECT_SKILL_STEP
:
313 case SPELL_EFFECT_HEAL_PCT
:
314 case SPELL_EFFECT_ENERGIZE_PCT
:
317 // non-positive aura use
318 case SPELL_EFFECT_APPLY_AURA
:
319 case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
:
321 switch(spellproto
->EffectApplyAuraName
[effIndex
])
323 case SPELL_AURA_DUMMY
:
325 // dummy aura can be positive or negative dependent from casted spell
326 switch(spellproto
->Id
)
328 case 13139: // net-o-matic special effect
329 case 23445: // evil twin
330 case 35679: // Protectorate Demolitionist
331 case 38637: // Nether Exhaustion (red)
332 case 38638: // Nether Exhaustion (green)
333 case 38639: // Nether Exhaustion (blue)
339 case SPELL_AURA_MOD_STAT
:
340 case SPELL_AURA_MOD_DAMAGE_DONE
: // dependent from bas point sign (negative -> negative)
341 case SPELL_AURA_MOD_HEALING_DONE
:
343 if(spellproto
->CalculateSimpleValue(effIndex
) < 0)
347 case SPELL_AURA_ADD_TARGET_TRIGGER
:
349 case SPELL_AURA_PERIODIC_TRIGGER_SPELL
:
350 if(spellId
!= spellproto
->EffectTriggerSpell
[effIndex
])
352 uint32 spellTriggeredId
= spellproto
->EffectTriggerSpell
[effIndex
];
353 SpellEntry
const *spellTriggeredProto
= sSpellStore
.LookupEntry(spellTriggeredId
);
355 if(spellTriggeredProto
)
357 // non-positive targets of main spell return early
358 for(int i
= 0; i
< 3; ++i
)
360 // if non-positive trigger cast targeted to positive target this main cast is non-positive
361 // this will place this spell auras as debuffs
362 if(IsPositiveTarget(spellTriggeredProto
->EffectImplicitTargetA
[effIndex
],spellTriggeredProto
->EffectImplicitTargetB
[effIndex
]) && !IsPositiveEffect(spellTriggeredId
,i
))
368 case SPELL_AURA_PROC_TRIGGER_SPELL
:
369 // many positive auras have negative triggered spells at damage for example and this not make it negative (it can be canceled for example)
371 case SPELL_AURA_MOD_STUN
: //have positive and negative spells, we can't sort its correctly at this moment.
372 if(effIndex
==0 && spellproto
->Effect
[1]==0 && spellproto
->Effect
[2]==0)
373 return false; // but all single stun aura spells is negative
376 if(spellproto
->Id
== 17624)
379 case SPELL_AURA_MOD_ROOT
:
380 case SPELL_AURA_MOD_SILENCE
:
381 case SPELL_AURA_GHOST
:
382 case SPELL_AURA_PERIODIC_LEECH
:
383 case SPELL_AURA_MOD_PACIFY_SILENCE
:
384 case SPELL_AURA_MOD_STALKED
:
385 case SPELL_AURA_PERIODIC_DAMAGE_PERCENT
:
387 case SPELL_AURA_PERIODIC_DAMAGE
: // used in positive spells also.
388 // part of negative spell if casted at self (prevent cancel)
389 if(spellproto
->EffectImplicitTargetA
[effIndex
] == TARGET_SELF
)
392 case SPELL_AURA_MOD_DECREASE_SPEED
: // used in positive spells also
393 // part of positive spell if casted at self
394 if(spellproto
->EffectImplicitTargetA
[effIndex
] != TARGET_SELF
)
396 // but not this if this first effect (don't found batter check)
397 if(spellproto
->Attributes
& 0x4000000 && effIndex
==0)
400 case SPELL_AURA_TRANSFORM
:
401 // some spells negative
402 switch(spellproto
->Id
)
404 case 36897: // Transporter Malfunction (race mutation to horde)
405 case 36899: // Transporter Malfunction (race mutation to alliance)
409 case SPELL_AURA_MOD_SCALE
:
410 // some spells negative
411 switch(spellproto
->Id
)
413 case 36900: // Soul Split: Evil!
414 case 36901: // Soul Split: Good
415 case 36893: // Transporter Malfunction (decrease size case)
416 case 36895: // Transporter Malfunction (increase size case)
420 case SPELL_AURA_MECHANIC_IMMUNITY
:
422 // non-positive immunities
423 switch(spellproto
->EffectMiscValue
[effIndex
])
425 case MECHANIC_BANDAGE
:
426 case MECHANIC_SHIELD
:
428 case MECHANIC_INVULNERABILITY
:
434 case SPELL_AURA_ADD_FLAT_MODIFIER
: // mods
435 case SPELL_AURA_ADD_PCT_MODIFIER
:
438 switch(spellproto
->EffectMiscValue
[effIndex
])
440 case SPELLMOD_COST
: // dependent from bas point sign (negative -> positive)
441 if(spellproto
->CalculateSimpleValue(effIndex
) > 0)
448 case SPELL_AURA_MOD_HEALING_PCT
:
449 if(spellproto
->CalculateSimpleValue(effIndex
) < 0)
452 case SPELL_AURA_MOD_SKILL
:
453 if(spellproto
->CalculateSimpleValue(effIndex
) < 0)
456 case SPELL_AURA_FORCE_REACTION
:
457 if(spellproto
->Id
==42792) // Recently Dropped Flag (prevent cancel)
469 // non-positive targets
470 if(!IsPositiveTarget(spellproto
->EffectImplicitTargetA
[effIndex
],spellproto
->EffectImplicitTargetB
[effIndex
]))
473 // AttributesEx check
474 if(spellproto
->AttributesEx
& SPELL_ATTR_EX_NEGATIVE
)
481 bool IsPositiveSpell(uint32 spellId
)
483 SpellEntry
const *spellproto
= sSpellStore
.LookupEntry(spellId
);
484 if (!spellproto
) return false;
486 // spells with atleast one negative effect are considered negative
487 // some self-applied spells have negative effects but in self casting case negative check ignored.
488 for (int i
= 0; i
< 3; ++i
)
489 if (!IsPositiveEffect(spellId
, i
))
494 bool IsSingleTargetSpell(SpellEntry
const *spellInfo
)
496 // all other single target spells have if it has AttributesEx5
497 if ( spellInfo
->AttributesEx5
& SPELL_ATTR_EX5_SINGLE_TARGET_SPELL
)
500 // TODO - need found Judgements rule
501 switch(GetSpellSpecific(spellInfo
->Id
))
503 case SPELL_JUDGEMENT
:
509 // single target triggered spell.
510 // Not real client side single target spell, but it' not triggered until prev. aura expired.
511 // This is allow store it in single target spells list for caster for spell proc checking
512 if(spellInfo
->Id
==38324) // Regeneration (triggered by 38299 (HoTs on Heals))
518 bool IsSingleTargetSpells(SpellEntry
const *spellInfo1
, SpellEntry
const *spellInfo2
)
520 // TODO - need better check
521 // Equal icon and spellfamily
522 if( spellInfo1
->SpellFamilyName
== spellInfo2
->SpellFamilyName
&&
523 spellInfo1
->SpellIconID
== spellInfo2
->SpellIconID
)
526 // TODO - need found Judgements rule
527 SpellSpecific spec1
= GetSpellSpecific(spellInfo1
->Id
);
528 // spell with single target specific types
531 case SPELL_JUDGEMENT
:
532 case SPELL_MAGE_POLYMORPH
:
533 if(GetSpellSpecific(spellInfo2
->Id
) == spec1
)
543 bool IsAuraAddedBySpell(uint32 auraType
, uint32 spellId
)
545 SpellEntry
const *spellproto
= sSpellStore
.LookupEntry(spellId
);
546 if (!spellproto
) return false;
548 for (int i
= 0; i
< 3; ++i
)
549 if (spellproto
->EffectApplyAuraName
[i
] == auraType
)
554 SpellCastResult
GetErrorAtShapeshiftedCast (SpellEntry
const *spellInfo
, uint32 form
)
556 // talents that learn spells can have stance requirements that need ignore
557 // (this requirement only for client-side stance show in talent description)
558 if( GetTalentSpellCost(spellInfo
->Id
) > 0 &&
559 (spellInfo
->Effect
[0]==SPELL_EFFECT_LEARN_SPELL
|| spellInfo
->Effect
[1]==SPELL_EFFECT_LEARN_SPELL
|| spellInfo
->Effect
[2]==SPELL_EFFECT_LEARN_SPELL
) )
560 return SPELL_CAST_OK
;
562 uint32 stanceMask
= (form
? 1 << (form
- 1) : 0);
564 if (stanceMask
& spellInfo
->StancesNot
) // can explicitly not be casted in this stance
565 return SPELL_FAILED_NOT_SHAPESHIFT
;
567 if (stanceMask
& spellInfo
->Stances
) // can explicitly be casted in this stance
568 return SPELL_CAST_OK
;
570 bool actAsShifted
= false;
573 SpellShapeshiftEntry
const *shapeInfo
= sSpellShapeshiftStore
.LookupEntry(form
);
576 sLog
.outError("GetErrorAtShapeshiftedCast: unknown shapeshift %u", form
);
577 return SPELL_CAST_OK
;
579 actAsShifted
= !(shapeInfo
->flags1
& 1); // shapeshift acts as normal form for spells
584 if (spellInfo
->Attributes
& SPELL_ATTR_NOT_SHAPESHIFT
) // not while shapeshifted
585 return SPELL_FAILED_NOT_SHAPESHIFT
;
586 else if (spellInfo
->Stances
!= 0) // needs other shapeshift
587 return SPELL_FAILED_ONLY_SHAPESHIFT
;
592 if(!(spellInfo
->AttributesEx2
& SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT
) && spellInfo
->Stances
!= 0)
593 return SPELL_FAILED_ONLY_SHAPESHIFT
;
596 return SPELL_CAST_OK
;
599 void SpellMgr::LoadSpellTargetPositions()
601 mSpellTargetPositions
.clear(); // need for reload case
606 QueryResult
*result
= WorldDatabase
.Query("SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position");
615 sLog
.outString( ">> Loaded %u spell target coordinates", count
);
619 barGoLink
bar( result
->GetRowCount() );
623 Field
*fields
= result
->Fetch();
629 uint32 Spell_ID
= fields
[0].GetUInt32();
631 SpellTargetPosition st
;
633 st
.target_mapId
= fields
[1].GetUInt32();
634 st
.target_X
= fields
[2].GetFloat();
635 st
.target_Y
= fields
[3].GetFloat();
636 st
.target_Z
= fields
[4].GetFloat();
637 st
.target_Orientation
= fields
[5].GetFloat();
639 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(Spell_ID
);
642 sLog
.outErrorDb("Spell (ID:%u) listed in `spell_target_position` does not exist.",Spell_ID
);
647 for(int i
= 0; i
< 3; ++i
)
649 if( spellInfo
->EffectImplicitTargetA
[i
]==TARGET_TABLE_X_Y_Z_COORDINATES
|| spellInfo
->EffectImplicitTargetB
[i
]==TARGET_TABLE_X_Y_Z_COORDINATES
)
657 sLog
.outErrorDb("Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_TABLE_X_Y_Z_COORDINATES (17).",Spell_ID
);
661 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(st
.target_mapId
);
664 sLog
.outErrorDb("Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`.",Spell_ID
,st
.target_mapId
);
668 if(st
.target_X
==0 && st
.target_Y
==0 && st
.target_Z
==0)
670 sLog
.outErrorDb("Spell (ID:%u) target coordinates not provided.",Spell_ID
);
674 mSpellTargetPositions
[Spell_ID
] = st
;
676 } while( result
->NextRow() );
681 sLog
.outString( ">> Loaded %u spell teleport coordinates", count
);
684 void SpellMgr::LoadSpellAffects()
686 mSpellAffectMap
.clear(); // need for reload case
691 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, effectId, SpellClassMask0, SpellClassMask1, SpellClassMask2 FROM spell_affect");
700 sLog
.outString( ">> Loaded %u spell affect definitions", count
);
704 barGoLink
bar( result
->GetRowCount() );
708 Field
*fields
= result
->Fetch();
712 uint16 entry
= fields
[0].GetUInt16();
713 uint8 effectId
= fields
[1].GetUInt8();
715 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(entry
);
719 sLog
.outErrorDb("Spell %u listed in `spell_affect` does not exist", entry
);
725 sLog
.outErrorDb("Spell %u listed in `spell_affect` have invalid effect index (%u)", entry
,effectId
);
729 if( spellInfo
->Effect
[effectId
] != SPELL_EFFECT_APPLY_AURA
||
730 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_FLAT_MODIFIER
&&
731 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_PCT_MODIFIER
&&
732 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_TARGET_TRIGGER
)
734 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
);
738 SpellAffectEntry affect
;
739 affect
.SpellClassMask
[0] = fields
[2].GetUInt32();
740 affect
.SpellClassMask
[1] = fields
[3].GetUInt32();
741 affect
.SpellClassMask
[2] = fields
[4].GetUInt32();
743 // Spell.dbc have own data
744 uint32
const *ptr
= 0;
747 case 0: ptr
= &spellInfo
->EffectSpellClassMaskA
[0]; break;
748 case 1: ptr
= &spellInfo
->EffectSpellClassMaskB
[0]; break;
749 case 2: ptr
= &spellInfo
->EffectSpellClassMaskC
[0]; break;
753 if(ptr
[0] == affect
.SpellClassMask
[0] || ptr
[1] == affect
.SpellClassMask
[1] || ptr
[2] == affect
.SpellClassMask
[2])
756 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
);
760 mSpellAffectMap
[(entry
<<8) + effectId
] = affect
;
763 } while( result
->NextRow() );
768 sLog
.outString( ">> Loaded %u custom spell affect definitions", count
);
770 for (uint32 id
= 0; id
< sSpellStore
.GetNumRows(); ++id
)
772 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(id
);
776 for (int effectId
= 0; effectId
< 3; ++effectId
)
778 if( spellInfo
->Effect
[effectId
] != SPELL_EFFECT_APPLY_AURA
||
779 (spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_FLAT_MODIFIER
&&
780 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_PCT_MODIFIER
&&
781 spellInfo
->EffectApplyAuraName
[effectId
] != SPELL_AURA_ADD_TARGET_TRIGGER
) )
784 uint32
const *ptr
= 0;
787 case 0: ptr
= &spellInfo
->EffectSpellClassMaskA
[0]; break;
788 case 1: ptr
= &spellInfo
->EffectSpellClassMaskB
[0]; break;
789 case 2: ptr
= &spellInfo
->EffectSpellClassMaskC
[0]; break;
793 if(ptr
[0] || ptr
[1] || ptr
[2])
796 if(mSpellAffectMap
.find((id
<<8) + effectId
) != mSpellAffectMap
.end())
799 sLog
.outErrorDb("Spell %u (%s) misses spell_affect for effect %u",id
,spellInfo
->SpellName
[sWorld
.GetDefaultDbcLocale()], effectId
);
804 bool SpellMgr::IsAffectedByMod(SpellEntry
const *spellInfo
, SpellModifier
*mod
) const
806 // false for spellInfo == NULL
807 if (!spellInfo
|| !mod
)
810 SpellEntry
const *affect_spell
= sSpellStore
.LookupEntry(mod
->spellId
);
811 // False if affect_spell == NULL or spellFamily not equal
812 if (!affect_spell
|| affect_spell
->SpellFamilyName
!= spellInfo
->SpellFamilyName
)
816 if (mod
->mask
& spellInfo
->SpellFamilyFlags
||
817 mod
->mask2
& spellInfo
->SpellFamilyFlags2
)
823 void SpellMgr::LoadSpellProcEvents()
825 mSpellProcEventMap
.clear(); // need for reload case
829 // 0 1 2 3 4 5 6 7 8 9 10
830 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
836 sLog
.outString( ">> Loaded %u spell proc event conditions", count
);
840 barGoLink
bar( result
->GetRowCount() );
841 uint32 customProc
= 0;
844 Field
*fields
= result
->Fetch();
848 uint32 entry
= fields
[0].GetUInt32();
850 const SpellEntry
*spell
= sSpellStore
.LookupEntry(entry
);
853 sLog
.outErrorDb("Spell %u listed in `spell_proc_event` does not exist", entry
);
857 SpellProcEventEntry spe
;
859 spe
.schoolMask
= fields
[1].GetUInt32();
860 spe
.spellFamilyName
= fields
[2].GetUInt32();
861 spe
.spellFamilyMask
= (uint64
)fields
[3].GetUInt32()|((uint64
)fields
[4].GetUInt32()<<32);
862 spe
.spellFamilyMask2
= fields
[5].GetUInt32();
863 spe
.procFlags
= fields
[6].GetUInt32();
864 spe
.procEx
= fields
[7].GetUInt32();
865 spe
.ppmRate
= fields
[8].GetFloat();
866 spe
.customChance
= fields
[9].GetFloat();
867 spe
.cooldown
= fields
[10].GetUInt32();
869 mSpellProcEventMap
[entry
] = spe
;
871 if (spell
->procFlags
==0)
873 if (spe
.procFlags
== 0)
875 sLog
.outErrorDb("Spell %u listed in `spell_proc_event` probally not triggered spell", entry
);
881 } while( result
->NextRow() );
887 sLog
.outString( ">> Loaded %u extra spell proc event conditions +%u custom", count
, customProc
);
889 sLog
.outString( ">> Loaded %u extra spell proc event conditions", count
);
892 void SpellMgr::LoadSpellBonusess()
894 mSpellBonusMap
.clear(); // need for reload case
897 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, direct_bonus, dot_bonus, ap_bonus FROM spell_bonus_data");
903 sLog
.outString( ">> Loaded %u spell bonus data", count
);
907 barGoLink
bar( result
->GetRowCount() );
910 Field
*fields
= result
->Fetch();
912 uint32 entry
= fields
[0].GetUInt32();
914 const SpellEntry
*spell
= sSpellStore
.LookupEntry(entry
);
917 sLog
.outErrorDb("Spell %u listed in `spell_bonus_data` does not exist", entry
);
923 sbe
.direct_damage
= fields
[1].GetFloat();
924 sbe
.dot_damage
= fields
[2].GetFloat();
925 sbe
.ap_bonus
= fields
[3].GetFloat();
927 mSpellBonusMap
[entry
] = sbe
;
928 } while( result
->NextRow() );
933 sLog
.outString( ">> Loaded %u extra spell bonus data", count
);
936 bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry
const * spellProcEvent
, uint32 EventProcFlag
, SpellEntry
const * procSpell
, uint32 procFlags
, uint32 procExtra
, bool active
)
939 uint32 procEvent_procEx
= PROC_EX_NONE
;
941 // check prockFlags for condition
942 if((procFlags
& EventProcFlag
) == 0)
945 // Always trigger for this
946 if (EventProcFlag
& (PROC_FLAG_KILLED
| PROC_FLAG_KILL
| PROC_FLAG_ON_TRAP_ACTIVATION
))
949 if (spellProcEvent
) // Exist event data
952 procEvent_procEx
= spellProcEvent
->procEx
;
954 // For melee triggers
955 if (procSpell
== NULL
)
957 // Check (if set) for school (melee attack have Normal school)
958 if(spellProcEvent
->schoolMask
&& (spellProcEvent
->schoolMask
& SPELL_SCHOOL_MASK_NORMAL
) == 0)
961 else // For spells need check school/spell family/family mask
963 // Check (if set) for school
964 if(spellProcEvent
->schoolMask
&& (spellProcEvent
->schoolMask
& procSpell
->SchoolMask
) == 0)
967 // Check (if set) for spellFamilyName
968 if(spellProcEvent
->spellFamilyName
&& (spellProcEvent
->spellFamilyName
!= procSpell
->SpellFamilyName
))
971 // spellFamilyName is Ok need check for spellFamilyMask if present
972 if(spellProcEvent
->spellFamilyMask
|| spellProcEvent
->spellFamilyMask2
)
974 if ((spellProcEvent
->spellFamilyMask
& procSpell
->SpellFamilyFlags
) == 0 &&
975 (spellProcEvent
->spellFamilyMask2
& procSpell
->SpellFamilyFlags2
) == 0)
977 active
= true; // Spell added manualy -> so its active spell
981 // Check for extra req (if none) and hit/crit
982 if (procEvent_procEx
== PROC_EX_NONE
)
984 // No extra req, so can trigger only for active (damage/healing present) and hit/crit
985 if((procExtra
& (PROC_EX_NORMAL_HIT
|PROC_EX_CRITICAL_HIT
)) && active
)
988 else // Passive spells hits here only if resist/reflect/immune/evade
990 // Exist req for PROC_EX_EX_TRIGGER_ALWAYS
991 if (procEvent_procEx
& PROC_EX_EX_TRIGGER_ALWAYS
)
993 // Passive spells can`t trigger if need hit
994 if ((procEvent_procEx
& PROC_EX_NORMAL_HIT
) && !active
)
996 // Check Extra Requirement like (hit/crit/miss/resist/parry/dodge/block/immune/reflect/absorb and other)
997 if (procEvent_procEx
& procExtra
)
1003 void SpellMgr::LoadSpellElixirs()
1005 mSpellElixirs
.clear(); // need for reload case
1010 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, mask FROM spell_elixir");
1019 sLog
.outString( ">> Loaded %u spell elixir definitions", count
);
1023 barGoLink
bar( result
->GetRowCount() );
1027 Field
*fields
= result
->Fetch();
1031 uint16 entry
= fields
[0].GetUInt16();
1032 uint8 mask
= fields
[1].GetUInt8();
1034 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(entry
);
1038 sLog
.outErrorDb("Spell %u listed in `spell_elixir` does not exist", entry
);
1042 mSpellElixirs
[entry
] = mask
;
1045 } while( result
->NextRow() );
1050 sLog
.outString( ">> Loaded %u spell elixir definitions", count
);
1053 void SpellMgr::LoadSpellThreats()
1055 sSpellThreatStore
.Free(); // for reload
1057 sSpellThreatStore
.Load();
1059 sLog
.outString( ">> Loaded %u aggro generating spells", sSpellThreatStore
.RecordCount
);
1063 bool SpellMgr::IsRankSpellDueToSpell(SpellEntry
const *spellInfo_1
,uint32 spellId_2
) const
1065 SpellEntry
const *spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
1066 if(!spellInfo_1
|| !spellInfo_2
) return false;
1067 if(spellInfo_1
->Id
== spellId_2
) return false;
1069 return GetFirstSpellInChain(spellInfo_1
->Id
)==GetFirstSpellInChain(spellId_2
);
1072 bool SpellMgr::canStackSpellRanks(SpellEntry
const *spellInfo
)
1074 if(IsPassiveSpell(spellInfo
->Id
)) // ranked passive spell
1076 if(spellInfo
->powerType
!= POWER_MANA
&& spellInfo
->powerType
!= POWER_HEALTH
)
1078 if(IsProfessionOrRidingSpell(spellInfo
->Id
))
1081 if(spellmgr
.IsSkillBonusSpell(spellInfo
->Id
))
1084 // All stance spells. if any better way, change it.
1085 for (int i
= 0; i
< 3; ++i
)
1087 switch(spellInfo
->SpellFamilyName
)
1089 case SPELLFAMILY_PALADIN
:
1090 // Paladin aura Spell
1091 if (spellInfo
->Effect
[i
]==SPELL_EFFECT_APPLY_AREA_AURA_RAID
)
1094 case SPELLFAMILY_DRUID
:
1096 if (spellInfo
->Effect
[i
]==SPELL_EFFECT_APPLY_AURA
&&
1097 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_MOD_SHAPESHIFT
)
1100 case SPELLFAMILY_ROGUE
:
1102 if (spellInfo
->Effect
[i
]==SPELL_EFFECT_APPLY_AURA
&&
1103 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_MOD_SHAPESHIFT
)
1110 bool SpellMgr::IsNoStackSpellDueToSpell(uint32 spellId_1
, uint32 spellId_2
) const
1112 SpellEntry
const *spellInfo_1
= sSpellStore
.LookupEntry(spellId_1
);
1113 SpellEntry
const *spellInfo_2
= sSpellStore
.LookupEntry(spellId_2
);
1115 if(!spellInfo_1
|| !spellInfo_2
)
1118 if(spellInfo_1
->Id
== spellId_2
)
1121 //I think we don't check this correctly because i need a exception for spell:
1122 //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.
1123 if(spellInfo_2
->SpellFamilyFlags
== 2048)
1126 // Resurrection sickness
1127 if((spellInfo_1
->Id
== SPELL_ID_PASSIVE_RESURRECTION_SICKNESS
) != (spellInfo_2
->Id
==SPELL_ID_PASSIVE_RESURRECTION_SICKNESS
))
1130 // Allow stack passive and not passive spells
1131 if ((spellInfo_1
->Attributes
& SPELL_ATTR_PASSIVE
)!=(spellInfo_2
->Attributes
& SPELL_ATTR_PASSIVE
))
1134 // Specific spell family spells
1135 switch(spellInfo_1
->SpellFamilyName
)
1137 case SPELLFAMILY_GENERIC
:
1138 switch(spellInfo_2
->SpellFamilyName
)
1140 case SPELLFAMILY_GENERIC
: // same family case
1143 if ((spellInfo_1
->Id
== 21992 && spellInfo_2
->Id
== 27648) ||
1144 (spellInfo_2
->Id
== 21992 && spellInfo_1
->Id
== 27648))
1147 // Lightning Speed (Mongoose) and Fury of the Crashing Waves (Tsunami Talisman)
1148 if ((spellInfo_1
->Id
== 28093 && spellInfo_2
->Id
== 42084) ||
1149 (spellInfo_2
->Id
== 28093 && spellInfo_1
->Id
== 42084))
1152 // Soulstone Resurrection and Twisting Nether (resurrector)
1153 if( spellInfo_1
->SpellIconID
== 92 && spellInfo_2
->SpellIconID
== 92 && (
1154 spellInfo_1
->SpellVisual
[0] == 99 && spellInfo_2
->SpellVisual
[0] == 0 ||
1155 spellInfo_2
->SpellVisual
[0] == 99 && spellInfo_1
->SpellVisual
[0] == 0 ) )
1158 // Heart of the Wild and (Primal Instinct (Idol of Terror) triggering spell or Agility)
1159 if( spellInfo_1
->SpellIconID
== 240 && spellInfo_2
->SpellIconID
== 240 && (
1160 spellInfo_1
->SpellVisual
[0] == 0 && spellInfo_2
->SpellVisual
[0] == 78 ||
1161 spellInfo_2
->SpellVisual
[0] == 0 && spellInfo_1
->SpellVisual
[0] == 78 ) )
1164 // Personalized Weather (thunder effect should overwrite rainy aura)
1165 if(spellInfo_1
->SpellIconID
== 2606 && spellInfo_2
->SpellIconID
== 2606)
1168 // Brood Affliction: Bronze
1169 if( (spellInfo_1
->Id
== 23170 && spellInfo_2
->Id
== 23171) ||
1170 (spellInfo_2
->Id
== 23170 && spellInfo_1
->Id
== 23171) )
1173 // See Chapel Invisibility and See Noth Invisibility
1174 if( (spellInfo_1
->Id
== 52950 && spellInfo_2
->Id
== 52707) ||
1175 (spellInfo_2
->Id
== 52950 && spellInfo_1
->Id
== 52707) )
1178 // Regular and Night Elf Ghost
1179 if( (spellInfo_1
->Id
== 8326 && spellInfo_2
->Id
== 20584) ||
1180 (spellInfo_2
->Id
== 8326 && spellInfo_1
->Id
== 20584) )
1185 case SPELLFAMILY_WARRIOR
:
1187 // Scroll of Protection and Defensive Stance (multi-family check)
1188 if( spellInfo_1
->SpellIconID
== 276 && spellInfo_1
->SpellVisual
[0] == 196 && spellInfo_2
->Id
== 71)
1191 // Improved Hamstring -> Hamstring (multi-family check)
1192 if( (spellInfo_2
->SpellFamilyFlags
& 2) && spellInfo_1
->Id
== 23694 )
1197 case SPELLFAMILY_DRUID
:
1199 // Scroll of Stamina and Leader of the Pack (multi-family check)
1200 if( spellInfo_1
->SpellIconID
== 312 && spellInfo_1
->SpellVisual
[0] == 216 && spellInfo_2
->Id
== 24932 )
1203 // Dragonmaw Illusion (multi-family check)
1204 if (spellId_1
== 40216 && spellId_2
== 42016 )
1209 case SPELLFAMILY_ROGUE
:
1211 // Garrote-Silence -> Garrote (multi-family check)
1212 if( spellInfo_1
->SpellIconID
== 498 && spellInfo_1
->SpellVisual
[0] == 0 && spellInfo_2
->SpellIconID
== 498 )
1217 case SPELLFAMILY_HUNTER
:
1219 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1220 if( spellInfo_1
->Id
== 19410 && spellInfo_2
->Id
== 5116 )
1223 // Improved Wing Clip -> Wing Clip (multi-family check)
1224 if( (spellInfo_2
->SpellFamilyFlags
& 0x40) && spellInfo_1
->Id
== 19229 )
1228 case SPELLFAMILY_PALADIN
:
1230 // Unstable Currents and other -> *Sanctity Aura (multi-family check)
1231 if( spellInfo_2
->SpellIconID
==502 && spellInfo_1
->SpellIconID
==502 && spellInfo_1
->SpellVisual
[0]==969 )
1234 // *Band of Eternal Champion and Seal of Command(multi-family check)
1235 if( spellId_1
== 35081 && spellInfo_2
->SpellIconID
==561 && spellInfo_2
->SpellVisual
[0]==7992)
1241 // Dragonmaw Illusion, Blood Elf Illusion, Human Illusion, Illidari Agent Illusion, Scarlet Crusade Disguise
1242 if(spellInfo_1
->SpellIconID
== 1691 && spellInfo_2
->SpellIconID
== 1691)
1245 case SPELLFAMILY_MAGE
:
1246 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_MAGE
)
1248 // Blizzard & Chilled (and some other stacked with blizzard spells
1249 if( (spellInfo_1
->SpellFamilyFlags
& 0x80) && (spellInfo_2
->SpellFamilyFlags
& 0x100000) ||
1250 (spellInfo_2
->SpellFamilyFlags
& 0x80) && (spellInfo_1
->SpellFamilyFlags
& 0x100000) )
1253 // Blink & Improved Blink
1254 if( (spellInfo_1
->SpellFamilyFlags
& 0x0000000000010000LL
) && (spellInfo_2
->SpellVisual
[0] == 72 && spellInfo_2
->SpellIconID
== 1499) ||
1255 (spellInfo_2
->SpellFamilyFlags
& 0x0000000000010000LL
) && (spellInfo_1
->SpellVisual
[0] == 72 && spellInfo_1
->SpellIconID
== 1499) )
1258 // Detect Invisibility and Mana Shield (multi-family check)
1259 if( spellInfo_2
->Id
== 132 && spellInfo_1
->SpellIconID
== 209 && spellInfo_1
->SpellVisual
[0] == 968 )
1262 // Combustion and Fire Protection Aura (multi-family check)
1263 if( spellInfo_1
->Id
== 11129 && spellInfo_2
->SpellIconID
== 33 && spellInfo_2
->SpellVisual
[0] == 321 )
1267 case SPELLFAMILY_WARLOCK
:
1268 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_WARLOCK
)
1270 // Siphon Life and Drain Life
1271 if( spellInfo_1
->SpellIconID
== 152 && spellInfo_2
->SpellIconID
== 546 ||
1272 spellInfo_2
->SpellIconID
== 152 && spellInfo_1
->SpellIconID
== 546 )
1275 //Corruption & Seed of corruption
1276 if( spellInfo_1
->SpellIconID
== 313 && spellInfo_2
->SpellIconID
== 1932 ||
1277 spellInfo_2
->SpellIconID
== 313 && spellInfo_1
->SpellIconID
== 1932 )
1278 if(spellInfo_1
->SpellVisual
[0] != 0 && spellInfo_2
->SpellVisual
[0] != 0)
1279 return true; // can't be stacked
1281 // Corruption and Unstable Affliction
1282 if( spellInfo_1
->SpellIconID
== 313 && spellInfo_2
->SpellIconID
== 2039 ||
1283 spellInfo_2
->SpellIconID
== 313 && spellInfo_1
->SpellIconID
== 2039 )
1286 // (Corruption or Unstable Affliction) and (Curse of Agony or Curse of Doom)
1287 if( (spellInfo_1
->SpellIconID
== 313 || spellInfo_1
->SpellIconID
== 2039) && (spellInfo_2
->SpellIconID
== 544 || spellInfo_2
->SpellIconID
== 91) ||
1288 (spellInfo_2
->SpellIconID
== 313 || spellInfo_2
->SpellIconID
== 2039) && (spellInfo_1
->SpellIconID
== 544 || spellInfo_1
->SpellIconID
== 91) )
1291 // Detect Invisibility and Mana Shield (multi-family check)
1292 if( spellInfo_1
->Id
== 132 && spellInfo_2
->SpellIconID
== 209 && spellInfo_2
->SpellVisual
[0] == 968 )
1295 case SPELLFAMILY_WARRIOR
:
1296 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_WARRIOR
)
1298 // Rend and Deep Wound
1299 if( (spellInfo_1
->SpellFamilyFlags
& 0x20) && (spellInfo_2
->SpellFamilyFlags
& 0x1000000000LL
) ||
1300 (spellInfo_2
->SpellFamilyFlags
& 0x20) && (spellInfo_1
->SpellFamilyFlags
& 0x1000000000LL
) )
1303 // Battle Shout and Rampage
1304 if( (spellInfo_1
->SpellIconID
== 456 && spellInfo_2
->SpellIconID
== 2006) ||
1305 (spellInfo_2
->SpellIconID
== 456 && spellInfo_1
->SpellIconID
== 2006) )
1309 // Hamstring -> Improved Hamstring (multi-family check)
1310 if( (spellInfo_1
->SpellFamilyFlags
& 2) && spellInfo_2
->Id
== 23694 )
1313 // Defensive Stance and Scroll of Protection (multi-family check)
1314 if( spellInfo_1
->Id
== 71 && spellInfo_2
->SpellIconID
== 276 && spellInfo_2
->SpellVisual
[0] == 196 )
1317 // Bloodlust and Bloodthirst (multi-family check)
1318 if( spellInfo_2
->Id
== 2825 && spellInfo_1
->SpellIconID
== 38 && spellInfo_1
->SpellVisual
[0] == 0 )
1322 case SPELLFAMILY_PRIEST
:
1323 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_PRIEST
)
1325 //Devouring Plague and Shadow Vulnerability
1326 if( (spellInfo_1
->SpellFamilyFlags
& 0x2000000) && (spellInfo_2
->SpellFamilyFlags
& 0x800000000LL
) ||
1327 (spellInfo_2
->SpellFamilyFlags
& 0x2000000) && (spellInfo_1
->SpellFamilyFlags
& 0x800000000LL
) )
1330 //StarShards and Shadow Word: Pain
1331 if( (spellInfo_1
->SpellFamilyFlags
& 0x200000) && (spellInfo_2
->SpellFamilyFlags
& 0x8000) ||
1332 (spellInfo_2
->SpellFamilyFlags
& 0x200000) && (spellInfo_1
->SpellFamilyFlags
& 0x8000) )
1335 if( (spellInfo_1
->Id
== 47585 && spellInfo_2
->Id
== 60069) ||
1336 (spellInfo_2
->Id
== 47585 && spellInfo_1
->Id
== 60069) )
1340 case SPELLFAMILY_DRUID
:
1341 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_DRUID
)
1343 //Omen of Clarity and Blood Frenzy
1344 if( (spellInfo_1
->SpellFamilyFlags
== 0x0 && spellInfo_1
->SpellIconID
== 108) && (spellInfo_2
->SpellFamilyFlags
& 0x20000000000000LL
) ||
1345 (spellInfo_2
->SpellFamilyFlags
== 0x0 && spellInfo_2
->SpellIconID
== 108) && (spellInfo_1
->SpellFamilyFlags
& 0x20000000000000LL
) )
1348 // Tree of Life (Shapeshift) and 34123 Tree of Life (Passive)
1349 if ((spellId_1
== 33891 && spellId_2
== 34123) ||
1350 (spellId_2
== 33891 && spellId_1
== 34123))
1353 // Wrath of Elune and Nature's Grace
1354 if( spellInfo_1
->Id
== 16886 && spellInfo_2
->Id
== 46833 || spellInfo_2
->Id
== 16886 && spellInfo_1
->Id
== 46833 )
1357 // Bear Rage (Feral T4 (2)) and Omen of Clarity
1358 if( spellInfo_1
->Id
== 16864 && spellInfo_2
->Id
== 37306 || spellInfo_2
->Id
== 16864 && spellInfo_1
->Id
== 37306 )
1361 // Cat Energy (Feral T4 (2)) and Omen of Clarity
1362 if( spellInfo_1
->Id
== 16864 && spellInfo_2
->Id
== 37311 || spellInfo_2
->Id
== 16864 && spellInfo_1
->Id
== 37311 )
1365 // Survival Instincts and Survival Instincts
1366 if( spellInfo_1
->Id
== 61336 && spellInfo_2
->Id
== 50322 || spellInfo_2
->Id
== 61336 && spellInfo_1
->Id
== 50322 )
1370 // Leader of the Pack and Scroll of Stamina (multi-family check)
1371 if( spellInfo_1
->Id
== 24932 && spellInfo_2
->SpellIconID
== 312 && spellInfo_2
->SpellVisual
[0] == 216 )
1374 // Dragonmaw Illusion (multi-family check)
1375 if (spellId_1
== 42016 && spellId_2
== 40216 )
1379 case SPELLFAMILY_ROGUE
:
1380 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_ROGUE
)
1382 // Master of Subtlety
1383 if (spellId_1
== 31665 && spellId_2
== 31666 || spellId_1
== 31666 && spellId_2
== 31665 )
1388 if( spellInfo_1
->SpellIconID
== 2285 && spellInfo_2
->SpellIconID
== 2285 )
1391 // Garrote -> Garrote-Silence (multi-family check)
1392 if( spellInfo_1
->SpellIconID
== 498 && spellInfo_2
->SpellIconID
== 498 && spellInfo_2
->SpellVisual
[0] == 0 )
1395 case SPELLFAMILY_HUNTER
:
1396 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_HUNTER
)
1398 // Rapid Fire & Quick Shots
1399 if( (spellInfo_1
->SpellFamilyFlags
& 0x20) && (spellInfo_2
->SpellFamilyFlags
& 0x20000000000LL
) ||
1400 (spellInfo_2
->SpellFamilyFlags
& 0x20) && (spellInfo_1
->SpellFamilyFlags
& 0x20000000000LL
) )
1403 // Serpent Sting & (Immolation/Explosive Trap Effect)
1404 if( (spellInfo_1
->SpellFamilyFlags
& 0x4) && (spellInfo_2
->SpellFamilyFlags
& 0x00000004000LL
) ||
1405 (spellInfo_2
->SpellFamilyFlags
& 0x4) && (spellInfo_1
->SpellFamilyFlags
& 0x00000004000LL
) )
1409 if( spellInfo_1
->SpellIconID
== 1680 && spellInfo_2
->SpellIconID
== 1680 )
1413 // Wing Clip -> Improved Wing Clip (multi-family check)
1414 if( (spellInfo_1
->SpellFamilyFlags
& 0x40) && spellInfo_2
->Id
== 19229 )
1417 // Concussive Shot and Imp. Concussive Shot (multi-family check)
1418 if( spellInfo_2
->Id
== 19410 && spellInfo_1
->Id
== 5116 )
1421 case SPELLFAMILY_PALADIN
:
1422 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_PALADIN
)
1425 if( IsSealSpell(spellInfo_1
) && IsSealSpell(spellInfo_2
) )
1428 // Combustion and Fire Protection Aura (multi-family check)
1429 if( spellInfo_2
->Id
== 11129 && spellInfo_1
->SpellIconID
== 33 && spellInfo_1
->SpellVisual
[0] == 321 )
1432 // *Sanctity Aura -> Unstable Currents and other (multi-family check)
1433 if( spellInfo_1
->SpellIconID
==502 && spellInfo_2
->SpellFamilyName
== SPELLFAMILY_GENERIC
&& spellInfo_2
->SpellIconID
==502 && spellInfo_2
->SpellVisual
[0]==969 )
1436 // *Seal of Command and Band of Eternal Champion (multi-family check)
1437 if( spellInfo_1
->SpellIconID
==561 && spellInfo_1
->SpellVisual
[0]==7992 && spellId_2
== 35081)
1440 case SPELLFAMILY_SHAMAN
:
1441 if( spellInfo_2
->SpellFamilyName
== SPELLFAMILY_SHAMAN
)
1444 if( IsElementalShield(spellInfo_1
) && IsElementalShield(spellInfo_2
) )
1448 if( spellInfo_1
->SpellIconID
==220 && spellInfo_2
->SpellIconID
==220 &&
1449 spellInfo_1
->SpellFamilyFlags
!= spellInfo_2
->SpellFamilyFlags
)
1452 // Bloodlust and Bloodthirst (multi-family check)
1453 if( spellInfo_1
->Id
== 2825 && spellInfo_2
->SpellIconID
== 38 && spellInfo_2
->SpellVisual
[0] == 0 )
1460 // more generic checks
1461 if (spellInfo_1
->SpellIconID
== spellInfo_2
->SpellIconID
&&
1462 spellInfo_1
->SpellIconID
!= 0 && spellInfo_2
->SpellIconID
!= 0)
1464 bool isModifier
= false;
1465 for (int i
= 0; i
< 3; ++i
)
1467 if (spellInfo_1
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_FLAT_MODIFIER
||
1468 spellInfo_1
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_PCT_MODIFIER
||
1469 spellInfo_2
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_FLAT_MODIFIER
||
1470 spellInfo_2
->EffectApplyAuraName
[i
] == SPELL_AURA_ADD_PCT_MODIFIER
)
1478 if (IsRankSpellDueToSpell(spellInfo_1
, spellId_2
))
1481 if (spellInfo_1
->SpellFamilyName
== 0 || spellInfo_2
->SpellFamilyName
== 0)
1484 if (spellInfo_1
->SpellFamilyName
!= spellInfo_2
->SpellFamilyName
)
1487 for (int i
= 0; i
< 3; ++i
)
1488 if (spellInfo_1
->Effect
[i
] != spellInfo_2
->Effect
[i
] ||
1489 spellInfo_1
->EffectItemType
[i
] != spellInfo_2
->EffectItemType
[i
] ||
1490 spellInfo_1
->EffectMiscValue
[i
] != spellInfo_2
->EffectMiscValue
[i
] ||
1491 spellInfo_1
->EffectApplyAuraName
[i
] != spellInfo_2
->EffectApplyAuraName
[i
])
1497 bool SpellMgr::IsProfessionOrRidingSpell(uint32 spellId
)
1499 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
1503 if(spellInfo
->Effect
[1] != SPELL_EFFECT_SKILL
)
1506 uint32 skill
= spellInfo
->EffectMiscValue
[1];
1508 return IsProfessionOrRidingSkill(skill
);
1511 bool SpellMgr::IsProfessionSpell(uint32 spellId
)
1513 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
1517 if(spellInfo
->Effect
[1] != SPELL_EFFECT_SKILL
)
1520 uint32 skill
= spellInfo
->EffectMiscValue
[1];
1522 return IsProfessionSkill(skill
);
1525 bool SpellMgr::IsPrimaryProfessionSpell(uint32 spellId
)
1527 SpellEntry
const *spellInfo
= sSpellStore
.LookupEntry(spellId
);
1531 if(spellInfo
->Effect
[1] != SPELL_EFFECT_SKILL
)
1534 uint32 skill
= spellInfo
->EffectMiscValue
[1];
1536 return IsPrimaryProfessionSkill(skill
);
1539 bool SpellMgr::IsPrimaryProfessionFirstRankSpell(uint32 spellId
) const
1541 return IsPrimaryProfessionSpell(spellId
) && GetSpellRank(spellId
)==1;
1544 bool SpellMgr::IsSkillBonusSpell(uint32 spellId
) const
1546 SkillLineAbilityMap::const_iterator lower
= GetBeginSkillLineAbilityMap(spellId
);
1547 SkillLineAbilityMap::const_iterator upper
= GetEndSkillLineAbilityMap(spellId
);
1549 for(SkillLineAbilityMap::const_iterator _spell_idx
= lower
; _spell_idx
!= upper
; ++_spell_idx
)
1551 SkillLineAbilityEntry
const *pAbility
= _spell_idx
->second
;
1552 if (!pAbility
|| pAbility
->learnOnGetSkill
!= ABILITY_LEARNED_ON_GET_PROFESSION_SKILL
)
1555 if(pAbility
->req_skill_value
> 0)
1562 SpellEntry
const* SpellMgr::SelectAuraRankForPlayerLevel(SpellEntry
const* spellInfo
, uint32 playerLevel
) const
1564 // ignore passive spells
1565 if(IsPassiveSpell(spellInfo
->Id
))
1568 bool needRankSelection
= false;
1569 for(int i
=0;i
<3;++i
)
1571 if( IsPositiveEffect(spellInfo
->Id
, i
) && (
1572 spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AURA
||
1573 spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AREA_AURA_PARTY
||
1574 spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AREA_AURA_RAID
1577 needRankSelection
= true;
1583 if(!needRankSelection
)
1586 for(uint32 nextSpellId
= spellInfo
->Id
; nextSpellId
!= 0; nextSpellId
= GetPrevSpellInChain(nextSpellId
))
1588 SpellEntry
const *nextSpellInfo
= sSpellStore
.LookupEntry(nextSpellId
);
1592 // if found appropriate level
1593 if(playerLevel
+ 10 >= nextSpellInfo
->spellLevel
)
1594 return nextSpellInfo
;
1596 // one rank less then
1603 void SpellMgr::LoadSpellChains()
1605 mSpellChains
.clear(); // need for reload case
1606 mSpellChainsNext
.clear(); // need for reload case
1608 QueryResult
*result
= WorldDatabase
.Query("SELECT spell_id, prev_spell, first_spell, rank, req_spell FROM spell_chain");
1615 sLog
.outString( ">> Loaded 0 spell chain records" );
1616 sLog
.outErrorDb("`spell_chains` table is empty!");
1622 barGoLink
bar( result
->GetRowCount() );
1626 Field
*fields
= result
->Fetch();
1628 uint32 spell_id
= fields
[0].GetUInt32();
1630 SpellChainNode node
;
1631 node
.prev
= fields
[1].GetUInt32();
1632 node
.first
= fields
[2].GetUInt32();
1633 node
.rank
= fields
[3].GetUInt8();
1634 node
.req
= fields
[4].GetUInt32();
1636 if(!sSpellStore
.LookupEntry(spell_id
))
1638 sLog
.outErrorDb("Spell %u listed in `spell_chain` does not exist",spell_id
);
1642 if(node
.prev
!=0 && !sSpellStore
.LookupEntry(node
.prev
))
1644 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existed previous rank spell.",
1645 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1649 if(!sSpellStore
.LookupEntry(node
.first
))
1651 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing first rank spell.",
1652 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1656 // check basic spell chain data integrity (note: rank can be equal 0 or 1 for first/single spell)
1657 if( (spell_id
== node
.first
) != (node
.rank
<= 1) ||
1658 (spell_id
== node
.first
) != (node
.prev
== 0) ||
1659 (node
.rank
<= 1) != (node
.prev
== 0) )
1661 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not compatible chain data.",
1662 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1666 if(node
.req
!=0 && !sSpellStore
.LookupEntry(node
.req
))
1668 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not existing required spell.",
1669 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1673 // talents not required data in spell chain for work, but must be checked if present for intergrity
1674 if(TalentSpellPos
const* pos
= GetTalentSpellPos(spell_id
))
1676 if(node
.rank
!=pos
->rank
+1)
1678 sLog
.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong rank.",
1679 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1683 if(TalentEntry
const* talentEntry
= sTalentStore
.LookupEntry(pos
->talent_id
))
1685 if(node
.first
!=talentEntry
->RankID
[0])
1687 sLog
.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong first rank spell.",
1688 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1692 if(node
.rank
> 1 && node
.prev
!= talentEntry
->RankID
[node
.rank
-1-1])
1694 sLog
.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong prev rank spell.",
1695 spell_id
,node
.prev
,node
.first
,node
.rank
,node
.req
);
1699 /*if(node.req!=talentEntry->DependsOnSpell)
1701 sLog.outErrorDb("Talent %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has wrong required spell.",
1702 spell_id,node.prev,node.first,node.rank,node.req);
1708 mSpellChains
[spell_id
] = node
;
1711 mSpellChainsNext
.insert(SpellChainMapNext::value_type(node
.prev
,spell_id
));
1714 mSpellChainsNext
.insert(SpellChainMapNext::value_type(node
.req
,spell_id
));
1717 } while( result
->NextRow() );
1721 // additional integrity checks
1722 for(SpellChainMap::const_iterator i
= mSpellChains
.begin(); i
!= mSpellChains
.end(); ++i
)
1726 SpellChainMap::const_iterator i_prev
= mSpellChains
.find(i
->second
.prev
);
1727 if(i_prev
== mSpellChains
.end())
1729 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found previous rank spell in table.",
1730 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
);
1732 else if( i_prev
->second
.first
!= i
->second
.first
)
1734 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).",
1735 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1736 i_prev
->second
.prev
,i_prev
->second
.first
,i_prev
->second
.rank
,i_prev
->second
.req
);
1738 else if( i_prev
->second
.rank
+1 != i
->second
.rank
)
1740 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).",
1741 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1742 i_prev
->second
.prev
,i_prev
->second
.first
,i_prev
->second
.rank
,i_prev
->second
.req
);
1748 SpellChainMap::const_iterator i_req
= mSpellChains
.find(i
->second
.req
);
1749 if(i_req
== mSpellChains
.end())
1751 sLog
.outErrorDb("Spell %u (prev: %u, first: %u, rank: %d, req: %u) listed in `spell_chain` has not found required rank spell in table.",
1752 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
);
1754 else if( i_req
->second
.first
== i
->second
.first
)
1756 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).",
1757 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1758 i_req
->second
.prev
,i_req
->second
.first
,i_req
->second
.rank
,i_req
->second
.req
);
1760 else if( i_req
->second
.req
)
1762 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).",
1763 i
->first
,i
->second
.prev
,i
->second
.first
,i
->second
.rank
,i
->second
.req
,
1764 i_req
->second
.prev
,i_req
->second
.first
,i_req
->second
.rank
,i_req
->second
.req
);
1770 sLog
.outString( ">> Loaded %u spell chain records", count
);
1773 void SpellMgr::LoadSpellLearnSkills()
1775 mSpellLearnSkills
.clear(); // need for reload case
1777 // search auto-learned skills and add its to map also for use in unlearn spells/talents
1778 uint32 dbc_count
= 0;
1779 barGoLink
bar( sSpellStore
.GetNumRows() );
1780 for(uint32 spell
= 0; spell
< sSpellStore
.GetNumRows(); ++spell
)
1783 SpellEntry
const* entry
= sSpellStore
.LookupEntry(spell
);
1788 for(int i
= 0; i
< 3; ++i
)
1790 if(entry
->Effect
[i
]==SPELL_EFFECT_SKILL
)
1792 SpellLearnSkillNode dbc_node
;
1793 dbc_node
.skill
= entry
->EffectMiscValue
[i
];
1794 if ( dbc_node
.skill
!= SKILL_RIDING
)
1797 dbc_node
.value
= entry
->CalculateSimpleValue(i
)*75;
1798 dbc_node
.maxvalue
= entry
->CalculateSimpleValue(i
)*75;
1800 mSpellLearnSkills
[spell
] = dbc_node
;
1808 sLog
.outString( ">> Loaded %u Spell Learn Skills from DBC", dbc_count
);
1811 void SpellMgr::LoadSpellLearnSpells()
1813 mSpellLearnSpells
.clear(); // need for reload case
1816 QueryResult
*result
= WorldDatabase
.Query("SELECT entry, SpellID, Active FROM spell_learn_spell");
1823 sLog
.outString( ">> Loaded 0 spell learn spells" );
1824 sLog
.outErrorDb("`spell_learn_spell` table is empty!");
1830 barGoLink
bar( result
->GetRowCount() );
1834 Field
*fields
= result
->Fetch();
1836 uint32 spell_id
= fields
[0].GetUInt32();
1838 SpellLearnSpellNode node
;
1839 node
.spell
= fields
[1].GetUInt32();
1840 node
.active
= fields
[2].GetBool();
1841 node
.autoLearned
= false;
1843 if(!sSpellStore
.LookupEntry(spell_id
))
1845 sLog
.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",spell_id
);
1849 if(!sSpellStore
.LookupEntry(node
.spell
))
1851 sLog
.outErrorDb("Spell %u listed in `spell_learn_spell` does not exist",node
.spell
);
1855 mSpellLearnSpells
.insert(SpellLearnSpellMap::value_type(spell_id
,node
));
1858 } while( result
->NextRow() );
1862 // search auto-learned spells and add its to map also for use in unlearn spells/talents
1863 uint32 dbc_count
= 0;
1864 for(uint32 spell
= 0; spell
< sSpellStore
.GetNumRows(); ++spell
)
1866 SpellEntry
const* entry
= sSpellStore
.LookupEntry(spell
);
1871 for(int i
= 0; i
< 3; ++i
)
1873 if(entry
->Effect
[i
]==SPELL_EFFECT_LEARN_SPELL
)
1875 SpellLearnSpellNode dbc_node
;
1876 dbc_node
.spell
= entry
->EffectTriggerSpell
[i
];
1877 dbc_node
.active
= true; // all dbc based learned spells is active (show in spell book or hide by client itself)
1879 // ignore learning not existed spells (broken/outdated/or generic learnig spell 483
1880 if(!sSpellStore
.LookupEntry(dbc_node
.spell
))
1883 // talent or passive spells or skill-step spells auto-casted and not need dependent learning,
1884 // pet teaching spells don't must be dependent learning (casted)
1885 // other required explicit dependent learning
1886 dbc_node
.autoLearned
= entry
->EffectImplicitTargetA
[i
]==TARGET_PET
|| GetTalentSpellCost(spell
) > 0 || IsPassiveSpell(spell
) || IsSpellHaveEffect(entry
,SPELL_EFFECT_SKILL_STEP
);
1888 SpellLearnSpellMap::const_iterator db_node_begin
= GetBeginSpellLearnSpell(spell
);
1889 SpellLearnSpellMap::const_iterator db_node_end
= GetEndSpellLearnSpell(spell
);
1892 for(SpellLearnSpellMap::const_iterator itr
= db_node_begin
; itr
!= db_node_end
; ++itr
)
1894 if(itr
->second
.spell
== dbc_node
.spell
)
1896 sLog
.outErrorDb("Spell %u auto-learn spell %u in spell.dbc then the record in `spell_learn_spell` is redundant, please fix DB.",
1897 spell
,dbc_node
.spell
);
1903 if(!found
) // add new spell-spell pair if not found
1905 mSpellLearnSpells
.insert(SpellLearnSpellMap::value_type(spell
,dbc_node
));
1913 sLog
.outString( ">> Loaded %u spell learn spells + %u found in DBC", count
, dbc_count
);
1916 void SpellMgr::LoadSpellScriptTarget()
1918 mSpellScriptTarget
.clear(); // need for reload case
1922 QueryResult
*result
= WorldDatabase
.Query("SELECT entry,type,targetEntry FROM spell_script_target");
1931 sLog
.outErrorDb(">> Loaded 0 SpellScriptTarget. DB table `spell_script_target` is empty.");
1935 barGoLink
bar(result
->GetRowCount());
1939 Field
*fields
= result
->Fetch();
1942 uint32 spellId
= fields
[0].GetUInt32();
1943 uint32 type
= fields
[1].GetUInt32();
1944 uint32 targetEntry
= fields
[2].GetUInt32();
1946 SpellEntry
const* spellProto
= sSpellStore
.LookupEntry(spellId
);
1950 sLog
.outErrorDb("Table `spell_script_target`: spellId %u listed for TargetEntry %u does not exist.",spellId
,targetEntry
);
1954 bool targetfound
= false;
1955 for(int i
= 0; i
<3; ++i
)
1957 if( spellProto
->EffectImplicitTargetA
[i
]==TARGET_SCRIPT
||
1958 spellProto
->EffectImplicitTargetB
[i
]==TARGET_SCRIPT
||
1959 spellProto
->EffectImplicitTargetA
[i
]==TARGET_SCRIPT_COORDINATES
||
1960 spellProto
->EffectImplicitTargetB
[i
]==TARGET_SCRIPT_COORDINATES
)
1968 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
);
1972 if( type
>= MAX_SPELL_TARGET_TYPE
)
1974 sLog
.outErrorDb("Table `spell_script_target`: target type %u for TargetEntry %u is incorrect.",type
,targetEntry
);
1980 case SPELL_TARGET_TYPE_GAMEOBJECT
:
1982 if( targetEntry
==0 )
1985 if(!sGOStorage
.LookupEntry
<GameObjectInfo
>(targetEntry
))
1987 sLog
.outErrorDb("Table `spell_script_target`: gameobject template entry %u does not exist.",targetEntry
);
1994 if( targetEntry
==0 )
1996 sLog
.outErrorDb("Table `spell_script_target`: target entry == 0 for not GO target type (%u).",type
);
1999 if(!sCreatureStorage
.LookupEntry
<CreatureInfo
>(targetEntry
))
2001 sLog
.outErrorDb("Table `spell_script_target`: creature template entry %u does not exist.",targetEntry
);
2004 const CreatureInfo
* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(targetEntry
);
2006 if(spellId
== 30427 && !cInfo
->SkinLootId
)
2008 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
);
2015 mSpellScriptTarget
.insert(SpellScriptTarget::value_type(spellId
,SpellTargetEntry(SpellTargetType(type
),targetEntry
)));
2018 } while (result
->NextRow());
2023 /* Disabled (lot errors at this moment)
2024 for(uint32 i = 1; i < sSpellStore.nCount; ++i)
2026 SpellEntry const * spellInfo = sSpellStore.LookupEntry(i);
2031 for(int j=0; j<3; ++j)
2033 if( spellInfo->EffectImplicitTargetA[j] == TARGET_SCRIPT || spellInfo->EffectImplicitTargetA[j] != TARGET_SELF && spellInfo->EffectImplicitTargetB[j] == TARGET_SCRIPT )
2035 SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(spellInfo->Id);
2036 SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(spellInfo->Id);
2039 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);
2040 break; // effects of spell
2048 sLog
.outString(">> Loaded %u Spell Script Targets", count
);
2051 void SpellMgr::LoadSpellPetAuras()
2053 mSpellPetAuraMap
.clear(); // need for reload case
2058 QueryResult
*result
= WorldDatabase
.Query("SELECT spell, pet, aura FROM spell_pet_auras");
2067 sLog
.outString( ">> Loaded %u spell pet auras", count
);
2071 barGoLink
bar( result
->GetRowCount() );
2075 Field
*fields
= result
->Fetch();
2079 uint16 spell
= fields
[0].GetUInt16();
2080 uint16 pet
= fields
[1].GetUInt16();
2081 uint16 aura
= fields
[2].GetUInt16();
2083 SpellPetAuraMap::iterator itr
= mSpellPetAuraMap
.find(spell
);
2084 if(itr
!= mSpellPetAuraMap
.end())
2086 itr
->second
.AddAura(pet
, aura
);
2090 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(spell
);
2093 sLog
.outErrorDb("Spell %u listed in `spell_pet_auras` does not exist", spell
);
2098 if((spellInfo
->Effect
[i
] == SPELL_EFFECT_APPLY_AURA
&&
2099 spellInfo
->EffectApplyAuraName
[i
] == SPELL_AURA_DUMMY
) ||
2100 spellInfo
->Effect
[i
] == SPELL_EFFECT_DUMMY
)
2105 sLog
.outError("Spell %u listed in `spell_pet_auras` does not have dummy aura or dummy effect", spell
);
2109 SpellEntry
const* spellInfo2
= sSpellStore
.LookupEntry(aura
);
2112 sLog
.outErrorDb("Aura %u listed in `spell_pet_auras` does not exist", aura
);
2116 PetAura
pa(pet
, aura
, spellInfo
->EffectImplicitTargetA
[i
] == TARGET_PET
, spellInfo
->CalculateSimpleValue(i
));
2117 mSpellPetAuraMap
[spell
] = pa
;
2121 } while( result
->NextRow() );
2126 sLog
.outString( ">> Loaded %u spell pet auras", count
);
2129 static uint32 family2skillline
[MAX_CREATURE_FAMILY
][2] = {
2130 /* ----------------------------- = 0 */ {0, 0 },
2131 /*CREATURE_FAMILY_WOLF = 1 */ {208, 270},
2132 /*CREATURE_FAMILY_CAT = 2 */ {209, 270},
2133 /*CREATURE_FAMILY_SPIDER = 3 */ {203, 270},
2134 /*CREATURE_FAMILY_BEAR = 4 */ {210, 270},
2135 /*CREATURE_FAMILY_BOAR = 5 */ {211, 270},
2136 /*CREATURE_FAMILY_CROCOLISK = 6 */ {212, 270},
2137 /*CREATURE_FAMILY_CARRION_BIRD = 7 */ {213, 270},
2138 /*CREATURE_FAMILY_CRAB = 8 */ {214, 270},
2139 /*CREATURE_FAMILY_GORILLA = 9 */ {215, 270},
2140 /*CREATURE_FAMILY_HORSE_CUSTOM = 10*/ {0, 0 },
2141 /*CREATURE_FAMILY_RAPTOR = 11*/ {217, 270},
2142 /*CREATURE_FAMILY_TALLSTRIDER = 12*/ {218, 270},
2143 /* ----------------------------- = 13*/ {0, 0 },
2144 /* ----------------------------- = 14*/ {0, 0 },
2145 /*CREATURE_FAMILY_FELHUNTER = 15*/ {189, 0 },
2146 /*CREATURE_FAMILY_VOIDWALKER = 16*/ {204, 0 },
2147 /*CREATURE_FAMILY_SUCCUBUS = 17*/ {205, 0 },
2148 /* ----------------------------- = 18*/ {0, 0 },
2149 /*CREATURE_FAMILY_DOOMGUARD = 19*/ {207, 0 },
2150 /*CREATURE_FAMILY_SCORPID = 20*/ {236, 270},
2151 /*CREATURE_FAMILY_TURTLE = 21*/ {251, 270},
2152 /* ----------------------------- = 22*/ {0, 0 },
2153 /*CREATURE_FAMILY_IMP = 23*/ {188, 0 },
2154 /*CREATURE_FAMILY_BAT = 24*/ {653, 270},
2155 /*CREATURE_FAMILY_HYENA = 25*/ {654, 270},
2156 /*CREATURE_FAMILY_BIRD_OF_PREY = 26*/ {655, 270},
2157 /*CREATURE_FAMILY_WIND_SERPENT = 27*/ {656, 270},
2158 /*CREATURE_FAMILY_REMOTE_CONTROL = 28*/ {758, 0 },
2159 /*CREATURE_FAMILY_FELGUARD = 29*/ {761, 0 },
2160 /*CREATURE_FAMILY_DRAGONHAWK = 30*/ {763, 270},
2161 /*CREATURE_FAMILY_RAVAGER = 31*/ {767, 270},
2162 /*CREATURE_FAMILY_WARP_STALKER = 32*/ {766, 270},
2163 /*CREATURE_FAMILY_SPOREBAT = 33*/ {765, 270},
2164 /*CREATURE_FAMILY_NETHER_RAY = 34*/ {764, 270},
2165 /*CREATURE_FAMILY_SERPENT = 35*/ {768, 270},
2166 /* ----------------------------- = 36*/ {0, 0 },
2167 /*CREATURE_FAMILY_MOTH = 37*/ {775, 270},
2168 /*CREATURE_FAMILY_CHIMAERA = 38*/ {780, 270},
2169 /*CREATURE_FAMILY_DEVILSAUR = 39*/ {781, 270},
2170 /*CREATURE_FAMILY_GHOUL = 40*/ {782, 0 },
2171 /*CREATURE_FAMILY_SILITHID = 41*/ {783, 270},
2172 /*CREATURE_FAMILY_WORM = 42*/ {784, 270},
2173 /*CREATURE_FAMILY_RHINO = 43*/ {786, 270},
2174 /*CREATURE_FAMILY_WASP = 44*/ {785, 270},
2175 /*CREATURE_FAMILY_CORE_HOUND = 45*/ {787, 270},
2176 /*CREATURE_FAMILY_SPIRIT_BEAST = 46*/ {788, 270}
2179 void SpellMgr::LoadPetLevelupSpellMap()
2182 uint32 family_count
= 0;
2184 for (uint32 i
= 0; i
< sCreatureFamilyStore
.GetNumRows(); ++i
)
2186 CreatureFamilyEntry
const *creatureFamily
= sCreatureFamilyStore
.LookupEntry(i
);
2187 if(!creatureFamily
) // not exist
2190 if(i
>= MAX_CREATURE_FAMILY
)
2193 if(!family2skillline
[i
][0])
2196 for (uint32 j
= 0; j
< sSkillLineAbilityStore
.GetNumRows(); ++j
)
2198 SkillLineAbilityEntry
const *skillLine
= sSkillLineAbilityStore
.LookupEntry(j
);
2202 if (skillLine
->skillId
!=family2skillline
[i
][0] &&
2203 (!family2skillline
[i
][1] || skillLine
->skillId
!=family2skillline
[i
][1]))
2206 if(skillLine
->learnOnGetSkill
!= ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL
)
2209 SpellEntry
const *spell
= sSpellStore
.LookupEntry(skillLine
->spellId
);
2210 if(!spell
) // not exist
2213 PetLevelupSpellSet
& spellSet
= mPetLevelupSpellMap
[creatureFamily
->ID
];
2214 if(spellSet
.empty())
2217 spellSet
.insert(PetLevelupSpellSet::value_type(spell
->spellLevel
,spell
->Id
));
2223 sLog
.outString( ">> Loaded %u pet levelup and default spells for %u families", count
, family_count
);
2226 bool LoadPetDefaultSpells_helper(CreatureInfo
const* cInfo
, PetDefaultSpellsEntry
& petDefSpells
)
2229 bool have_spell
= false;
2230 for(int j
= 0; j
< MAX_CREATURE_SPELL_DATA_SLOT
; ++j
)
2232 if(petDefSpells
.spellid
[j
])
2241 // remove duplicates with levelupSpells if any
2242 if(PetLevelupSpellSet
const *levelupSpells
= cInfo
->family
? spellmgr
.GetPetLevelupSpellList(cInfo
->family
) : NULL
)
2244 for(int j
= 0; j
< MAX_CREATURE_SPELL_DATA_SLOT
; ++j
)
2246 if(!petDefSpells
.spellid
[j
])
2249 for(PetLevelupSpellSet::const_iterator itr
= levelupSpells
->begin(); itr
!= levelupSpells
->end(); ++itr
)
2251 if (itr
->second
== petDefSpells
.spellid
[j
])
2253 petDefSpells
.spellid
[j
] = 0;
2262 for(int j
= 0; j
< MAX_CREATURE_SPELL_DATA_SLOT
; ++j
)
2264 if(petDefSpells
.spellid
[j
])
2274 void SpellMgr::LoadPetDefaultSpells()
2276 assert(MAX_CREATURE_SPELL_DATA_SLOT
==CREATURE_MAX_SPELLS
);
2278 mPetDefaultSpellsMap
.clear();
2280 uint32 countCreature
= 0;
2281 uint32 countData
= 0;
2283 for(uint32 i
= 0; i
< sCreatureStorage
.MaxEntry
; ++i
)
2285 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(i
);
2289 if(!cInfo
->PetSpellDataId
)
2292 // for creature with PetSpellDataId get default pet spells from dbc
2293 CreatureSpellDataEntry
const* spellDataEntry
= sCreatureSpellDataStore
.LookupEntry(cInfo
->PetSpellDataId
);
2297 int32 petSpellsId
= -(int32
)cInfo
->PetSpellDataId
;
2298 PetDefaultSpellsEntry petDefSpells
;
2299 for(int j
= 0; j
< MAX_CREATURE_SPELL_DATA_SLOT
; ++j
)
2300 petDefSpells
.spellid
[j
] = spellDataEntry
->spellId
[j
];
2302 if(LoadPetDefaultSpells_helper(cInfo
, petDefSpells
))
2304 mPetDefaultSpellsMap
[petSpellsId
] = petDefSpells
;
2309 // different summon spells
2310 for(uint32 i
= 0; i
< sSpellStore
.GetNumRows(); ++i
)
2312 SpellEntry
const* spellEntry
= sSpellStore
.LookupEntry(i
);
2316 for(int k
= 0; k
< 3; ++k
)
2318 if(spellEntry
->Effect
[k
]==SPELL_EFFECT_SUMMON
|| spellEntry
->Effect
[k
]==SPELL_EFFECT_SUMMON_PET
)
2320 uint32 creature_id
= spellEntry
->EffectMiscValue
[k
];
2321 CreatureInfo
const* cInfo
= sCreatureStorage
.LookupEntry
<CreatureInfo
>(creature_id
);
2326 if(cInfo
->PetSpellDataId
)
2329 // for creature without PetSpellDataId get default pet spells from creature_template
2330 int32 petSpellsId
= cInfo
->Entry
;
2331 if(mPetDefaultSpellsMap
.find(cInfo
->Entry
) != mPetDefaultSpellsMap
.end())
2334 PetDefaultSpellsEntry petDefSpells
;
2335 for(int j
= 0; j
< MAX_CREATURE_SPELL_DATA_SLOT
; ++j
)
2336 petDefSpells
.spellid
[j
] = cInfo
->spells
[j
];
2338 if(LoadPetDefaultSpells_helper(cInfo
, petDefSpells
))
2340 mPetDefaultSpellsMap
[petSpellsId
] = petDefSpells
;
2348 sLog
.outString( ">> Loaded addition spells for %u pet spell data entries and %u summonable creature templates", countData
, countCreature
);
2351 /// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc
2352 bool SpellMgr::IsSpellValid(SpellEntry
const* spellInfo
, Player
* pl
, bool msg
)
2358 bool need_check_reagents
= false;
2361 for(int i
=0; i
<3; ++i
)
2363 switch(spellInfo
->Effect
[i
])
2368 // craft spell for crafting non-existed item (break client recipes list show)
2369 case SPELL_EFFECT_CREATE_ITEM
:
2371 if(!ObjectMgr::GetItemPrototype( spellInfo
->EffectItemType
[i
] ))
2376 ChatHandler(pl
).PSendSysMessage("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->EffectItemType
[i
]);
2378 sLog
.outErrorDb("Craft spell %u create not-exist in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->EffectItemType
[i
]);
2383 need_check_reagents
= true;
2386 case SPELL_EFFECT_LEARN_SPELL
:
2388 SpellEntry
const* spellInfo2
= sSpellStore
.LookupEntry(spellInfo
->EffectTriggerSpell
[i
]);
2389 if( !IsSpellValid(spellInfo2
,pl
,msg
) )
2394 ChatHandler(pl
).PSendSysMessage("Spell %u learn to broken spell %u, and then...",spellInfo
->Id
,spellInfo
->EffectTriggerSpell
[i
]);
2396 sLog
.outErrorDb("Spell %u learn to invalid spell %u, and then...",spellInfo
->Id
,spellInfo
->EffectTriggerSpell
[i
]);
2405 if(need_check_reagents
)
2407 for(int j
= 0; j
< 8; ++j
)
2409 if(spellInfo
->Reagent
[j
] > 0 && !ObjectMgr::GetItemPrototype( spellInfo
->Reagent
[j
] ))
2414 ChatHandler(pl
).PSendSysMessage("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->Reagent
[j
]);
2416 sLog
.outErrorDb("Craft spell %u have not-exist reagent in DB item (Entry: %u) and then...",spellInfo
->Id
,spellInfo
->Reagent
[j
]);
2426 void SpellMgr::LoadSpellAreas()
2428 mSpellAreaMap
.clear(); // need for reload case
2429 mSpellAreaForQuestMap
.clear();
2430 mSpellAreaForActiveQuestMap
.clear();
2431 mSpellAreaForQuestEndMap
.clear();
2432 mSpellAreaForAuraMap
.clear();
2436 // 0 1 2 3 4 5 6 7 8
2437 QueryResult
*result
= WorldDatabase
.Query("SELECT spell, area, quest_start, quest_start_active, quest_end, aura_spell, racemask, gender, autocast FROM spell_area");
2446 sLog
.outString( ">> Loaded %u spell area requirements", count
);
2450 barGoLink
bar( result
->GetRowCount() );
2454 Field
*fields
= result
->Fetch();
2458 uint32 spell
= fields
[0].GetUInt32();
2459 SpellArea spellArea
;
2460 spellArea
.spellId
= spell
;
2461 spellArea
.areaId
= fields
[1].GetUInt32();
2462 spellArea
.questStart
= fields
[2].GetUInt32();
2463 spellArea
.questStartCanActive
= fields
[3].GetBool();
2464 spellArea
.questEnd
= fields
[4].GetUInt32();
2465 spellArea
.auraSpell
= fields
[5].GetInt32();
2466 spellArea
.raceMask
= fields
[6].GetUInt32();
2467 spellArea
.gender
= Gender(fields
[7].GetUInt8());
2468 spellArea
.autocast
= fields
[8].GetBool();
2470 if(!sSpellStore
.LookupEntry(spell
))
2472 sLog
.outErrorDb("Spell %u listed in `spell_area` does not exist", spell
);
2478 SpellAreaMapBounds sa_bounds
= GetSpellAreaMapBounds(spellArea
.spellId
);
2479 for(SpellAreaMap::const_iterator itr
= sa_bounds
.first
; itr
!= sa_bounds
.second
; ++itr
)
2481 if(spellArea
.spellId
&& itr
->second
.spellId
&& spellArea
.spellId
!= itr
->second
.spellId
)
2483 if(spellArea
.areaId
&& itr
->second
.areaId
&& spellArea
.areaId
!= itr
->second
.areaId
)
2485 if(spellArea
.questStart
&& itr
->second
.questStart
&& spellArea
.questStart
!= itr
->second
.questStart
)
2487 if(spellArea
.auraSpell
&& itr
->second
.auraSpell
&& spellArea
.auraSpell
!= itr
->second
.auraSpell
)
2489 if(spellArea
.raceMask
&& itr
->second
.raceMask
&& (spellArea
.raceMask
& itr
->second
.raceMask
)==0)
2491 if(spellArea
.gender
!= GENDER_NONE
&& itr
->second
.gender
!= GENDER_NONE
&& spellArea
.gender
!= itr
->second
.gender
)
2494 // duplicate by requirements
2501 sLog
.outErrorDb("Spell %u listed in `spell_area` already listed with similar requirements.", spell
);
2507 if(spellArea
.areaId
&& !GetAreaEntryByAreaID(spellArea
.areaId
))
2509 sLog
.outErrorDb("Spell %u listed in `spell_area` have wrong area (%u) requirement", spell
,spellArea
.areaId
);
2513 if(spellArea
.questStart
&& !objmgr
.GetQuestTemplate(spellArea
.questStart
))
2515 sLog
.outErrorDb("Spell %u listed in `spell_area` have wrong start quest (%u) requirement", spell
,spellArea
.questStart
);
2519 if(spellArea
.questEnd
)
2521 if(!objmgr
.GetQuestTemplate(spellArea
.questEnd
))
2523 sLog
.outErrorDb("Spell %u listed in `spell_area` have wrong end quest (%u) requirement", spell
,spellArea
.questEnd
);
2527 if(spellArea
.questEnd
==spellArea
.questStart
&& !spellArea
.questStartCanActive
)
2529 sLog
.outErrorDb("Spell %u listed in `spell_area` have quest (%u) requirement for start and end in same time", spell
,spellArea
.questEnd
);
2534 if(spellArea
.auraSpell
)
2536 SpellEntry
const* spellInfo
= sSpellStore
.LookupEntry(abs(spellArea
.auraSpell
));
2539 sLog
.outErrorDb("Spell %u listed in `spell_area` have wrong aura spell (%u) requirement", spell
,abs(spellArea
.auraSpell
));
2543 if(spellInfo
->EffectApplyAuraName
[0]!=SPELL_AURA_DUMMY
&& spellInfo
->EffectApplyAuraName
[0]!=SPELL_AURA_PHASE
)
2545 sLog
.outErrorDb("Spell %u listed in `spell_area` have aura spell requirement (%u) without dummy/phase aura in effect 0", spell
,abs(spellArea
.auraSpell
));
2549 if(abs(spellArea
.auraSpell
)==spellArea
.spellId
)
2551 sLog
.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement for itself", spell
,abs(spellArea
.auraSpell
));
2555 // not allow autocast chains by auraSpell field (but allow use as alternative if not present)
2556 if(spellArea
.autocast
&& spellArea
.auraSpell
> 0)
2559 SpellAreaForAuraMapBounds saBound
= GetSpellAreaForAuraMapBounds(spellArea
.spellId
);
2560 for(SpellAreaForAuraMap::const_iterator itr
= saBound
.first
; itr
!= saBound
.second
; ++itr
)
2562 if(itr
->second
->autocast
&& itr
->second
->auraSpell
> 0)
2571 sLog
.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement that itself autocast from aura", spell
,spellArea
.auraSpell
);
2575 SpellAreaMapBounds saBound2
= GetSpellAreaMapBounds(spellArea
.auraSpell
);
2576 for(SpellAreaMap::const_iterator itr2
= saBound2
.first
; itr2
!= saBound2
.second
; ++itr2
)
2578 if(itr2
->second
.autocast
&& itr2
->second
.auraSpell
> 0)
2587 sLog
.outErrorDb("Spell %u listed in `spell_area` have aura spell (%u) requirement that itself autocast from aura", spell
,spellArea
.auraSpell
);
2593 if(spellArea
.raceMask
&& (spellArea
.raceMask
& RACEMASK_ALL_PLAYABLE
)==0)
2595 sLog
.outErrorDb("Spell %u listed in `spell_area` have wrong race mask (%u) requirement", spell
,spellArea
.raceMask
);
2599 if(spellArea
.gender
!=GENDER_NONE
&& spellArea
.gender
!=GENDER_FEMALE
&& spellArea
.gender
!=GENDER_MALE
)
2601 sLog
.outErrorDb("Spell %u listed in `spell_area` have wrong gender (%u) requirement", spell
,spellArea
.gender
);
2605 SpellArea
const* sa
= &mSpellAreaMap
.insert(SpellAreaMap::value_type(spell
,spellArea
))->second
;
2607 // for search by current zone/subzone at zone/subzone change
2608 if(spellArea
.areaId
)
2609 mSpellAreaForAreaMap
.insert(SpellAreaForAreaMap::value_type(spellArea
.areaId
,sa
));
2611 // for search at quest start/reward
2612 if(spellArea
.questStart
)
2614 if(spellArea
.questStartCanActive
)
2615 mSpellAreaForActiveQuestMap
.insert(SpellAreaForQuestMap::value_type(spellArea
.questStart
,sa
));
2617 mSpellAreaForQuestMap
.insert(SpellAreaForQuestMap::value_type(spellArea
.questStart
,sa
));
2620 // for search at quest start/reward
2621 if(spellArea
.questEnd
)
2622 mSpellAreaForQuestEndMap
.insert(SpellAreaForQuestMap::value_type(spellArea
.questEnd
,sa
));
2624 // for search at aura apply
2625 if(spellArea
.auraSpell
)
2626 mSpellAreaForAuraMap
.insert(SpellAreaForAuraMap::value_type(abs(spellArea
.auraSpell
),sa
));
2629 } while( result
->NextRow() );
2634 sLog
.outString( ">> Loaded %u spell area requirements", count
);
2637 SpellCastResult
SpellMgr::GetSpellAllowedInLocationError(SpellEntry
const *spellInfo
, uint32 map_id
, uint32 zone_id
, uint32 area_id
, Player
const* player
)
2640 if( spellInfo
->AreaGroupId
> 0)
2643 AreaGroupEntry
const* groupEntry
= sAreaGroupStore
.LookupEntry(spellInfo
->AreaGroupId
);
2646 for (uint32 i
=0; i
<6; ++i
)
2647 if( groupEntry
->AreaId
[i
] == zone_id
|| groupEntry
->AreaId
[i
] == area_id
)
2649 if (found
|| !groupEntry
->nextGroup
)
2651 // Try search in next group
2652 groupEntry
= sAreaGroupStore
.LookupEntry(groupEntry
->nextGroup
);
2656 return SPELL_FAILED_INCORRECT_AREA
;
2659 // DB base check (if non empty then must fit at least single for allow)
2660 SpellAreaMapBounds saBounds
= spellmgr
.GetSpellAreaMapBounds(spellInfo
->Id
);
2661 if(saBounds
.first
!= saBounds
.second
)
2663 for(SpellAreaMap::const_iterator itr
= saBounds
.first
; itr
!= saBounds
.second
; ++itr
)
2665 if(itr
->second
.IsFitToRequirements(player
,zone_id
,area_id
))
2666 return SPELL_CAST_OK
;
2668 return SPELL_FAILED_INCORRECT_AREA
;
2672 switch(spellInfo
->Id
)
2674 case 23333: // Warsong Flag
2675 case 23335: // Silverwing Flag
2676 return map_id
== 489 && player
&& player
->InBattleGround() ? SPELL_CAST_OK
: SPELL_FAILED_REQUIRES_AREA
;
2677 case 34976: // Netherstorm Flag
2678 return map_id
== 566 && player
&& player
->InBattleGround() ? SPELL_CAST_OK
: SPELL_FAILED_REQUIRES_AREA
;
2679 case 2584: // Waiting to Resurrect
2680 case 22011: // Spirit Heal Channel
2681 case 22012: // Spirit Heal
2682 case 24171: // Resurrection Impact Visual
2683 case 42792: // Recently Dropped Flag
2684 case 43681: // Inactive
2685 case 44535: // Spirit Heal (mana)
2687 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2689 return SPELL_FAILED_INCORRECT_AREA
;
2691 return mapEntry
->IsBattleGround() && player
&& player
->InBattleGround() ? SPELL_CAST_OK
: SPELL_FAILED_REQUIRES_AREA
;
2693 case 44521: // Preparation
2696 return SPELL_FAILED_REQUIRES_AREA
;
2698 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2700 return SPELL_FAILED_INCORRECT_AREA
;
2702 if(!mapEntry
->IsBattleGround())
2703 return SPELL_FAILED_REQUIRES_AREA
;
2705 BattleGround
* bg
= player
->GetBattleGround();
2706 return bg
&& bg
->GetStatus()==STATUS_WAIT_JOIN
? SPELL_CAST_OK
: SPELL_FAILED_REQUIRES_AREA
;
2708 case 32724: // Gold Team (Alliance)
2709 case 32725: // Green Team (Alliance)
2710 case 35774: // Gold Team (Horde)
2711 case 35775: // Green Team (Horde)
2713 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2715 return SPELL_FAILED_INCORRECT_AREA
;
2717 return mapEntry
->IsBattleArena() && player
&& player
->InBattleGround() ? SPELL_CAST_OK
: SPELL_FAILED_REQUIRES_AREA
;
2719 case 32727: // Arena Preparation
2722 return SPELL_FAILED_REQUIRES_AREA
;
2724 MapEntry
const* mapEntry
= sMapStore
.LookupEntry(map_id
);
2726 return SPELL_FAILED_INCORRECT_AREA
;
2728 if(!mapEntry
->IsBattleArena())
2729 return SPELL_FAILED_REQUIRES_AREA
;
2731 BattleGround
* bg
= player
->GetBattleGround();
2732 return bg
&& bg
->GetStatus()==STATUS_WAIT_JOIN
? SPELL_CAST_OK
: SPELL_FAILED_REQUIRES_AREA
;
2736 return SPELL_CAST_OK
;
2739 void SpellMgr::LoadSkillLineAbilityMap()
2741 mSkillLineAbilityMap
.clear();
2743 barGoLink
bar( sSkillLineAbilityStore
.GetNumRows() );
2746 for (uint32 i
= 0; i
< sSkillLineAbilityStore
.GetNumRows(); ++i
)
2749 SkillLineAbilityEntry
const *SkillInfo
= sSkillLineAbilityStore
.LookupEntry(i
);
2753 mSkillLineAbilityMap
.insert(SkillLineAbilityMap::value_type(SkillInfo
->spellId
,SkillInfo
));
2758 sLog
.outString(">> Loaded %u SkillLineAbility MultiMap Data", count
);
2761 DiminishingGroup
GetDiminishingReturnsGroupForSpell(SpellEntry
const* spellproto
, bool triggered
)
2763 // Explicit Diminishing Groups
2764 switch(spellproto
->SpellFamilyName
)
2766 case SPELLFAMILY_ROGUE
:
2769 if (spellproto
->SpellFamilyFlags
& 0x00000200000LL
)
2770 return DIMINISHING_KIDNEYSHOT
;
2772 else if (spellproto
->SpellFamilyFlags
& 0x00001000000LL
)
2773 return DIMINISHING_BLIND_CYCLONE
;
2776 case SPELLFAMILY_WARLOCK
:
2779 if (spellproto
->SpellFamilyFlags
& 0x40840000000LL
)
2780 return DIMINISHING_WARLOCK_FEAR
;
2782 else if (spellproto
->SpellFamilyFlags
& 0x00080000000LL
)
2783 return DIMINISHING_LIMITONLY
;
2786 case SPELLFAMILY_DRUID
:
2789 if (spellproto
->SpellFamilyFlags
& 0x02000000000LL
)
2790 return DIMINISHING_BLIND_CYCLONE
;
2793 case SPELLFAMILY_WARRIOR
:
2795 // Hamstring - limit duration to 10s in PvP
2796 if (spellproto
->SpellFamilyFlags
& 0x00000000002LL
)
2797 return DIMINISHING_LIMITONLY
;
2805 uint32 mechanic
= GetAllSpellMechanicMask(spellproto
);
2806 if (mechanic
== MECHANIC_NONE
) return DIMINISHING_NONE
;
2807 if (mechanic
& (1<<MECHANIC_STUN
)) return triggered
? DIMINISHING_TRIGGER_STUN
: DIMINISHING_CONTROL_STUN
;
2808 if (mechanic
& (1<<MECHANIC_SLEEP
)) return DIMINISHING_SLEEP
;
2809 if (mechanic
& (1<<MECHANIC_POLYMORPH
)) return DIMINISHING_POLYMORPH
;
2810 if (mechanic
& (1<<MECHANIC_ROOT
)) return triggered
? DIMINISHING_TRIGGER_ROOT
: DIMINISHING_CONTROL_ROOT
;
2811 if (mechanic
& (1<<MECHANIC_FEAR
)) return DIMINISHING_FEAR
;
2812 if (mechanic
& (1<<MECHANIC_CHARM
)) return DIMINISHING_CHARM
;
2813 if (mechanic
& (1<<MECHANIC_SILENCE
)) return DIMINISHING_SILENCE
;
2814 if (mechanic
& (1<<DIMINISHING_DISARM
)) return DIMINISHING_DISARM
;
2815 if (mechanic
& (1<<MECHANIC_FREEZE
)) return DIMINISHING_FREEZE
;
2816 if (mechanic
& ((1<<MECHANIC_KNOCKOUT
) | (1<<MECHANIC_SAPPED
))) return DIMINISHING_KNOCKOUT
;
2817 if (mechanic
& (1<<MECHANIC_BANISH
)) return DIMINISHING_BANISH
;
2818 if (mechanic
& (1<<MECHANIC_HORROR
)) return DIMINISHING_DEATHCOIL
;
2821 return DIMINISHING_NONE
;
2824 bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group
)
2828 case DIMINISHING_CONTROL_STUN
:
2829 case DIMINISHING_TRIGGER_STUN
:
2830 case DIMINISHING_KIDNEYSHOT
:
2831 case DIMINISHING_SLEEP
:
2832 case DIMINISHING_CONTROL_ROOT
:
2833 case DIMINISHING_TRIGGER_ROOT
:
2834 case DIMINISHING_FEAR
:
2835 case DIMINISHING_WARLOCK_FEAR
:
2836 case DIMINISHING_CHARM
:
2837 case DIMINISHING_POLYMORPH
:
2838 case DIMINISHING_FREEZE
:
2839 case DIMINISHING_KNOCKOUT
:
2840 case DIMINISHING_BLIND_CYCLONE
:
2841 case DIMINISHING_BANISH
:
2842 case DIMINISHING_LIMITONLY
:
2850 DiminishingReturnsType
GetDiminishingReturnsGroupType(DiminishingGroup group
)
2854 case DIMINISHING_BLIND_CYCLONE
:
2855 case DIMINISHING_CONTROL_STUN
:
2856 case DIMINISHING_TRIGGER_STUN
:
2857 case DIMINISHING_KIDNEYSHOT
:
2859 case DIMINISHING_SLEEP
:
2860 case DIMINISHING_CONTROL_ROOT
:
2861 case DIMINISHING_TRIGGER_ROOT
:
2862 case DIMINISHING_FEAR
:
2863 case DIMINISHING_CHARM
:
2864 case DIMINISHING_POLYMORPH
:
2865 case DIMINISHING_SILENCE
:
2866 case DIMINISHING_DISARM
:
2867 case DIMINISHING_DEATHCOIL
:
2868 case DIMINISHING_FREEZE
:
2869 case DIMINISHING_BANISH
:
2870 case DIMINISHING_WARLOCK_FEAR
:
2871 case DIMINISHING_KNOCKOUT
:
2872 return DRTYPE_PLAYER
;
2880 bool SpellArea::IsFitToRequirements(Player
const* player
, uint32 newZone
, uint32 newArea
) const
2882 if(gender
!=GENDER_NONE
)
2884 // not in expected gender
2885 if(!player
|| gender
!= player
->getGender())
2891 // not in expected race
2892 if(!player
|| !(raceMask
& player
->getRaceMask()))
2898 // not in expected zone
2899 if(newZone
!=areaId
&& newArea
!=areaId
)
2905 // not in expected required quest state
2906 if(!player
|| (!questStartCanActive
|| !player
->IsActiveQuest(questStart
)) && !player
->GetQuestRewardStatus(questStart
))
2912 // not in expected forbidden quest state
2913 if(!player
|| player
->GetQuestRewardStatus(questEnd
))
2919 // not have expected aura
2923 // have expected aura
2924 return player
->HasAura(auraSpell
,0);
2926 // not have expected aura
2927 return !player
->HasAura(-auraSpell
,0);