2010-10-07 15:35:36 +02:00
/*
2012-12-31 23:15:50 +01:00
* Copyright (C) 2008-2013 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2008-11-17 22:07:21 -06:00
*/
2009-10-17 15:51:44 -07:00
2008-11-17 22:07:21 -06:00
#include "SpellMgr.h"
2011-07-26 23:09:28 +02:00
#include "SpellInfo.h"
2008-11-17 22:07:21 -06:00
#include "ObjectMgr.h"
2010-12-21 11:40:20 +01:00
#include "SpellAuras.h"
2008-11-17 22:07:21 -06:00
#include "SpellAuraDefines.h"
2011-07-26 23:09:28 +02:00
#include "SharedDefines.h"
2009-03-27 09:58:20 -06:00
#include "DBCStores.h"
2008-11-17 22:07:21 -06:00
#include "World.h"
#include "Chat.h"
#include "Spell.h"
2010-08-08 04:37:24 +02:00
#include "BattlegroundMgr.h"
2009-05-10 22:48:22 -05:00
#include "CreatureAI.h"
2010-04-18 23:20:07 +02:00
#include "MapManager.h"
2011-01-09 00:00:08 -03:00
#include "BattlegroundIC.h"
2012-03-02 15:23:07 -03:00
#include "BattlefieldWG.h"
#include "BattlefieldMgr.h"
2012-11-17 05:18:37 +01:00
#include "Player.h"
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
bool IsPrimaryProfessionSkill ( uint32 skill )
2008-11-17 22:07:21 -06:00
{
2011-09-15 14:08:17 +02:00
SkillLineEntry const * pSkill = sSkillLineStore . LookupEntry ( skill );
2012-12-22 22:21:33 +01:00
return pSkill && pSkill -> categoryId == SKILL_CATEGORY_PROFESSION ;
}
2009-10-17 15:51:44 -07:00
2012-12-22 22:21:33 +01:00
bool IsWeaponSkill ( uint32 skill )
{
SkillLineEntry const * pSkill = sSkillLineStore . LookupEntry ( skill );
return pSkill && pSkill -> categoryId == SKILL_CATEGORY_WEAPON ;
2009-07-23 18:32:32 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
bool IsPartOfSkillLine ( uint32 skillId , uint32 spellId )
2010-02-20 23:57:54 +01:00
{
2011-07-26 23:09:28 +02:00
SkillLineAbilityMapBounds skillBounds = sSpellMgr -> GetSkillLineAbilityMapBounds ( spellId );
for ( SkillLineAbilityMap :: const_iterator itr = skillBounds . first ; itr != skillBounds . second ; ++ itr )
if ( itr -> second -> skillId == skillId )
2011-05-29 15:46:14 +02:00
return true ;
2011-07-26 23:09:28 +02:00
return false ;
2010-02-20 23:57:54 +01:00
}
2011-07-26 23:09:28 +02:00
DiminishingGroup GetDiminishingReturnsGroupForSpell ( SpellInfo const * spellproto , bool triggered )
2009-07-30 17:16:56 +02:00
{
2011-07-26 23:09:28 +02:00
if ( spellproto -> IsPositive ())
return DIMINISHING_NONE ;
2011-05-05 12:52:40 +02:00
2011-07-26 23:09:28 +02:00
for ( uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
2011-05-05 12:52:40 +02:00
{
2011-07-26 23:09:28 +02:00
if ( spellproto -> Effects [ i ]. ApplyAuraName == SPELL_AURA_MOD_TAUNT )
return DIMINISHING_TAUNT ;
2009-07-30 17:16:56 +02:00
}
2011-05-05 12:52:40 +02:00
2011-07-26 23:09:28 +02:00
// Explicit Diminishing Groups
switch ( spellproto -> SpellFamilyName )
2008-11-17 22:07:21 -06:00
{
2008-11-28 20:19:37 +01:00
case SPELLFAMILY_GENERIC :
{
2011-07-26 23:09:28 +02:00
// Pet charge effects (Infernal Awakening, Demon Charge)
if ( spellproto -> SpellVisual [ 0 ] == 2816 && spellproto -> SpellIconID == 15 )
return DIMINISHING_CONTROLLED_STUN ;
2012-08-28 18:35:26 +02:00
// Frost Tomb
else if ( spellproto -> Id == 48400 )
return DIMINISHING_NONE ;
2011-07-26 23:09:28 +02:00
// Gnaw
else if ( spellproto -> Id == 47481 )
return DIMINISHING_CONTROLLED_STUN ;
2012-11-19 00:42:25 +00:00
// ToC Icehowl Arctic Breath
else if ( spellproto -> SpellVisual [ 0 ] == 14153 )
return DIMINISHING_NONE ;
2008-11-28 20:19:37 +01:00
break ;
}
2011-07-26 23:09:28 +02:00
// Event spells
case SPELLFAMILY_UNK1 :
return DIMINISHING_NONE ;
2008-11-17 22:07:21 -06:00
case SPELLFAMILY_MAGE :
{
2011-07-26 23:09:28 +02:00
// Frostbite
if ( spellproto -> SpellFamilyFlags [ 1 ] & 0x80000000 )
return DIMINISHING_ROOT ;
// Shattered Barrier
else if ( spellproto -> SpellVisual [ 0 ] == 12297 )
return DIMINISHING_ROOT ;
// Deep Freeze
else if ( spellproto -> SpellIconID == 2939 && spellproto -> SpellVisual [ 0 ] == 9963 )
return DIMINISHING_CONTROLLED_STUN ;
// Frost Nova / Freeze (Water Elemental)
else if ( spellproto -> SpellIconID == 193 )
return DIMINISHING_CONTROLLED_ROOT ;
// Dragon's Breath
else if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x800000 )
2011-11-13 00:51:33 +01:00
return DIMINISHING_DRAGONS_BREATH ;
2008-11-17 22:07:21 -06:00
break ;
}
case SPELLFAMILY_WARRIOR :
{
2011-08-19 13:33:53 -03:00
// Hamstring - limit duration to 10s in PvP
if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x2 )
return DIMINISHING_LIMITONLY ;
2011-07-26 23:09:28 +02:00
// Charge Stun (own diminishing)
else if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x01000000 )
return DIMINISHING_CHARGE ;
2008-11-17 22:07:21 -06:00
break ;
}
case SPELLFAMILY_WARLOCK :
{
2011-08-19 13:33:53 -03:00
// Curses/etc
2012-05-30 08:01:02 +02:00
if (( spellproto -> SpellFamilyFlags [ 0 ] & 0x80000000 ) || ( spellproto -> SpellFamilyFlags [ 1 ] & 0x200 ))
2011-08-19 13:33:53 -03:00
return DIMINISHING_LIMITONLY ;
2011-07-26 23:09:28 +02:00
// Seduction
else if ( spellproto -> SpellFamilyFlags [ 1 ] & 0x10000000 )
return DIMINISHING_FEAR ;
2008-11-17 22:07:21 -06:00
break ;
}
2011-07-26 23:09:28 +02:00
case SPELLFAMILY_DRUID :
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
// Pounce
if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x20000 )
return DIMINISHING_OPENING_STUN ;
// Cyclone
else if ( spellproto -> SpellFamilyFlags [ 1 ] & 0x20 )
return DIMINISHING_CYCLONE ;
// Entangling Roots
// Nature's Grasp
else if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x00000200 )
return DIMINISHING_CONTROLLED_ROOT ;
2011-08-19 13:33:53 -03:00
// Faerie Fire
else if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x400 )
return DIMINISHING_LIMITONLY ;
2008-11-17 22:07:21 -06:00
break ;
}
2011-07-26 23:09:28 +02:00
case SPELLFAMILY_ROGUE :
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
// Gouge
if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x8 )
return DIMINISHING_DISORIENT ;
// Blind
else if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x1000000 )
return DIMINISHING_FEAR ;
// Cheap Shot
else if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x400 )
return DIMINISHING_OPENING_STUN ;
2011-08-19 13:33:53 -03:00
// Crippling poison - Limit to 10 seconds in PvP (No SpellFamilyFlags)
else if ( spellproto -> SpellIconID == 163 )
return DIMINISHING_LIMITONLY ;
2008-11-17 22:07:21 -06:00
break ;
}
2011-07-26 23:09:28 +02:00
case SPELLFAMILY_HUNTER :
2008-11-17 22:07:21 -06:00
{
2011-11-13 00:51:33 +01:00
// Hunter's Mark
2011-08-19 13:33:53 -03:00
if (( spellproto -> SpellFamilyFlags [ 0 ] & 0x400 ) && spellproto -> SpellIconID == 538 )
return DIMINISHING_LIMITONLY ;
2011-07-26 23:09:28 +02:00
// Scatter Shot (own diminishing)
2011-08-19 13:33:53 -03:00
else if (( spellproto -> SpellFamilyFlags [ 0 ] & 0x40000 ) && spellproto -> SpellIconID == 132 )
2011-07-26 23:09:28 +02:00
return DIMINISHING_SCATTER_SHOT ;
// Entrapment (own diminishing)
else if ( spellproto -> SpellVisual [ 0 ] == 7484 && spellproto -> SpellIconID == 20 )
return DIMINISHING_ENTRAPMENT ;
// Wyvern Sting mechanic is MECHANIC_SLEEP but the diminishing is DIMINISHING_DISORIENT
else if (( spellproto -> SpellFamilyFlags [ 1 ] & 0x1000 ) && spellproto -> SpellIconID == 1721 )
return DIMINISHING_DISORIENT ;
// Freezing Arrow
else if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x8 )
return DIMINISHING_DISORIENT ;
2008-11-17 22:07:21 -06:00
break ;
}
2011-07-26 23:09:28 +02:00
case SPELLFAMILY_PALADIN :
{
2011-08-19 13:33:53 -03:00
// Judgement of Justice - limit duration to 10s in PvP
if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x100000 )
return DIMINISHING_LIMITONLY ;
2011-07-26 23:09:28 +02:00
// Turn Evil
2011-08-19 13:33:53 -03:00
else if (( spellproto -> SpellFamilyFlags [ 1 ] & 0x804000 ) && spellproto -> SpellIconID == 309 )
2011-07-26 23:09:28 +02:00
return DIMINISHING_FEAR ;
2008-12-29 12:22:49 -06:00
break ;
2011-07-26 23:09:28 +02:00
}
case SPELLFAMILY_DEATHKNIGHT :
2009-02-18 16:26:02 -06:00
{
2011-07-26 23:09:28 +02:00
// Hungering Cold (no flags)
if ( spellproto -> SpellIconID == 2797 )
return DIMINISHING_DISORIENT ;
2011-08-19 13:33:53 -03:00
// Mark of Blood
else if (( spellproto -> SpellFamilyFlags [ 0 ] & 0x10000000 ) && spellproto -> SpellIconID == 2285 )
return DIMINISHING_LIMITONLY ;
2011-07-26 23:09:28 +02:00
break ;
2009-02-18 16:26:02 -06:00
}
2008-11-20 18:13:10 -06:00
default :
2011-07-26 23:09:28 +02:00
break ;
2008-11-20 18:13:10 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// Lastly - Set diminishing depending on mechanic
uint32 mechanic = spellproto -> GetAllEffectsMechanicMask ();
if ( mechanic & ( 1 << MECHANIC_CHARM ))
return DIMINISHING_MIND_CONTROL ;
if ( mechanic & ( 1 << MECHANIC_SILENCE ))
return DIMINISHING_SILENCE ;
if ( mechanic & ( 1 << MECHANIC_SLEEP ))
return DIMINISHING_SLEEP ;
if ( mechanic & (( 1 << MECHANIC_SAPPED ) | ( 1 << MECHANIC_POLYMORPH ) | ( 1 << MECHANIC_SHACKLE )))
return DIMINISHING_DISORIENT ;
// Mechanic Knockout, except Blast Wave
if ( mechanic & ( 1 << MECHANIC_KNOCKOUT ) && spellproto -> SpellIconID != 292 )
return DIMINISHING_DISORIENT ;
if ( mechanic & ( 1 << MECHANIC_DISARM ))
return DIMINISHING_DISARM ;
if ( mechanic & ( 1 << MECHANIC_FEAR ))
return DIMINISHING_FEAR ;
if ( mechanic & ( 1 << MECHANIC_STUN ))
return triggered ? DIMINISHING_STUN : DIMINISHING_CONTROLLED_STUN ;
if ( mechanic & ( 1 << MECHANIC_BANISH ))
return DIMINISHING_BANISH ;
if ( mechanic & ( 1 << MECHANIC_ROOT ))
return triggered ? DIMINISHING_ROOT : DIMINISHING_CONTROLLED_ROOT ;
2012-05-30 08:01:02 +02:00
if ( mechanic & ( 1 << MECHANIC_HORROR ))
return DIMINISHING_HORROR ;
2011-07-26 23:09:28 +02:00
return DIMINISHING_NONE ;
}
DiminishingReturnsType GetDiminishingReturnsGroupType ( DiminishingGroup group )
2008-11-20 18:13:10 -06:00
{
2011-07-26 23:09:28 +02:00
switch ( group )
2008-11-20 18:13:10 -06:00
{
2011-07-26 23:09:28 +02:00
case DIMINISHING_TAUNT :
case DIMINISHING_CONTROLLED_STUN :
case DIMINISHING_STUN :
case DIMINISHING_OPENING_STUN :
case DIMINISHING_CYCLONE :
case DIMINISHING_CHARGE :
return DRTYPE_ALL ;
2011-08-19 13:33:53 -03:00
case DIMINISHING_LIMITONLY :
case DIMINISHING_NONE :
return DRTYPE_NONE ;
2008-11-17 22:07:21 -06:00
default :
2011-07-26 23:09:28 +02:00
return DRTYPE_PLAYER ;
2008-11-17 22:07:21 -06:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
DiminishingLevels GetDiminishingReturnsMaxLevel ( DiminishingGroup group )
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
switch ( group )
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
case DIMINISHING_TAUNT :
return DIMINISHING_LEVEL_TAUNT_IMMUNE ;
2008-11-17 22:07:21 -06:00
default :
2011-07-26 23:09:28 +02:00
return DIMINISHING_LEVEL_IMMUNE ;
2008-11-17 22:07:21 -06:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
int32 GetDiminishingReturnsLimitDuration ( DiminishingGroup group , SpellInfo const * spellproto )
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
if ( ! IsDiminishingReturnsGroupDurationLimited ( group ))
return 0 ;
2010-01-10 13:48:57 +01:00
2011-07-26 23:09:28 +02:00
// Explicit diminishing duration
2010-06-23 03:45:44 +02:00
switch ( spellproto -> SpellFamilyName )
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
case SPELLFAMILY_DRUID :
{
// Faerie Fire - limit to 40 seconds in PvP (3.1)
if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x400 )
return 40 * IN_MILLISECONDS ;
2010-06-23 03:45:44 +02:00
break ;
2011-07-26 23:09:28 +02:00
}
2010-06-28 20:34:11 +02:00
case SPELLFAMILY_HUNTER :
2011-07-26 23:09:28 +02:00
{
// Wyvern Sting
if ( spellproto -> SpellFamilyFlags [ 1 ] & 0x1000 )
return 6 * IN_MILLISECONDS ;
// Hunter's Mark
if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x400 )
return 120 * IN_MILLISECONDS ;
2010-06-28 20:34:11 +02:00
break ;
2011-07-26 23:09:28 +02:00
}
case SPELLFAMILY_PALADIN :
{
// Repentance - limit to 6 seconds in PvP
if ( spellproto -> SpellFamilyFlags [ 0 ] & 0x4 )
return 6 * IN_MILLISECONDS ;
break ;
}
case SPELLFAMILY_WARLOCK :
{
// Banish - limit to 6 seconds in PvP
if ( spellproto -> SpellFamilyFlags [ 1 ] & 0x8000000 )
return 6 * IN_MILLISECONDS ;
// Curse of Tongues - limit to 12 seconds in PvP
else if ( spellproto -> SpellFamilyFlags [ 2 ] & 0x800 )
return 12 * IN_MILLISECONDS ;
// Curse of Elements - limit to 120 seconds in PvP
else if ( spellproto -> SpellFamilyFlags [ 1 ] & 0x200 )
return 120 * IN_MILLISECONDS ;
2010-09-05 14:34:48 -07:00
break ;
2011-07-26 23:09:28 +02:00
}
2010-06-23 03:45:44 +02:00
default :
break ;
2009-03-18 21:04:46 +01:00
}
2009-10-17 15:51:44 -07:00
2012-09-04 17:15:37 +03:00
return 8 * IN_MILLISECONDS ;
2011-07-26 23:09:28 +02:00
}
bool IsDiminishingReturnsGroupDurationLimited ( DiminishingGroup group )
{
switch ( group )
2009-03-18 21:04:46 +01:00
{
2011-11-13 00:51:33 +01:00
case DIMINISHING_BANISH :
2011-07-26 23:09:28 +02:00
case DIMINISHING_CONTROLLED_STUN :
case DIMINISHING_CONTROLLED_ROOT :
2011-11-13 00:51:33 +01:00
case DIMINISHING_CYCLONE :
case DIMINISHING_DISORIENT :
case DIMINISHING_ENTRAPMENT :
2011-07-26 23:09:28 +02:00
case DIMINISHING_FEAR :
2011-11-13 00:51:33 +01:00
case DIMINISHING_HORROR :
2011-07-26 23:09:28 +02:00
case DIMINISHING_MIND_CONTROL :
case DIMINISHING_OPENING_STUN :
2011-11-13 00:51:33 +01:00
case DIMINISHING_ROOT :
case DIMINISHING_STUN :
2011-07-26 23:09:28 +02:00
case DIMINISHING_SLEEP :
2011-11-13 00:51:33 +01:00
case DIMINISHING_LIMITONLY :
2009-03-18 21:04:46 +01:00
return true ;
default :
2011-07-26 23:09:28 +02:00
return false ;
2009-03-18 21:04:46 +01:00
}
2011-07-26 23:09:28 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellMgr :: SpellMgr ()
{
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellMgr ::~ SpellMgr ()
{
UnloadSpellInfoStore ();
}
/// Some checks for spells, to prevent adding deprecated/broken spells for trainers, spell book, etc
2011-11-07 11:18:00 -06:00
bool SpellMgr :: IsSpellValid ( SpellInfo const * spellInfo , Player * player , bool msg )
2011-07-26 23:09:28 +02:00
{
// not exist
if ( ! spellInfo )
return false ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
bool need_check_reagents = false ;
// check effects
for ( uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
{
switch ( spellInfo -> Effects [ i ]. Effect )
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
case 0 :
continue ;
// craft spell for crafting non-existed item (break client recipes list show)
case SPELL_EFFECT_CREATE_ITEM :
case SPELL_EFFECT_CREATE_ITEM_2 :
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
if ( spellInfo -> Effects [ i ]. ItemType == 0 )
{
// skip auto-loot crafting spells, its not need explicit item info (but have special fake items sometime)
if ( ! spellInfo -> IsLootCrafting ())
2009-04-09 17:32:22 +02:00
{
2011-07-26 23:09:28 +02:00
if ( msg )
2009-04-09 17:32:22 +02:00
{
2011-11-07 11:18:00 -06:00
if ( player )
2012-11-17 05:18:37 +01:00
ChatHandler ( player -> GetSession ()). PSendSysMessage ( "Craft spell %u not have create item entry." , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
else
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Craft spell %u not have create item entry." , spellInfo -> Id );
2009-04-09 17:32:22 +02:00
}
2008-11-17 22:07:21 -06:00
return false ;
2011-07-26 23:09:28 +02:00
}
}
// also possible IsLootCrafting case but fake item must exist anyway
else if ( ! sObjectMgr -> GetItemTemplate ( spellInfo -> Effects [ i ]. ItemType ))
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
if ( msg )
2008-11-17 22:07:21 -06:00
{
2011-11-07 11:18:00 -06:00
if ( player )
2012-11-17 05:18:37 +01:00
ChatHandler ( player -> GetSession ()). PSendSysMessage ( "Craft spell %u create not-exist in DB item (Entry: %u) and then..." , spellInfo -> Id , spellInfo -> Effects [ i ]. ItemType );
2011-07-26 23:09:28 +02:00
else
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Craft spell %u create not-exist in DB item (Entry: %u) and then..." , spellInfo -> Id , spellInfo -> Effects [ i ]. ItemType );
2008-11-17 22:07:21 -06:00
}
2011-07-26 23:09:28 +02:00
return false ;
2011-06-17 12:00:11 +02:00
}
2011-07-26 23:09:28 +02:00
need_check_reagents = true ;
break ;
}
case SPELL_EFFECT_LEARN_SPELL :
{
SpellInfo const * spellInfo2 = sSpellMgr -> GetSpellInfo ( spellInfo -> Effects [ i ]. TriggerSpell );
2011-11-07 11:18:00 -06:00
if ( ! IsSpellValid ( spellInfo2 , player , msg ))
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
if ( msg )
2008-11-17 22:07:21 -06:00
{
2011-11-07 11:18:00 -06:00
if ( player )
2012-11-17 05:18:37 +01:00
ChatHandler ( player -> GetSession ()). PSendSysMessage ( "Spell %u learn to broken spell %u, and then..." , spellInfo -> Id , spellInfo -> Effects [ i ]. TriggerSpell );
2011-07-26 23:09:28 +02:00
else
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u learn to invalid spell %u, and then..." , spellInfo -> Id , spellInfo -> Effects [ i ]. TriggerSpell );
2008-11-17 22:07:21 -06:00
}
2011-07-26 23:09:28 +02:00
return false ;
2011-06-17 12:00:11 +02:00
}
2011-07-26 23:09:28 +02:00
break ;
2008-11-17 22:07:21 -06:00
}
}
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( need_check_reagents )
{
for ( uint8 j = 0 ; j < MAX_SPELL_REAGENTS ; ++ j )
{
if ( spellInfo -> Reagent [ j ] > 0 && ! sObjectMgr -> GetItemTemplate ( spellInfo -> Reagent [ j ]))
{
if ( msg )
{
2011-11-07 11:18:00 -06:00
if ( player )
2012-11-17 05:18:37 +01:00
ChatHandler ( player -> GetSession ()). PSendSysMessage ( "Craft spell %u have not-exist reagent in DB item (Entry: %u) and then..." , spellInfo -> Id , spellInfo -> Reagent [ j ]);
2011-07-26 23:09:28 +02:00
else
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Craft spell %u have not-exist reagent in DB item (Entry: %u) and then..." , spellInfo -> Id , spellInfo -> Reagent [ j ]);
2011-07-26 23:09:28 +02:00
}
return false ;
}
}
}
2009-10-17 15:51:44 -07:00
2008-11-17 22:07:21 -06:00
return true ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 SpellMgr :: GetSpellDifficultyId ( uint32 spellId ) const
2009-08-06 11:24:14 -05:00
{
2011-07-26 23:09:28 +02:00
SpellDifficultySearcherMap :: const_iterator i = mSpellDifficultySearcherMap . find ( spellId );
return i == mSpellDifficultySearcherMap . end () ? 0 : ( * i ). second ;
2009-08-06 11:24:14 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: SetSpellDifficultyId ( uint32 spellId , uint32 id )
2009-08-06 11:24:14 -05:00
{
2011-07-26 23:09:28 +02:00
mSpellDifficultySearcherMap [ spellId ] = id ;
2009-08-06 11:24:14 -05:00
}
2009-10-17 15:51:44 -07:00
2011-08-19 14:53:40 +02:00
uint32 SpellMgr :: GetSpellIdForDifficulty ( uint32 spellId , Unit const * caster ) const
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
if ( ! GetSpellInfo ( spellId ))
return spellId ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( ! caster || ! caster -> GetMap () || ! caster -> GetMap () -> IsDungeon ())
return spellId ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 mode = uint32 ( caster -> GetMap () -> GetSpawnMode ());
if ( mode >= MAX_DIFFICULTY )
2008-11-17 22:07:21 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SPELLS_AURAS , "SpellMgr::GetSpellIdForDifficulty: Incorrect Difficulty for spell %u." , spellId );
2011-07-26 23:09:28 +02:00
return spellId ; //return source spell
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 difficultyId = GetSpellDifficultyId ( spellId );
if ( ! difficultyId )
return spellId ; //return source spell, it has only REGULAR_DIFFICULTY
2009-10-17 15:51:44 -07:00
2011-09-15 14:08:17 +02:00
SpellDifficultyEntry const * difficultyEntry = sSpellDifficultyStore . LookupEntry ( difficultyId );
2011-07-26 23:09:28 +02:00
if ( ! difficultyEntry )
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
sLog -> outDebug ( LOG_FILTER_SPELLS_AURAS , "SpellMgr::GetSpellIdForDifficulty: SpellDifficultyEntry not found for spell %u. This should never happen." , spellId );
return spellId ; //return source spell
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( difficultyEntry -> SpellID [ mode ] <= 0 && mode > DUNGEON_DIFFICULTY_HEROIC )
{
sLog -> outDebug ( LOG_FILTER_SPELLS_AURAS , "SpellMgr::GetSpellIdForDifficulty: spell %u mode %u spell is NULL, using mode %u" , spellId , mode , mode - 2 );
mode -= 2 ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( difficultyEntry -> SpellID [ mode ] <= 0 )
2008-11-17 22:07:21 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "SpellMgr::GetSpellIdForDifficulty: spell %u mode %u spell is 0. Check spelldifficulty_dbc!" , spellId , mode );
2011-07-26 23:09:28 +02:00
return spellId ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
sLog -> outDebug ( LOG_FILTER_SPELLS_AURAS , "SpellMgr::GetSpellIdForDifficulty: spellid for spell %u in mode %u is %d" , spellId , mode , difficultyEntry -> SpellID [ mode ]);
return uint32 ( difficultyEntry -> SpellID [ mode ]);
}
2009-10-17 15:51:44 -07:00
2011-08-19 14:53:40 +02:00
SpellInfo const * SpellMgr :: GetSpellForDifficultyFromSpell ( SpellInfo const * spell , Unit const * caster ) const
2011-07-26 23:09:28 +02:00
{
uint32 newSpellId = GetSpellIdForDifficulty ( spell -> Id , caster );
SpellInfo const * newSpell = GetSpellInfo ( newSpellId );
if ( ! newSpell )
2009-06-07 22:13:17 +02:00
{
2011-07-26 23:09:28 +02:00
sLog -> outDebug ( LOG_FILTER_SPELLS_AURAS , "SpellMgr::GetSpellForDifficultyFromSpell: spell %u not found. Check spelldifficulty_dbc!" , newSpellId );
return spell ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
sLog -> outDebug ( LOG_FILTER_SPELLS_AURAS , "SpellMgr::GetSpellForDifficultyFromSpell: Spell id for instance mode is %u (original %u)" , newSpell -> Id , spell -> Id );
return newSpell ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellChainNode const * SpellMgr :: GetSpellChainNode ( uint32 spell_id ) const
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
SpellChainMap :: const_iterator itr = mSpellChains . find ( spell_id );
if ( itr == mSpellChains . end ())
return NULL ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
return & itr -> second ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 SpellMgr :: GetFirstSpellInChain ( uint32 spell_id ) const
{
if ( SpellChainNode const * node = GetSpellChainNode ( spell_id ))
return node -> first -> Id ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
return spell_id ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 SpellMgr :: GetLastSpellInChain ( uint32 spell_id ) const
{
if ( SpellChainNode const * node = GetSpellChainNode ( spell_id ))
return node -> last -> Id ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
return spell_id ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 SpellMgr :: GetNextSpellInChain ( uint32 spell_id ) const
{
if ( SpellChainNode const * node = GetSpellChainNode ( spell_id ))
2011-08-03 11:23:08 +02:00
if ( node -> next )
return node -> next -> Id ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
return 0 ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 SpellMgr :: GetPrevSpellInChain ( uint32 spell_id ) const
{
if ( SpellChainNode const * node = GetSpellChainNode ( spell_id ))
2011-08-03 11:23:08 +02:00
if ( node -> prev )
return node -> prev -> Id ;
2010-04-18 23:20:07 +02:00
2011-07-26 23:09:28 +02:00
return 0 ;
}
2010-04-18 23:20:07 +02:00
2011-07-26 23:09:28 +02:00
uint8 SpellMgr :: GetSpellRank ( uint32 spell_id ) const
{
if ( SpellChainNode const * node = GetSpellChainNode ( spell_id ))
return node -> rank ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
return 0 ;
}
2010-04-18 23:20:07 +02:00
2011-07-26 23:09:28 +02:00
uint32 SpellMgr :: GetSpellWithRank ( uint32 spell_id , uint32 rank , bool strict ) const
{
if ( SpellChainNode const * node = GetSpellChainNode ( spell_id ))
{
if ( rank != node -> rank )
return GetSpellWithRank ( node -> rank < rank ? node -> next -> Id : node -> prev -> Id , rank , strict );
}
else if ( strict && rank > 1 )
return 0 ;
return spell_id ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellRequiredMapBounds SpellMgr :: GetSpellsRequiredForSpellBounds ( uint32 spell_id ) const
{
2013-01-02 09:53:43 +01:00
return mSpellReq . equal_range ( spell_id );
2011-07-26 23:09:28 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellsRequiringSpellMapBounds SpellMgr :: GetSpellsRequiringSpellBounds ( uint32 spell_id ) const
{
2013-01-02 09:53:43 +01:00
return mSpellsReqSpell . equal_range ( spell_id );
2011-07-26 23:09:28 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
bool SpellMgr :: IsSpellRequiringSpell ( uint32 spellid , uint32 req_spellid ) const
{
SpellsRequiringSpellMapBounds spellsRequiringSpell = GetSpellsRequiringSpellBounds ( req_spellid );
for ( SpellsRequiringSpellMap :: const_iterator itr = spellsRequiringSpell . first ; itr != spellsRequiringSpell . second ; ++ itr )
2009-05-25 16:50:01 -05:00
{
2011-07-26 23:09:28 +02:00
if ( itr -> second == spellid )
return true ;
2009-05-25 16:50:01 -05:00
}
2011-07-26 23:09:28 +02:00
return false ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
const SpellsRequiringSpellMap SpellMgr :: GetSpellsRequiringSpell ()
{
return this -> mSpellsReqSpell ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 SpellMgr :: GetSpellRequired ( uint32 spell_id ) const
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
SpellRequiredMap :: const_iterator itr = mSpellReq . find ( spell_id );
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( itr == mSpellReq . end ())
return 0 ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
return itr -> second ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellLearnSkillNode const * SpellMgr :: GetSpellLearnSkill ( uint32 spell_id ) const
{
SpellLearnSkillMap :: const_iterator itr = mSpellLearnSkills . find ( spell_id );
if ( itr != mSpellLearnSkills . end ())
return & itr -> second ;
else
return NULL ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellLearnSpellMapBounds SpellMgr :: GetSpellLearnSpellMapBounds ( uint32 spell_id ) const
2008-11-17 22:07:21 -06:00
{
2013-01-02 09:53:43 +01:00
return mSpellLearnSpells . equal_range ( spell_id );
2011-07-26 23:09:28 +02:00
}
2010-12-19 17:06:33 +01:00
2011-07-26 23:09:28 +02:00
bool SpellMgr :: IsSpellLearnSpell ( uint32 spell_id ) const
{
return mSpellLearnSpells . find ( spell_id ) != mSpellLearnSpells . end ();
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
bool SpellMgr :: IsSpellLearnToSpell ( uint32 spell_id1 , uint32 spell_id2 ) const
{
SpellLearnSpellMapBounds bounds = GetSpellLearnSpellMapBounds ( spell_id1 );
for ( SpellLearnSpellMap :: const_iterator i = bounds . first ; i != bounds . second ; ++ i )
if ( i -> second . spell == spell_id2 )
return true ;
return false ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellTargetPosition const * SpellMgr :: GetSpellTargetPosition ( uint32 spell_id ) const
{
SpellTargetPositionMap :: const_iterator itr = mSpellTargetPositions . find ( spell_id );
if ( itr != mSpellTargetPositions . end ())
return & itr -> second ;
return NULL ;
}
SpellSpellGroupMapBounds SpellMgr :: GetSpellSpellGroupMapBounds ( uint32 spell_id ) const
{
spell_id = GetFirstSpellInChain ( spell_id );
2013-01-02 09:53:43 +01:00
return mSpellSpellGroup . equal_range ( spell_id );
2011-07-26 23:09:28 +02:00
}
2012-10-07 01:31:43 +02:00
bool SpellMgr :: IsSpellMemberOfSpellGroup ( uint32 spellid , SpellGroup groupid ) const
2011-07-26 23:09:28 +02:00
{
SpellSpellGroupMapBounds spellGroup = GetSpellSpellGroupMapBounds ( spellid );
2012-05-30 08:01:02 +02:00
for ( SpellSpellGroupMap :: const_iterator itr = spellGroup . first ; itr != spellGroup . second ; ++ itr )
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
if ( itr -> second == groupid )
return true ;
2008-11-17 22:07:21 -06:00
}
2011-07-26 23:09:28 +02:00
return false ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellGroupSpellMapBounds SpellMgr :: GetSpellGroupSpellMapBounds ( SpellGroup group_id ) const
{
2013-01-02 09:53:43 +01:00
return mSpellGroupSpell . equal_range ( group_id );
2011-07-26 23:09:28 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: GetSetOfSpellsInSpellGroup ( SpellGroup group_id , std :: set < uint32 >& foundSpells ) const
{
std :: set < SpellGroup > usedGroups ;
GetSetOfSpellsInSpellGroup ( group_id , foundSpells , usedGroups );
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: GetSetOfSpellsInSpellGroup ( SpellGroup group_id , std :: set < uint32 >& foundSpells , std :: set < SpellGroup >& usedGroups ) const
{
if ( usedGroups . find ( group_id ) != usedGroups . end ())
return ;
usedGroups . insert ( group_id );
SpellGroupSpellMapBounds groupSpell = GetSpellGroupSpellMapBounds ( group_id );
2012-05-30 08:01:02 +02:00
for ( SpellGroupSpellMap :: const_iterator itr = groupSpell . first ; itr != groupSpell . second ; ++ itr )
2011-07-26 23:09:28 +02:00
{
if ( itr -> second < 0 )
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
SpellGroup currGroup = ( SpellGroup ) abs ( itr -> second );
GetSetOfSpellsInSpellGroup ( currGroup , foundSpells , usedGroups );
2008-11-17 22:07:21 -06:00
}
2011-07-26 23:09:28 +02:00
else
{
foundSpells . insert ( itr -> second );
}
}
}
2009-10-17 15:51:44 -07:00
2011-10-18 23:27:39 +02:00
bool SpellMgr :: AddSameEffectStackRuleSpellGroups ( SpellInfo const * spellInfo , int32 amount , std :: map < SpellGroup , int32 >& groups ) const
{
2011-10-18 23:38:55 +02:00
uint32 spellId = spellInfo -> GetFirstRankSpell () -> Id ;
SpellSpellGroupMapBounds spellGroup = GetSpellSpellGroupMapBounds ( spellId );
// Find group with SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT if it belongs to one
2012-05-30 08:01:02 +02:00
for ( SpellSpellGroupMap :: const_iterator itr = spellGroup . first ; itr != spellGroup . second ; ++ itr )
2011-10-18 23:38:55 +02:00
{
SpellGroup group = itr -> second ;
SpellGroupStackMap :: const_iterator found = mSpellGroupStack . find ( group );
2011-10-18 23:27:39 +02:00
if ( found != mSpellGroupStack . end ())
2011-10-18 23:38:55 +02:00
{
if ( found -> second == SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT )
{
// Put the highest amount in the map
if ( groups . find ( group ) == groups . end ())
groups [ group ] = amount ;
else
{
int32 curr_amount = groups [ group ];
// Take absolute value because this also counts for the highest negative aura
if ( abs ( curr_amount ) < abs ( amount ))
groups [ group ] = amount ;
}
// return because a spell should be in only one SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT group
return true ;
}
}
}
// Not in a SPELL_GROUP_STACK_RULE_EXCLUSIVE_SAME_EFFECT group, so return false
return false ;
2011-10-18 23:27:39 +02:00
}
2011-07-26 23:09:28 +02:00
SpellGroupStackRule SpellMgr :: CheckSpellGroupStackRules ( SpellInfo const * spellInfo1 , SpellInfo const * spellInfo2 ) const
{
uint32 spellid_1 = spellInfo1 -> GetFirstRankSpell () -> Id ;
uint32 spellid_2 = spellInfo2 -> GetFirstRankSpell () -> Id ;
if ( spellid_1 == spellid_2 )
return SPELL_GROUP_STACK_RULE_DEFAULT ;
// find SpellGroups which are common for both spells
SpellSpellGroupMapBounds spellGroup1 = GetSpellSpellGroupMapBounds ( spellid_1 );
std :: set < SpellGroup > groups ;
2012-05-30 08:01:02 +02:00
for ( SpellSpellGroupMap :: const_iterator itr = spellGroup1 . first ; itr != spellGroup1 . second ; ++ itr )
2011-07-26 23:09:28 +02:00
{
if ( IsSpellMemberOfSpellGroup ( spellid_2 , itr -> second ))
2008-11-26 15:14:03 -06:00
{
2011-07-26 23:09:28 +02:00
bool add = true ;
SpellGroupSpellMapBounds groupSpell = GetSpellGroupSpellMapBounds ( itr -> second );
2012-05-30 08:01:02 +02:00
for ( SpellGroupSpellMap :: const_iterator itr2 = groupSpell . first ; itr2 != groupSpell . second ; ++ itr2 )
2008-11-26 15:14:03 -06:00
{
2011-07-26 23:09:28 +02:00
if ( itr2 -> second < 0 )
{
SpellGroup currGroup = ( SpellGroup ) abs ( itr2 -> second );
if ( IsSpellMemberOfSpellGroup ( spellid_1 , currGroup ) && IsSpellMemberOfSpellGroup ( spellid_2 , currGroup ))
{
add = false ;
break ;
}
}
2008-11-26 15:14:03 -06:00
}
2011-07-26 23:09:28 +02:00
if ( add )
groups . insert ( itr -> second );
2008-11-26 15:14:03 -06:00
}
2011-07-26 23:09:28 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellGroupStackRule rule = SPELL_GROUP_STACK_RULE_DEFAULT ;
2012-05-30 08:01:02 +02:00
for ( std :: set < SpellGroup >:: iterator itr = groups . begin (); itr != groups . end (); ++ itr )
2011-07-26 23:09:28 +02:00
{
SpellGroupStackMap :: const_iterator found = mSpellGroupStack . find ( * itr );
if ( found != mSpellGroupStack . end ())
rule = found -> second ;
if ( rule )
break ;
}
return rule ;
}
SpellProcEventEntry const * SpellMgr :: GetSpellProcEvent ( uint32 spellId ) const
{
SpellProcEventMap :: const_iterator itr = mSpellProcEventMap . find ( spellId );
if ( itr != mSpellProcEventMap . end ())
return & itr -> second ;
return NULL ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
bool SpellMgr :: IsSpellProcEventCanTriggeredBy ( SpellProcEventEntry const * spellProcEvent , uint32 EventProcFlag , SpellInfo const * procSpell , uint32 procFlags , uint32 procExtra , bool active )
2008-11-26 15:14:03 -06:00
{
// No extra req need
uint32 procEvent_procEx = PROC_EX_NONE ;
2009-10-17 15:51:44 -07:00
2008-11-26 15:14:03 -06:00
// check prockFlags for condition
2010-04-07 19:14:10 +02:00
if (( procFlags & EventProcFlag ) == 0 )
2008-11-26 15:14:03 -06:00
return false ;
2009-10-17 15:51:44 -07:00
2009-05-17 18:00:33 +02:00
bool hasFamilyMask = false ;
2009-10-17 15:51:44 -07:00
2009-05-15 16:59:27 +02:00
/* Check Periodic Auras
2009-10-17 15:51:44 -07:00
2009-07-18 22:18:47 +02:00
*Dots can trigger if spell has no PROC_FLAG_SUCCESSFUL_NEGATIVE_MAGIC_SPELL
nor PROC_FLAG_TAKEN_POSITIVE_MAGIC_SPELL
2009-10-17 15:51:44 -07:00
2009-07-18 22:18:47 +02:00
*Only Hots can trigger if spell has PROC_FLAG_TAKEN_POSITIVE_MAGIC_SPELL
2009-10-17 15:51:44 -07:00
2009-07-18 22:18:47 +02:00
*Only dots can trigger if spell has both positivity flags or PROC_FLAG_SUCCESSFUL_NEGATIVE_MAGIC_SPELL
2009-10-17 15:51:44 -07:00
2009-07-18 22:18:47 +02:00
*Aura has to have PROC_FLAG_TAKEN_POSITIVE_MAGIC_SPELL or spellfamily specified to trigger from Hot
2009-10-17 15:51:44 -07:00
2009-05-15 16:59:27 +02:00
*/
2009-10-17 15:51:44 -07:00
2010-10-08 19:17:49 +02:00
if ( procFlags & PROC_FLAG_DONE_PERIODIC )
2009-05-15 16:59:27 +02:00
{
2010-10-08 19:17:49 +02:00
if ( EventProcFlag & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG )
2009-05-15 16:59:27 +02:00
{
2009-06-15 18:27:41 +02:00
if ( ! ( procExtra & PROC_EX_INTERNAL_DOT ))
2009-05-15 16:59:27 +02:00
return false ;
}
2009-07-18 22:18:47 +02:00
else if ( procExtra & PROC_EX_INTERNAL_HOT )
procExtra |= PROC_EX_INTERNAL_REQ_FAMILY ;
2010-10-08 19:17:49 +02:00
else if ( EventProcFlag & PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS )
2009-08-23 11:33:00 -05:00
return false ;
2009-05-15 16:59:27 +02:00
}
2009-10-17 15:51:44 -07:00
2010-10-08 19:17:49 +02:00
if ( procFlags & PROC_FLAG_TAKEN_PERIODIC )
2009-05-15 16:59:27 +02:00
{
2010-10-08 19:17:49 +02:00
if ( EventProcFlag & PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS )
2009-05-15 16:59:27 +02:00
{
2009-06-15 18:27:41 +02:00
if ( ! ( procExtra & PROC_EX_INTERNAL_DOT ))
2009-05-15 16:59:27 +02:00
return false ;
}
2009-07-18 22:18:47 +02:00
else if ( procExtra & PROC_EX_INTERNAL_HOT )
procExtra |= PROC_EX_INTERNAL_REQ_FAMILY ;
2010-10-08 19:17:49 +02:00
else if ( EventProcFlag & PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_POS )
2009-08-23 11:33:00 -05:00
return false ;
2009-05-15 16:59:27 +02:00
}
2009-07-11 20:06:02 +02:00
// Trap casts are active by default
2010-10-08 19:17:49 +02:00
if ( procFlags & PROC_FLAG_DONE_TRAP_ACTIVATION )
2009-07-11 20:06:02 +02:00
active = true ;
2009-10-17 15:51:44 -07:00
2008-11-26 15:14:03 -06:00
// Always trigger for this
2009-07-11 20:06:02 +02:00
if ( procFlags & ( PROC_FLAG_KILLED | PROC_FLAG_KILL | PROC_FLAG_DEATH ))
2008-11-26 15:14:03 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2008-11-26 15:14:03 -06:00
if ( spellProcEvent ) // Exist event data
{
// Store extra req
procEvent_procEx = spellProcEvent -> procEx ;
2009-10-17 15:51:44 -07:00
2008-11-26 15:14:03 -06:00
// For melee triggers
if ( procSpell == NULL )
{
// Check (if set) for school (melee attack have Normal school)
2010-04-07 19:14:10 +02:00
if ( spellProcEvent -> schoolMask && ( spellProcEvent -> schoolMask & SPELL_SCHOOL_MASK_NORMAL ) == 0 )
2008-11-26 15:14:03 -06:00
return false ;
}
else // For spells need check school/spell family/family mask
{
// Check (if set) for school
2010-04-07 19:14:10 +02:00
if ( spellProcEvent -> schoolMask && ( spellProcEvent -> schoolMask & procSpell -> SchoolMask ) == 0 )
2008-11-26 15:14:03 -06:00
return false ;
2009-10-17 15:51:44 -07:00
2008-11-26 15:14:03 -06:00
// Check (if set) for spellFamilyName
2010-04-07 19:14:10 +02:00
if ( spellProcEvent -> spellFamilyName && ( spellProcEvent -> spellFamilyName != procSpell -> SpellFamilyName ))
2008-11-26 15:14:03 -06:00
return false ;
2009-10-17 15:51:44 -07:00
2008-11-26 15:14:03 -06:00
// spellFamilyName is Ok need check for spellFamilyMask if present
2010-04-07 19:14:10 +02:00
if ( spellProcEvent -> spellFamilyMask )
2008-11-26 15:14:03 -06:00
{
2011-06-28 13:53:48 +02:00
if ( ! ( spellProcEvent -> spellFamilyMask & procSpell -> SpellFamilyFlags ))
2008-11-26 15:14:03 -06:00
return false ;
2009-05-17 18:00:33 +02:00
hasFamilyMask = true ;
2009-07-09 23:49:46 +02:00
// Some spells are not considered as active even with have spellfamilyflags
if ( ! ( procEvent_procEx & PROC_EX_ONLY_ACTIVE_SPELL ))
active = true ;
2008-11-26 15:14:03 -06:00
}
}
}
2009-10-17 15:51:44 -07:00
2009-07-18 22:18:47 +02:00
if ( procExtra & ( PROC_EX_INTERNAL_REQ_FAMILY ))
2009-05-17 18:00:33 +02:00
{
if ( ! hasFamilyMask )
return false ;
}
2009-10-17 15:51:44 -07:00
2008-11-26 15:14:03 -06:00
// Check for extra req (if none) and hit/crit
if ( procEvent_procEx == PROC_EX_NONE )
{
2009-07-02 21:32:19 +02:00
// No extra req, so can trigger only for hit/crit - spell has to be active
2010-04-07 19:14:10 +02:00
if (( procExtra & ( PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT )) && active )
2008-11-26 15:14:03 -06:00
return true ;
}
else // Passive spells hits here only if resist/reflect/immune/evade
{
2009-07-02 21:32:19 +02:00
if ( procExtra & AURA_SPELL_PROC_EX_MASK )
{
2009-07-09 23:49:46 +02:00
// if spell marked as procing only from not active spells
if ( active && procEvent_procEx & PROC_EX_NOT_ACTIVE_SPELL )
return false ;
// if spell marked as procing only from active spells
if ( ! active && procEvent_procEx & PROC_EX_ONLY_ACTIVE_SPELL )
return false ;
2009-07-02 21:32:19 +02:00
// Exist req for PROC_EX_EX_TRIGGER_ALWAYS
if ( procEvent_procEx & PROC_EX_EX_TRIGGER_ALWAYS )
return true ;
2009-07-09 23:49:46 +02:00
// PROC_EX_NOT_ACTIVE_SPELL and PROC_EX_ONLY_ACTIVE_SPELL flags handle: if passed checks before
2010-01-10 01:23:15 +01:00
if (( procExtra & ( PROC_EX_NORMAL_HIT | PROC_EX_CRITICAL_HIT )) && (( procEvent_procEx & ( AURA_SPELL_PROC_EX_MASK )) == 0 ))
2009-07-09 23:49:46 +02:00
return true ;
2009-07-02 21:32:19 +02:00
}
2009-07-13 18:05:53 +02:00
// Check Extra Requirement like (hit/crit/miss/resist/parry/dodge/block/immune/reflect/absorb and other)
if ( procEvent_procEx & procExtra )
return true ;
2008-11-26 15:14:03 -06:00
}
return false ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellProcEntry const * SpellMgr :: GetSpellProcEntry ( uint32 spellId ) const
2011-06-26 13:54:44 +02:00
{
2011-07-26 23:09:28 +02:00
SpellProcMap :: const_iterator itr = mSpellProcMap . find ( spellId );
if ( itr != mSpellProcMap . end ())
return & itr -> second ;
return NULL ;
}
2011-06-26 13:54:44 +02:00
2011-07-26 23:09:28 +02:00
bool SpellMgr :: CanSpellTriggerProcOnEvent ( SpellProcEntry const & procEntry , ProcEventInfo & eventInfo )
{
// proc type doesn't match
if ( ! ( eventInfo . GetTypeMask () & procEntry . typeMask ))
return false ;
2011-06-26 13:54:44 +02:00
2011-07-26 23:09:28 +02:00
// check XP or honor target requirement
if ( procEntry . attributesMask & PROC_ATTR_REQ_EXP_OR_HONOR )
if ( Player * actor = eventInfo . GetActor () -> ToPlayer ())
if ( eventInfo . GetActionTarget () && ! actor -> isHonorOrXPTarget ( eventInfo . GetActionTarget ()))
return false ;
2011-06-26 13:54:44 +02:00
2011-07-26 23:09:28 +02:00
// always trigger for these types
if ( eventInfo . GetTypeMask () & ( PROC_FLAG_KILLED | PROC_FLAG_KILL | PROC_FLAG_DEATH ))
return true ;
2011-07-10 13:13:02 +02:00
// check school mask (if set) for other trigger types
if ( procEntry . schoolMask && ! ( eventInfo . GetSchoolMask () & procEntry . schoolMask ))
return false ;
// check spell family name/flags (if set) for spells
if ( eventInfo . GetTypeMask () & ( PERIODIC_PROC_FLAG_MASK | SPELL_PROC_FLAG_MASK | PROC_FLAG_DONE_TRAP_ACTIVATION ))
{
if ( procEntry . spellFamilyName && ( procEntry . spellFamilyName != eventInfo . GetSpellInfo () -> SpellFamilyName ))
return false ;
if ( procEntry . spellFamilyMask && ! ( procEntry . spellFamilyMask & eventInfo . GetSpellInfo () -> SpellFamilyFlags ))
return false ;
}
// check spell type mask (if set)
if ( eventInfo . GetTypeMask () & ( SPELL_PROC_FLAG_MASK | PERIODIC_PROC_FLAG_MASK ))
{
if ( procEntry . spellTypeMask && ! ( eventInfo . GetSpellTypeMask () & procEntry . spellTypeMask ))
return false ;
}
// check spell phase mask
if ( eventInfo . GetTypeMask () & REQ_SPELL_PHASE_PROC_FLAG_MASK )
{
if ( ! ( eventInfo . GetSpellPhaseMask () & procEntry . spellPhaseMask ))
return false ;
}
// check hit mask (on taken hit or on done hit, but not on spell cast phase)
if (( eventInfo . GetTypeMask () & TAKEN_HIT_PROC_FLAG_MASK ) || (( eventInfo . GetTypeMask () & DONE_HIT_PROC_FLAG_MASK ) && ! ( eventInfo . GetSpellPhaseMask () & PROC_SPELL_PHASE_CAST )))
{
uint32 hitMask = procEntry . hitMask ;
// get default values if hit mask not set
if ( ! hitMask )
{
// for taken procs allow normal + critical hits by default
if ( eventInfo . GetTypeMask () & TAKEN_HIT_PROC_FLAG_MASK )
hitMask |= PROC_HIT_NORMAL | PROC_HIT_CRITICAL ;
// for done procs allow normal + critical + absorbs by default
else
hitMask |= PROC_HIT_NORMAL | PROC_HIT_CRITICAL | PROC_HIT_ABSORB ;
}
if ( ! ( eventInfo . GetHitMask () & hitMask ))
return false ;
}
return true ;
}
2011-07-26 23:09:28 +02:00
SpellBonusEntry const * SpellMgr :: GetSpellBonusData ( uint32 spellId ) const
2011-06-26 13:54:44 +02:00
{
2011-07-26 23:09:28 +02:00
// Lookup data
SpellBonusMap :: const_iterator itr = mSpellBonusMap . find ( spellId );
if ( itr != mSpellBonusMap . end ())
return & itr -> second ;
// Not found, try lookup for 1 spell rank if exist
if ( uint32 rank_1 = GetFirstSpellInChain ( spellId ))
2011-06-26 13:54:44 +02:00
{
2011-07-26 23:09:28 +02:00
SpellBonusMap :: const_iterator itr2 = mSpellBonusMap . find ( rank_1 );
if ( itr2 != mSpellBonusMap . end ())
return & itr2 -> second ;
2011-06-26 13:54:44 +02:00
}
2011-07-26 23:09:28 +02:00
return NULL ;
}
2011-06-26 13:54:44 +02:00
2011-08-21 12:00:36 +02:00
SpellThreatEntry const * SpellMgr :: GetSpellThreatEntry ( uint32 spellID ) const
2011-07-26 23:09:28 +02:00
{
2011-08-21 12:00:36 +02:00
SpellThreatMap :: const_iterator itr = mSpellThreatMap . find ( spellID );
if ( itr != mSpellThreatMap . end ())
return & itr -> second ;
else
{
uint32 firstSpell = GetFirstSpellInChain ( spellID );
2011-11-23 19:17:33 +01:00
itr = mSpellThreatMap . find ( firstSpell );
2011-08-21 12:00:36 +02:00
if ( itr != mSpellThreatMap . end ())
return & itr -> second ;
}
return NULL ;
2011-07-26 23:09:28 +02:00
}
2011-06-26 13:54:44 +02:00
2011-07-26 23:09:28 +02:00
SkillLineAbilityMapBounds SpellMgr :: GetSkillLineAbilityMapBounds ( uint32 spell_id ) const
{
2013-01-02 09:53:43 +01:00
return mSkillLineAbilityMap . equal_range ( spell_id );
2011-07-26 23:09:28 +02:00
}
2011-06-26 13:54:44 +02:00
2011-07-26 23:09:28 +02:00
PetAura const * SpellMgr :: GetPetAura ( uint32 spell_id , uint8 eff )
{
SpellPetAuraMap :: const_iterator itr = mSpellPetAuraMap . find (( spell_id << 8 ) + eff );
if ( itr != mSpellPetAuraMap . end ())
return & itr -> second ;
else
return NULL ;
}
2011-06-26 13:54:44 +02:00
2011-07-26 23:09:28 +02:00
SpellEnchantProcEntry const * SpellMgr :: GetSpellEnchantProcEvent ( uint32 enchId ) const
{
SpellEnchantProcEventMap :: const_iterator itr = mSpellEnchantProcEventMap . find ( enchId );
if ( itr != mSpellEnchantProcEventMap . end ())
return & itr -> second ;
return NULL ;
2011-06-26 13:54:44 +02:00
}
2011-07-26 23:09:28 +02:00
bool SpellMgr :: IsArenaAllowedEnchancment ( uint32 ench_id ) const
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
return mEnchantCustomAttr [ ench_id ];
}
2010-12-19 17:06:33 +01:00
2011-07-26 23:09:28 +02:00
const std :: vector < int32 >* SpellMgr :: GetSpellLinked ( int32 spell_id ) const
{
SpellLinkedMap :: const_iterator itr = mSpellLinkedMap . find ( spell_id );
return itr != mSpellLinkedMap . end () ? & ( itr -> second ) : NULL ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
PetLevelupSpellSet const * SpellMgr :: GetPetLevelupSpellList ( uint32 petFamily ) const
{
PetLevelupSpellMap :: const_iterator itr = mPetLevelupSpellMap . find ( petFamily );
if ( itr != mPetLevelupSpellMap . end ())
return & itr -> second ;
else
return NULL ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
PetDefaultSpellsEntry const * SpellMgr :: GetPetDefaultSpellsEntry ( int32 id ) const
{
PetDefaultSpellsMap :: const_iterator itr = mPetDefaultSpellsMap . find ( id );
if ( itr != mPetDefaultSpellsMap . end ())
return & itr -> second ;
return NULL ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellAreaMapBounds SpellMgr :: GetSpellAreaMapBounds ( uint32 spell_id ) const
{
2013-01-02 09:53:43 +01:00
return mSpellAreaMap . equal_range ( spell_id );
2011-07-26 23:09:28 +02:00
}
2010-02-02 22:35:01 +01:00
2012-10-16 21:43:23 -05:00
SpellAreaForQuestMapBounds SpellMgr :: GetSpellAreaForQuestMapBounds ( uint32 quest_id ) const
2011-07-26 23:09:28 +02:00
{
2013-01-02 09:53:43 +01:00
return mSpellAreaForQuestMap . equal_range ( quest_id );
2011-07-26 23:09:28 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellAreaForQuestMapBounds SpellMgr :: GetSpellAreaForQuestEndMapBounds ( uint32 quest_id ) const
{
2013-01-02 09:53:43 +01:00
return mSpellAreaForQuestEndMap . equal_range ( quest_id );
2011-07-26 23:09:28 +02:00
}
2010-02-02 22:35:01 +01:00
2011-07-26 23:09:28 +02:00
SpellAreaForAuraMapBounds SpellMgr :: GetSpellAreaForAuraMapBounds ( uint32 spell_id ) const
{
2013-01-02 09:53:43 +01:00
return mSpellAreaForAuraMap . equal_range ( spell_id );
2011-07-26 23:09:28 +02:00
}
2010-02-01 19:22:32 +01:00
2011-07-26 23:09:28 +02:00
SpellAreaForAreaMapBounds SpellMgr :: GetSpellAreaForAreaMapBounds ( uint32 area_id ) const
{
2013-01-02 09:53:43 +01:00
return mSpellAreaForAreaMap . equal_range ( area_id );
2011-07-26 23:09:28 +02:00
}
2010-02-02 22:35:01 +01:00
2011-07-26 23:09:28 +02:00
bool SpellArea :: IsFitToRequirements ( Player const * player , uint32 newZone , uint32 newArea ) const
{
if ( gender != GENDER_NONE ) // not in expected gender
if ( ! player || gender != player -> getGender ())
return false ;
if ( raceMask ) // not in expected race
if ( ! player || ! ( raceMask & player -> getRaceMask ()))
return false ;
if ( areaId ) // not in expected zone
if ( newZone != areaId && newArea != areaId )
return false ;
if ( questStart ) // not in expected required quest state
2012-10-16 21:43:23 -05:00
if ( ! player || ((( 1 << player -> GetQuestStatus ( questStart )) & questStartStatus ) == 0 ))
2011-07-26 23:09:28 +02:00
return false ;
if ( questEnd ) // not in expected forbidden quest state
2012-10-16 21:43:23 -05:00
if ( ! player || ((( 1 << player -> GetQuestStatus ( questEnd )) & questEndStatus ) == 0 ))
2011-07-26 23:09:28 +02:00
return false ;
if ( auraSpell ) // not have expected aura
if ( ! player || ( auraSpell > 0 && ! player -> HasAura ( auraSpell )) || ( auraSpell < 0 && player -> HasAura ( - auraSpell )))
return false ;
// Extra conditions -- leaving the possibility add extra conditions...
switch ( spellId )
2010-02-02 22:35:01 +01:00
{
2013-01-03 17:37:39 +01:00
case 91604 : // No fly Zone - Wintergrasp
2012-02-21 11:33:49 -05:00
{
if ( ! player )
return false ;
2012-03-02 22:00:26 -03:00
Battlefield * Bf = sBattlefieldMgr -> GetBattlefieldToZoneId ( player -> GetZoneId ());
2012-02-21 11:33:49 -05:00
if ( ! Bf || Bf -> CanFlyIn () || ( ! player -> HasAuraType ( SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED ) && ! player -> HasAuraType ( SPELL_AURA_FLY )))
return false ;
break ;
}
2011-07-26 23:09:28 +02:00
case 68719 : // Oil Refinery - Isle of Conquest.
case 68720 : // Quarry - Isle of Conquest.
2010-02-01 19:22:32 +01:00
{
2012-09-05 17:17:45 +02:00
if ( ! player || player -> GetBattlegroundTypeId () != BATTLEGROUND_IC || ! player -> GetBattleground ())
2011-07-26 23:09:28 +02:00
return false ;
2010-02-02 22:35:01 +01:00
2011-07-26 23:09:28 +02:00
uint8 nodeType = spellId == 68719 ? NODE_TYPE_REFINERY : NODE_TYPE_QUARRY ;
uint8 nodeState = player -> GetTeamId () == TEAM_ALLIANCE ? NODE_STATE_CONTROLLED_A : NODE_STATE_CONTROLLED_H ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
BattlegroundIC * pIC = static_cast < BattlegroundIC *> ( player -> GetBattleground ());
if ( pIC -> GetNodeState ( nodeType ) == nodeState )
return true ;
2010-02-02 22:35:01 +01:00
2011-07-26 23:09:28 +02:00
return false ;
2010-02-02 22:35:01 +01:00
}
2012-03-02 15:23:07 -03:00
case 56618 : // Horde Controls Factory Phase Shift
case 56617 : // Alliance Controls Factory Phase Shift
2013-01-03 16:58:38 +01:00
{
if ( ! player )
return false ;
2012-03-02 15:23:07 -03:00
2013-01-03 16:58:38 +01:00
Battlefield * bf = sBattlefieldMgr -> GetBattlefieldToZoneId ( player -> GetZoneId ());
2012-03-02 15:23:07 -03:00
2013-01-03 16:58:38 +01:00
if ( ! bf || bf -> GetTypeId () != BATTLEFIELD_WG )
return false ;
2012-03-02 15:23:07 -03:00
2013-01-03 16:58:38 +01:00
// team that controls the workshop in the specified area
uint32 team = bf -> GetData ( newArea );
2012-08-22 22:56:31 +01:00
2013-01-03 16:58:38 +01:00
if ( team == TEAM_HORDE )
return spellId == 56618 ;
else if ( team == TEAM_ALLIANCE )
return spellId == 56617 ;
2012-03-02 15:23:07 -03:00
break ;
2013-01-03 16:58:38 +01:00
}
2012-08-26 16:46:25 +02:00
case 57940 : // Essence of Wintergrasp - Northrend
case 58045 : // Essence of Wintergrasp - Wintergrasp
{
if ( ! player )
return false ;
2012-08-27 00:26:02 +01:00
2012-08-26 16:46:25 +02:00
if ( Battlefield * battlefieldWG = sBattlefieldMgr -> GetBattlefieldByBattleId ( BATTLEFIELD_BATTLEID_WG ))
return battlefieldWG -> IsEnabled () && ( player -> GetTeamId () == battlefieldWG -> GetDefenderTeam ()) && ! battlefieldWG -> IsWarTime ();
break ;
}
2012-08-26 19:38:05 +02:00
case 74411 : // Battleground - Dampening
{
if ( ! player )
return false ;
if ( Battlefield * bf = sBattlefieldMgr -> GetBattlefieldToZoneId ( player -> GetZoneId ()))
return bf -> IsWarTime ();
break ;
}
2010-02-02 22:35:01 +01:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
return true ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellRanks ()
2010-01-23 17:05:20 +01:00
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2011-07-26 23:09:28 +02:00
// cleanup core data before reload - remove reference to ChainNode from SpellInfo
for ( SpellChainMap :: iterator itr = mSpellChains . begin (); itr != mSpellChains . end (); ++ itr )
{
mSpellInfoMap [ itr -> first ] -> ChainEntry = NULL ;
}
mSpellChains . clear ();
2012-05-30 08:01:02 +02:00
// 0 1 2
2011-09-29 12:43:05 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT first_spell_id, spell_id, rank from spell_ranks ORDER BY first_spell_id, rank" );
2010-01-23 17:05:20 +01:00
2010-04-07 22:59:46 +02:00
if ( ! result )
2010-01-23 17:05:20 +01:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell rank records. DB table `spell_ranks` is empty." );
2012-08-03 15:54:54 +02:00
2010-01-23 17:05:20 +01:00
return ;
}
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2011-07-26 23:09:28 +02:00
bool finished = false ;
2010-01-23 17:05:20 +01:00
do
{
2011-07-26 23:09:28 +02:00
// spellid, rank
std :: list < std :: pair < int32 , int32 > > rankChain ;
int32 currentSpell = - 1 ;
int32 lastSpell = - 1 ;
2010-01-23 17:05:20 +01:00
2011-07-26 23:09:28 +02:00
// fill one chain
while ( currentSpell == lastSpell && ! finished )
2010-02-02 22:35:01 +01:00
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2010-01-23 17:05:20 +01:00
2011-07-26 23:09:28 +02:00
currentSpell = fields [ 0 ]. GetUInt32 ();
if ( lastSpell == - 1 )
lastSpell = currentSpell ;
uint32 spell_id = fields [ 1 ]. GetUInt32 ();
2012-05-30 08:01:02 +02:00
uint32 rank = fields [ 2 ]. GetUInt8 ();
2010-01-23 17:05:20 +01:00
2011-07-26 23:09:28 +02:00
// don't drop the row if we're moving to the next rank
if ( currentSpell == lastSpell )
{
rankChain . push_back ( std :: make_pair ( spell_id , rank ));
if ( ! result -> NextRow ())
finished = true ;
}
else
break ;
}
// check if chain is made with valid first spell
2011-08-04 13:16:09 +02:00
SpellInfo const * first = GetSpellInfo ( lastSpell );
2011-07-26 23:09:28 +02:00
if ( ! first )
2010-01-23 17:05:20 +01:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell rank identifier(first_spell_id) %u listed in `spell_ranks` does not exist!" , lastSpell );
2010-01-23 17:05:20 +01:00
continue ;
}
2011-07-26 23:09:28 +02:00
// check if chain is long enough
if ( rankChain . size () < 2 )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "There is only 1 spell rank for identifier(first_spell_id) %u in `spell_ranks`, entry is not needed!" , lastSpell );
2011-07-26 23:09:28 +02:00
continue ;
}
int32 curRank = 0 ;
bool valid = true ;
// check spells in chain
2012-05-30 08:01:02 +02:00
for ( std :: list < std :: pair < int32 , int32 > >:: iterator itr = rankChain . begin (); itr != rankChain . end (); ++ itr )
2011-07-26 23:09:28 +02:00
{
2011-08-04 13:16:09 +02:00
SpellInfo const * spell = GetSpellInfo ( itr -> first );
2011-07-26 23:09:28 +02:00
if ( ! spell )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u (rank %u) listed in `spell_ranks` for chain %u does not exist!" , itr -> first , itr -> second , lastSpell );
2011-07-26 23:09:28 +02:00
valid = false ;
break ;
}
++ curRank ;
if ( itr -> second != curRank )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u (rank %u) listed in `spell_ranks` for chain %u does not have proper rank value(should be %u)!" , itr -> first , itr -> second , lastSpell , curRank );
2011-07-26 23:09:28 +02:00
valid = false ;
break ;
}
}
if ( ! valid )
continue ;
int32 prevRank = 0 ;
// insert the chain
std :: list < std :: pair < int32 , int32 > >:: iterator itr = rankChain . begin ();
do
{
2012-05-30 08:01:02 +02:00
++ count ;
2011-07-26 23:09:28 +02:00
int32 addedSpell = itr -> first ;
mSpellChains [ addedSpell ]. first = GetSpellInfo ( lastSpell );
mSpellChains [ addedSpell ]. last = GetSpellInfo ( rankChain . back (). first );
mSpellChains [ addedSpell ]. rank = itr -> second ;
mSpellChains [ addedSpell ]. prev = GetSpellInfo ( prevRank );
mSpellInfoMap [ addedSpell ] -> ChainEntry = & mSpellChains [ addedSpell ];
prevRank = addedSpell ;
++ itr ;
2012-11-16 09:51:44 +01:00
2011-07-26 23:09:28 +02:00
if ( itr == rankChain . end ())
{
mSpellChains [ addedSpell ]. next = NULL ;
break ;
}
else
mSpellChains [ addedSpell ]. next = GetSpellInfo ( itr -> first );
}
while ( true );
} while ( ! finished );
2010-01-23 17:05:20 +01:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u spell rank records in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2012-08-03 15:54:54 +02:00
2010-01-23 17:05:20 +01:00
}
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellRequired ()
2008-11-17 22:07:21 -06:00
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2011-07-26 23:09:28 +02:00
mSpellsReqSpell . clear (); // need for reload case
mSpellReq . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
// 0 1
2011-07-26 23:09:28 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT spell_id, req_spell from spell_required" );
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
if ( ! result )
2009-07-30 11:37:08 +08:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell required records. DB table `spell_required` is empty." );
2012-08-03 15:54:54 +02:00
2009-07-30 11:37:08 +08:00
return ;
}
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2009-07-30 11:37:08 +08:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
uint32 spell_id = fields [ 0 ]. GetUInt32 ();
2011-07-26 23:09:28 +02:00
uint32 spell_req = fields [ 1 ]. GetUInt32 ();
2012-05-30 08:01:02 +02:00
2011-07-26 23:09:28 +02:00
// check if chain is made with valid first spell
2011-08-04 13:16:09 +02:00
SpellInfo const * spell = GetSpellInfo ( spell_id );
2011-07-26 23:09:28 +02:00
if ( ! spell )
2009-07-30 11:37:08 +08:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "spell_id %u in `spell_required` table is not found in dbcs, skipped" , spell_id );
2011-07-26 23:09:28 +02:00
continue ;
}
2012-05-30 08:01:02 +02:00
2011-08-04 13:16:09 +02:00
SpellInfo const * req_spell = GetSpellInfo ( spell_req );
2011-07-26 23:09:28 +02:00
if ( ! req_spell )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "req_spell %u in `spell_required` table is not found in dbcs, skipped" , spell_req );
2011-07-26 23:09:28 +02:00
continue ;
}
2012-05-30 08:01:02 +02:00
2011-07-26 23:09:28 +02:00
if ( GetFirstSpellInChain ( spell_id ) == GetFirstSpellInChain ( spell_req ))
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "req_spell %u and spell_id %u in `spell_required` table are ranks of the same spell, entry not needed, skipped" , spell_req , spell_id );
2011-07-26 23:09:28 +02:00
continue ;
}
2012-05-30 08:01:02 +02:00
2011-07-26 23:09:28 +02:00
if ( IsSpellRequiringSpell ( spell_id , spell_req ))
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "duplicated entry of req_spell %u and spell_id %u in `spell_required`, skipped" , spell_req , spell_id );
2009-07-30 11:37:08 +08:00
continue ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellReq . insert ( std :: pair < uint32 , uint32 > ( spell_id , spell_req ));
mSpellsReqSpell . insert ( std :: pair < uint32 , uint32 > ( spell_req , spell_id ));
2012-05-30 08:01:02 +02:00
++ count ;
2010-01-01 14:19:29 -06:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u spell required records in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2012-08-03 15:54:54 +02:00
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellLearnSkills ()
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
uint32 oldMSTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellLearnSkills . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// search auto-learned skills and add its to map also for use in unlearn spells/talents
uint32 dbc_count = 0 ;
2011-08-26 09:41:33 +02:00
for ( uint32 spell = 0 ; spell < GetSpellInfoStoreSize (); ++ spell )
2011-07-26 23:09:28 +02:00
{
2011-08-04 13:16:09 +02:00
SpellInfo const * entry = GetSpellInfo ( spell );
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( ! entry )
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
for ( uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
2009-01-25 16:35:14 -06:00
{
2011-07-26 23:09:28 +02:00
if ( entry -> Effects [ i ]. Effect == SPELL_EFFECT_SKILL )
{
SpellLearnSkillNode dbc_node ;
dbc_node . skill = entry -> Effects [ i ]. MiscValue ;
dbc_node . step = entry -> Effects [ i ]. CalcValue ();
if ( dbc_node . skill != SKILL_RIDING )
dbc_node . value = 1 ;
else
dbc_node . value = dbc_node . step * 75 ;
dbc_node . maxvalue = dbc_node . step * 75 ;
mSpellLearnSkills [ spell ] = dbc_node ;
++ dbc_count ;
2009-01-25 16:35:14 -06:00
break ;
2011-07-26 23:09:28 +02:00
}
2009-01-25 16:35:14 -06:00
}
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u Spell Learn Skills from DBC in %u ms" , dbc_count , GetMSTimeDiffToNow ( oldMSTime ));
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellLearnSpells ()
2009-01-16 15:53:34 -06:00
{
2011-07-26 23:09:28 +02:00
uint32 oldMSTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellLearnSpells . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
// 0 1 2
2010-09-11 21:10:54 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT entry, SpellID, Active FROM spell_learn_spell" );
2010-01-01 14:19:29 -06:00
if ( ! result )
2008-11-17 22:07:21 -06:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell learn spells. DB table `spell_learn_spell` is empty." );
2008-11-17 22:07:21 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-05-15 16:26:00 -05:00
uint32 count = 0 ;
2008-11-17 22:07:21 -06:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2012-11-12 10:29:52 +01:00
uint32 spell_id = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2009-05-15 16:26:00 -05:00
SpellLearnSpellNode node ;
2012-11-12 10:29:52 +01:00
node . spell = fields [ 1 ]. GetUInt32 ();
2012-05-30 08:01:02 +02:00
node . active = fields [ 2 ]. GetBool ();
node . autoLearned = false ;
2009-10-17 15:51:44 -07:00
2011-08-04 13:16:09 +02:00
if ( ! GetSpellInfo ( spell_id ))
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_learn_spell` does not exist" , spell_id );
2009-05-15 16:26:00 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2011-08-04 13:16:09 +02:00
if ( ! GetSpellInfo ( node . spell ))
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_learn_spell` learning not existed spell %u" , spell_id , node . spell );
2009-07-01 18:07:57 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
if ( GetTalentSpellCost ( node . spell ))
2009-07-01 18:07:57 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_learn_spell` attempt learning talent spell %u, skipped" , spell_id , node . spell );
2009-05-15 16:26:00 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
mSpellLearnSpells . insert ( SpellLearnSpellMap :: value_type ( spell_id , node ));
2009-10-17 15:51:44 -07:00
2009-05-15 16:26:00 -05:00
++ count ;
2010-01-01 14:19:29 -06:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2009-05-15 16:26:00 -05:00
// search auto-learned spells and add its to map also for use in unlearn spells/talents
uint32 dbc_count = 0 ;
2011-08-04 13:16:09 +02:00
for ( uint32 spell = 0 ; spell < GetSpellInfoStoreSize (); ++ spell )
2009-05-15 16:26:00 -05:00
{
2011-08-04 13:16:09 +02:00
SpellInfo const * entry = GetSpellInfo ( spell );
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
if ( ! entry )
2009-05-15 16:26:00 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
for ( uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
2009-05-15 16:26:00 -05:00
{
2011-07-26 23:09:28 +02:00
if ( entry -> Effects [ i ]. Effect == SPELL_EFFECT_LEARN_SPELL )
2009-05-15 16:26:00 -05:00
{
SpellLearnSpellNode dbc_node ;
2011-07-26 23:09:28 +02:00
dbc_node . spell = entry -> Effects [ i ]. TriggerSpell ;
2010-01-01 14:19:29 -06:00
dbc_node . active = true ; // all dbc based learned spells is active (show in spell book or hide by client itself)
2009-10-17 15:51:44 -07:00
2009-05-15 16:26:00 -05:00
// ignore learning not existed spells (broken/outdated/or generic learnig spell 483
2011-08-04 13:16:09 +02:00
if ( ! GetSpellInfo ( dbc_node . spell ))
2009-05-15 16:26:00 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-05-15 16:26:00 -05:00
// talent or passive spells or skill-step spells auto-casted and not need dependent learning,
2011-06-28 13:53:48 +02:00
// pet teaching spells must not be dependent learning (casted)
2009-05-15 16:26:00 -05:00
// other required explicit dependent learning
2011-07-27 12:35:59 +02:00
dbc_node . autoLearned = entry -> Effects [ i ]. TargetA . GetTarget () == TARGET_UNIT_PET || GetTalentSpellCost ( spell ) > 0 || entry -> IsPassive () || entry -> HasEffect ( SPELL_EFFECT_SKILL_STEP );
2009-10-17 15:51:44 -07:00
2009-08-27 20:27:55 -05:00
SpellLearnSpellMapBounds db_node_bounds = GetSpellLearnSpellMapBounds ( spell );
2009-10-17 15:51:44 -07:00
2009-05-15 16:26:00 -05:00
bool found = false ;
2009-10-17 16:20:24 -07:00
for ( SpellLearnSpellMap :: const_iterator itr = db_node_bounds . first ; itr != db_node_bounds . second ; ++ itr )
2009-05-15 16:26:00 -05:00
{
2010-01-01 14:19:29 -06:00
if ( itr -> second . spell == dbc_node . spell )
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u auto-learn spell %u in spell.dbc then the record in `spell_learn_spell` is redundant, please fix DB." ,
2011-04-29 20:47:02 +02:00
spell , dbc_node . spell );
2009-05-15 16:26:00 -05:00
found = true ;
break ;
}
}
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
if ( ! found ) // add new spell-spell pair if not found
2009-05-15 16:26:00 -05:00
{
2011-04-29 20:47:02 +02:00
mSpellLearnSpells . insert ( SpellLearnSpellMap :: value_type ( spell , dbc_node ));
2009-05-15 16:26:00 -05:00
++ dbc_count ;
}
}
}
2008-12-22 02:11:11 +01:00
}
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u spell learn spells + %u found in DBC in %u ms" , count , dbc_count , GetMSTimeDiffToNow ( oldMSTime ));
2009-05-15 16:26:00 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellTargetPositions ()
2009-05-15 16:26:00 -05:00
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellTargetPositions . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
// 0 1 2 3 4 5
2011-07-26 23:09:28 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT id, target_map, target_position_x, target_position_y, target_position_z, target_orientation FROM spell_target_position" );
2009-11-19 03:53:49 -08:00
if ( ! result )
2009-05-15 16:26:00 -05:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell target coordinates. DB table `spell_target_position` is empty." );
2009-05-15 16:26:00 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-12-19 17:06:33 +01:00
uint32 count = 0 ;
2009-05-15 16:26:00 -05:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 Spell_ID = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellTargetPosition st ;
2012-05-30 08:01:02 +02:00
st . target_mapId = fields [ 1 ]. GetUInt16 ();
2011-07-26 23:09:28 +02:00
st . target_X = fields [ 2 ]. GetFloat ();
st . target_Y = fields [ 3 ]. GetFloat ();
st . target_Z = fields [ 4 ]. GetFloat ();
st . target_Orientation = fields [ 5 ]. GetFloat ();
MapEntry const * mapEntry = sMapStore . LookupEntry ( st . target_mapId );
if ( ! mapEntry )
2008-12-22 02:11:11 +01:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell (ID:%u) target map (ID: %u) does not exist in `Map.dbc`." , Spell_ID , st . target_mapId );
2011-07-26 23:09:28 +02:00
continue ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( st . target_X == 0 && st . target_Y == 0 && st . target_Z == 0 )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell (ID:%u) target coordinates not provided." , Spell_ID );
2011-07-26 23:09:28 +02:00
continue ;
}
2011-08-04 13:16:09 +02:00
SpellInfo const * spellInfo = GetSpellInfo ( Spell_ID );
2011-07-26 23:09:28 +02:00
if ( ! spellInfo )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell (ID:%u) listed in `spell_target_position` does not exist." , Spell_ID );
2011-07-26 23:09:28 +02:00
continue ;
}
bool found = false ;
for ( uint8 i = 0 ; i < MAX_SPELL_EFFECTS ; ++ i )
{
2011-08-16 19:44:18 +02:00
if ( spellInfo -> Effects [ i ]. TargetA . GetTarget () == TARGET_DEST_DB || spellInfo -> Effects [ i ]. TargetB . GetTarget () == TARGET_DEST_DB )
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
// additional requirements
if ( spellInfo -> Effects [ i ]. Effect == SPELL_EFFECT_BIND && spellInfo -> Effects [ i ]. MiscValue )
{
uint32 area_id = sMapMgr -> GetAreaId ( st . target_mapId , st . target_X , st . target_Y , st . target_Z );
if ( area_id != uint32 ( spellInfo -> Effects [ i ]. MiscValue ))
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell (Id: %u) listed in `spell_target_position` expected point to zone %u bit point to zone %u." , Spell_ID , spellInfo -> Effects [ i ]. MiscValue , area_id );
2011-07-26 23:09:28 +02:00
break ;
}
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
found = true ;
break ;
}
}
if ( ! found )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell (Id: %u) listed in `spell_target_position` does not have target TARGET_DEST_DB (17)." , Spell_ID );
2011-07-26 23:09:28 +02:00
continue ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellTargetPositions [ Spell_ID ] = st ;
2009-05-15 16:26:00 -05:00
++ count ;
2011-07-26 23:09:28 +02:00
2009-11-19 03:53:49 -08:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
/*
// Check all spells
for (uint32 i = 1; i < GetSpellInfoStoreSize; ++i)
{
SpellInfo const* spellInfo = GetSpellInfo(i);
if (!spellInfo)
continue;
bool found = false;
for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
{
switch (spellInfo->Effects[j].TargetA)
{
2011-08-16 19:44:18 +02:00
case TARGET_DEST_DB:
2011-07-26 23:09:28 +02:00
found = true;
break;
}
if (found)
break;
switch (spellInfo->Effects[j].TargetB)
{
2011-08-16 19:44:18 +02:00
case TARGET_DEST_DB:
2011-07-26 23:09:28 +02:00
found = true;
break;
}
if (found)
break;
}
if (found)
{
if (!sSpellMgr->GetSpellTargetPosition(i))
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell (ID: %u) does not have record in `spell_target_position`", i);
}
}*/
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u spell teleport coordinates in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellGroups ()
2008-11-17 22:07:21 -06:00
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2011-07-26 23:09:28 +02:00
mSpellSpellGroup . clear (); // need for reload case
mSpellGroupSpell . clear ();
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
// 0 1
2011-07-26 23:09:28 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT id, spell_id FROM spell_group" );
if ( ! result )
2008-11-17 22:07:21 -06:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell group definitions. DB table `spell_group` is empty." );
2011-07-26 23:09:28 +02:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
std :: set < uint32 > groups ;
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2011-07-26 23:09:28 +02:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 group_id = fields [ 0 ]. GetUInt32 ();
if ( group_id <= SPELL_GROUP_DB_RANGE_MIN && group_id >= SPELL_GROUP_CORE_RANGE_MAX )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "SpellGroup id %u listed in `spell_group` is in core range, but is not defined in core!" , group_id );
2011-07-26 23:09:28 +02:00
continue ;
2008-11-17 22:07:21 -06:00
}
2011-07-26 23:09:28 +02:00
int32 spell_id = fields [ 1 ]. GetInt32 ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
groups . insert ( std :: set < uint32 >:: value_type ( group_id ));
mSpellGroupSpell . insert ( SpellGroupSpellMap :: value_type (( SpellGroup ) group_id , spell_id ));
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
} while ( result -> NextRow ());
2012-05-30 08:01:02 +02:00
for ( SpellGroupSpellMap :: iterator itr = mSpellGroupSpell . begin (); itr != mSpellGroupSpell . end ();)
2009-05-24 12:16:12 -05:00
{
2011-07-26 23:09:28 +02:00
if ( itr -> second < 0 )
2009-05-24 12:16:12 -05:00
{
2011-07-26 23:09:28 +02:00
if ( groups . find ( abs ( itr -> second )) == groups . end ())
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "SpellGroup id %u listed in `spell_group` does not exist" , abs ( itr -> second ));
2011-07-26 23:09:28 +02:00
mSpellGroupSpell . erase ( itr ++ );
}
else
++ itr ;
2009-05-24 12:16:12 -05:00
}
2011-07-26 23:09:28 +02:00
else
2009-05-24 12:16:12 -05:00
{
2011-08-04 13:16:09 +02:00
SpellInfo const * spellInfo = GetSpellInfo ( itr -> second );
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( ! spellInfo )
2009-05-24 12:16:12 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_group` does not exist" , itr -> second );
2011-07-26 23:09:28 +02:00
mSpellGroupSpell . erase ( itr ++ );
2009-05-24 12:16:12 -05:00
}
2011-07-26 23:09:28 +02:00
else if ( spellInfo -> GetRank () > 1 )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_group` is not first rank of spell" , itr -> second );
2011-07-26 23:09:28 +02:00
mSpellGroupSpell . erase ( itr ++ );
}
else
++ itr ;
2009-05-24 12:16:12 -05:00
}
}
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
for ( std :: set < uint32 >:: iterator groupItr = groups . begin (); groupItr != groups . end (); ++ groupItr )
2009-05-24 12:16:12 -05:00
{
2011-07-26 23:09:28 +02:00
std :: set < uint32 > spells ;
GetSetOfSpellsInSpellGroup ( SpellGroup ( * groupItr ), spells );
2012-05-30 08:01:02 +02:00
for ( std :: set < uint32 >:: iterator spellItr = spells . begin (); spellItr != spells . end (); ++ spellItr )
2009-05-24 12:16:12 -05:00
{
2011-07-26 23:09:28 +02:00
++ count ;
mSpellSpellGroup . insert ( SpellSpellGroupMap :: value_type ( * spellItr , SpellGroup ( * groupItr )));
2009-05-24 12:16:12 -05:00
}
}
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u spell group definitions in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2009-05-24 12:16:12 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellGroupStackRules ()
2009-05-24 12:16:12 -05:00
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2011-07-26 23:09:28 +02:00
mSpellGroupStack . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// 0 1
QueryResult result = WorldDatabase . Query ( "SELECT group_id, stack_rule FROM spell_group_stack_rules" );
if ( ! result )
2009-05-24 12:16:12 -05:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell group stack rules. DB table `spell_group_stack_rules` is empty." );
2011-07-26 23:09:28 +02:00
return ;
}
2010-01-01 14:19:29 -06:00
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2011-07-26 23:09:28 +02:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 group_id = fields [ 0 ]. GetUInt32 ();
2012-05-30 08:01:02 +02:00
uint8 stack_rule = fields [ 1 ]. GetInt8 ();
2011-07-26 23:09:28 +02:00
if ( stack_rule >= SPELL_GROUP_STACK_RULE_MAX )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "SpellGroupStackRule %u listed in `spell_group_stack_rules` does not exist" , stack_rule );
2009-05-24 12:16:12 -05:00
continue ;
2011-07-26 23:09:28 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellGroupSpellMapBounds spellGroup = GetSpellGroupSpellMapBounds (( SpellGroup ) group_id );
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( spellGroup . first == spellGroup . second )
2009-05-24 12:16:12 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "SpellGroup id %u listed in `spell_group_stack_rules` does not exist" , group_id );
2011-07-26 23:09:28 +02:00
continue ;
2009-05-24 12:16:12 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellGroupStack [( SpellGroup ) group_id ] = ( SpellGroupStackRule ) stack_rule ;
++ count ;
} while ( result -> NextRow ());
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u spell group stack rules in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2011-07-26 23:09:28 +02:00
}
2010-12-19 17:06:33 +01:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellProcEvents ()
{
uint32 oldMSTime = getMSTime ();
2010-12-19 17:06:33 +01:00
2011-07-26 23:09:28 +02:00
mSpellProcEventMap . clear (); // need for reload case
// 0 1 2 3 4 5 6 7 8 9 10
QueryResult result = WorldDatabase . Query ( "SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event" );
if ( ! result )
2009-05-24 12:16:12 -05:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell proc event conditions. DB table `spell_proc_event` is empty." );
2011-07-26 23:09:28 +02:00
return ;
}
2010-01-01 14:19:29 -06:00
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2011-07-26 23:09:28 +02:00
uint32 customProc = 0 ;
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2011-08-04 13:16:09 +02:00
SpellInfo const * spell = GetSpellInfo ( entry );
2011-07-26 23:09:28 +02:00
if ( ! spell )
2009-05-24 12:16:12 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_proc_event` does not exist" , entry );
2011-07-26 23:09:28 +02:00
continue ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellProcEventEntry spe ;
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
spe . schoolMask = fields [ 1 ]. GetInt8 ();
spe . spellFamilyName = fields [ 2 ]. GetUInt16 ();
2011-07-26 23:09:28 +02:00
spe . spellFamilyMask [ 0 ] = fields [ 3 ]. GetUInt32 ();
spe . spellFamilyMask [ 1 ] = fields [ 4 ]. GetUInt32 ();
spe . spellFamilyMask [ 2 ] = fields [ 5 ]. GetUInt32 ();
spe . procFlags = fields [ 6 ]. GetUInt32 ();
spe . procEx = fields [ 7 ]. GetUInt32 ();
spe . ppmRate = fields [ 8 ]. GetFloat ();
spe . customChance = fields [ 9 ]. GetFloat ();
spe . cooldown = fields [ 10 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellProcEventMap [ entry ] = spe ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( spell -> ProcFlags == 0 )
{
if ( spe . procFlags == 0 )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_proc_event` probally not triggered spell" , entry );
2011-07-26 23:09:28 +02:00
continue ;
2009-05-24 12:16:12 -05:00
}
2011-07-26 23:09:28 +02:00
customProc ++ ;
2009-05-24 12:16:12 -05:00
}
2011-07-26 23:09:28 +02:00
++ count ;
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( customProc )
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u extra and %u custom spell proc event conditions in %u ms" , count , customProc , GetMSTimeDiffToNow ( oldMSTime ));
2011-07-26 23:09:28 +02:00
else
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u extra spell proc event conditions in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2012-08-03 15:54:54 +02:00
2009-05-24 12:16:12 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellProcs ()
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
uint32 oldMSTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellProcMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
2011-07-26 23:09:28 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT spellId, schoolMask, spellFamilyName, spellFamilyMask0, spellFamilyMask1, spellFamilyMask2, typeMask, spellTypeMask, spellPhaseMask, hitMask, attributesMask, ratePerMinute, chance, cooldown, charges FROM spell_proc" );
if ( ! result )
2008-11-17 22:07:21 -06:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell proc conditions and data. DB table `spell_proc` is empty." );
2011-07-26 23:09:28 +02:00
return ;
}
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2011-07-26 23:09:28 +02:00
do
{
Field * fields = result -> Fetch ();
2010-02-14 19:13:14 -07:00
2011-07-26 23:09:28 +02:00
int32 spellId = fields [ 0 ]. GetInt32 ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
bool allRanks = false ;
2012-12-27 06:04:45 +01:00
if ( spellId < 0 )
2011-07-26 23:09:28 +02:00
{
allRanks = true ;
spellId = - spellId ;
}
2012-12-27 06:04:45 +01:00
SpellInfo const * spellInfo = GetSpellInfo ( spellId );
if ( ! spellInfo )
2011-07-26 23:09:28 +02:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_proc` does not exist" , spellId );
2011-07-26 23:09:28 +02:00
continue ;
}
if ( allRanks )
{
2012-12-27 06:04:45 +01:00
if ( spellInfo -> GetFirstRankSpell () -> Id != uint32 ( spellId ))
2011-07-26 23:09:28 +02:00
{
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_proc` is not first rank of spell." , spellId );
2011-07-26 23:09:28 +02:00
continue ;
2009-05-15 16:26:00 -05:00
}
2011-07-26 23:09:28 +02:00
}
SpellProcEntry baseProcEntry ;
2012-05-30 08:01:02 +02:00
baseProcEntry . schoolMask = fields [ 1 ]. GetInt8 ();
baseProcEntry . spellFamilyName = fields [ 2 ]. GetUInt16 ();
2011-07-26 23:09:28 +02:00
baseProcEntry . spellFamilyMask [ 0 ] = fields [ 3 ]. GetUInt32 ();
baseProcEntry . spellFamilyMask [ 1 ] = fields [ 4 ]. GetUInt32 ();
baseProcEntry . spellFamilyMask [ 2 ] = fields [ 5 ]. GetUInt32 ();
baseProcEntry . typeMask = fields [ 6 ]. GetUInt32 ();
baseProcEntry . spellTypeMask = fields [ 7 ]. GetUInt32 ();
baseProcEntry . spellPhaseMask = fields [ 8 ]. GetUInt32 ();
baseProcEntry . hitMask = fields [ 9 ]. GetUInt32 ();
baseProcEntry . attributesMask = fields [ 10 ]. GetUInt32 ();
baseProcEntry . ratePerMinute = fields [ 11 ]. GetFloat ();
baseProcEntry . chance = fields [ 12 ]. GetFloat ();
float cooldown = fields [ 13 ]. GetFloat ();
baseProcEntry . cooldown = uint32 ( cooldown );
baseProcEntry . charges = fields [ 14 ]. GetUInt32 ();
2012-12-27 06:04:45 +01:00
while ( spellInfo )
2011-07-26 23:09:28 +02:00
{
2012-12-27 06:04:45 +01:00
if ( mSpellProcMap . find ( spellInfo -> Id ) != mSpellProcMap . end ())
2009-05-15 16:26:00 -05:00
{
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_proc` has duplicate entry in the table" , spellInfo -> Id );
2009-05-15 16:26:00 -05:00
break ;
}
2011-07-26 23:09:28 +02:00
SpellProcEntry procEntry = SpellProcEntry ( baseProcEntry );
// take defaults from dbcs
if ( ! procEntry . typeMask )
2012-12-27 06:04:45 +01:00
procEntry . typeMask = spellInfo -> ProcFlags ;
2011-07-26 23:09:28 +02:00
if ( ! procEntry . charges )
2012-12-27 06:04:45 +01:00
procEntry . charges = spellInfo -> ProcCharges ;
2011-07-26 23:09:28 +02:00
if ( ! procEntry . chance && ! procEntry . ratePerMinute )
2012-12-27 06:04:45 +01:00
procEntry . chance = float ( spellInfo -> ProcChance );
2011-07-26 23:09:28 +02:00
// validate data
if ( procEntry . schoolMask & ~ SPELL_SCHOOL_MASK_ALL )
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has wrong `schoolMask` set: %u" , spellInfo -> Id , procEntry . schoolMask );
2011-07-26 23:09:28 +02:00
if ( procEntry . spellFamilyName && ( procEntry . spellFamilyName < 3 || procEntry . spellFamilyName > 17 || procEntry . spellFamilyName == 14 || procEntry . spellFamilyName == 16 ))
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has wrong `spellFamilyName` set: %u" , spellInfo -> Id , procEntry . spellFamilyName );
2011-07-26 23:09:28 +02:00
if ( procEntry . chance < 0 )
{
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has negative value in `chance` field" , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
procEntry . chance = 0 ;
}
if ( procEntry . ratePerMinute < 0 )
{
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has negative value in `ratePerMinute` field" , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
procEntry . ratePerMinute = 0 ;
}
if ( cooldown < 0 )
{
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has negative value in `cooldown` field" , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
procEntry . cooldown = 0 ;
}
if ( procEntry . chance == 0 && procEntry . ratePerMinute == 0 )
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u doesn't have `chance` and `ratePerMinute` values defined, proc will not be triggered" , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
if ( procEntry . charges > 99 )
{
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has too big value in `charges` field" , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
procEntry . charges = 99 ;
}
if ( ! procEntry . typeMask )
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u doesn't have `typeMask` value defined, proc will not be triggered" , spellInfo -> Id );
if ( procEntry . spellTypeMask & ~ PROC_SPELL_TYPE_MASK_ALL )
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has wrong `spellTypeMask` set: %u" , spellInfo -> Id , procEntry . spellTypeMask );
2011-07-26 23:09:28 +02:00
if ( procEntry . spellTypeMask && ! ( procEntry . typeMask & ( SPELL_PROC_FLAG_MASK | PERIODIC_PROC_FLAG_MASK )))
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has `spellTypeMask` value defined, but it won't be used for defined `typeMask` value" , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
if ( ! procEntry . spellPhaseMask && procEntry . typeMask & REQ_SPELL_PHASE_PROC_FLAG_MASK )
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u doesn't have `spellPhaseMask` value defined, but it's required for defined `typeMask` value, proc will not be triggered" , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
if ( procEntry . spellPhaseMask & ~ PROC_SPELL_PHASE_MASK_ALL )
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has wrong `spellPhaseMask` set: %u" , spellInfo -> Id , procEntry . spellPhaseMask );
2011-07-26 23:09:28 +02:00
if ( procEntry . spellPhaseMask && ! ( procEntry . typeMask & REQ_SPELL_PHASE_PROC_FLAG_MASK ))
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has `spellPhaseMask` value defined, but it won't be used for defined `typeMask` value" , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
if ( procEntry . hitMask & ~ PROC_HIT_MASK_ALL )
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has wrong `hitMask` set: %u" , spellInfo -> Id , procEntry . hitMask );
2011-07-26 23:09:28 +02:00
if ( procEntry . hitMask && ! ( procEntry . typeMask & TAKEN_HIT_PROC_FLAG_MASK || ( procEntry . typeMask & DONE_HIT_PROC_FLAG_MASK && ( ! procEntry . spellPhaseMask || procEntry . spellPhaseMask & ( PROC_SPELL_PHASE_HIT | PROC_SPELL_PHASE_FINISH )))))
2012-12-27 06:04:45 +01:00
sLog -> outError ( LOG_FILTER_SQL , "`spell_proc` table entry for spellId %u has `hitMask` value defined, but it won't be used for defined `typeMask` and `spellPhaseMask` values" , spellInfo -> Id );
2011-07-26 23:09:28 +02:00
2012-12-27 06:04:45 +01:00
mSpellProcMap [ spellInfo -> Id ] = procEntry ;
2011-07-26 23:09:28 +02:00
if ( allRanks )
2012-12-27 06:04:45 +01:00
spellInfo = spellInfo -> GetNextRankSpell ();
2011-07-26 23:09:28 +02:00
else
break ;
2009-05-15 16:26:00 -05:00
}
2011-07-26 23:09:28 +02:00
++ count ;
2012-12-27 06:04:45 +01:00
}
while ( result -> NextRow ());
2011-07-26 23:09:28 +02:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u spell proc conditions and data in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2011-07-26 23:09:28 +02:00
}
void SpellMgr :: LoadSpellBonusess ()
{
uint32 oldMSTime = getMSTime ();
mSpellBonusMap . clear (); // need for reload case
2012-05-30 08:01:02 +02:00
2011-07-26 23:09:28 +02:00
// 0 1 2 3 4
QueryResult result = WorldDatabase . Query ( "SELECT entry, direct_bonus, dot_bonus, ap_bonus, ap_dot_bonus FROM spell_bonus_data" );
if ( ! result )
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell bonus data. DB table `spell_bonus_data` is empty." );
2011-07-26 23:09:28 +02:00
return ;
2009-05-15 16:26:00 -05:00
}
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2011-07-26 23:09:28 +02:00
do
2009-05-15 16:26:00 -05:00
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2011-07-26 23:09:28 +02:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2011-08-04 13:16:09 +02:00
SpellInfo const * spell = GetSpellInfo ( entry );
2011-07-26 23:09:28 +02:00
if ( ! spell )
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_bonus_data` does not exist" , entry );
2011-07-26 23:09:28 +02:00
continue ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellBonusEntry & sbe = mSpellBonusMap [ entry ];
sbe . direct_damage = fields [ 1 ]. GetFloat ();
sbe . dot_damage = fields [ 2 ]. GetFloat ();
sbe . ap_bonus = fields [ 3 ]. GetFloat ();
sbe . ap_dot_bonus = fields [ 4 ]. GetFloat ();
++ count ;
} while ( result -> NextRow ());
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u extra spell bonus data in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellThreats ()
2008-11-17 22:07:21 -06:00
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2011-07-26 23:09:28 +02:00
mSpellThreatMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2011-08-21 12:00:36 +02:00
// 0 1 2 3
QueryResult result = WorldDatabase . Query ( "SELECT entry, flatMod, pctMod, apPctMod FROM spell_threat" );
2009-11-19 03:53:49 -08:00
if ( ! result )
2008-11-17 22:07:21 -06:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 aggro generating spells. DB table `spell_threat` is empty." );
2008-11-17 22:07:21 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2008-11-17 22:07:21 -06:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2011-08-04 13:16:09 +02:00
if ( ! GetSpellInfo ( entry ))
2008-11-17 22:07:21 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_threat` does not exist" , entry );
2008-11-17 22:07:21 -06:00
continue ;
}
2009-10-17 15:51:44 -07:00
2011-08-21 12:00:36 +02:00
SpellThreatEntry ste ;
2012-05-30 08:01:02 +02:00
ste . flatMod = fields [ 1 ]. GetInt32 ();
2011-08-21 12:00:36 +02:00
ste . pctMod = fields [ 2 ]. GetFloat ();
ste . apPctMod = fields [ 3 ]. GetFloat ();
2009-10-17 15:51:44 -07:00
2011-08-21 12:00:36 +02:00
mSpellThreatMap [ entry ] = ste ;
2011-09-13 14:15:35 +02:00
++ count ;
2011-07-26 23:09:28 +02:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u SpellThreatEntries in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2011-07-26 23:09:28 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSkillLineAbilityMap ()
{
uint32 oldMSTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSkillLineAbilityMap . clear ();
uint32 count = 0 ;
2011-09-13 14:15:35 +02:00
for ( uint32 i = 0 ; i < sSkillLineAbilityStore . GetNumRows (); ++ i )
2011-07-26 23:09:28 +02:00
{
SkillLineAbilityEntry const * SkillInfo = sSkillLineAbilityStore . LookupEntry ( i );
if ( ! SkillInfo )
2008-11-17 22:07:21 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSkillLineAbilityMap . insert ( SkillLineAbilityMap :: value_type ( SkillInfo -> spellId , SkillInfo ));
++ count ;
}
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u SkillLineAbility MultiMap Data in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2011-07-26 23:09:28 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellPetAuras ()
{
uint32 oldMSTime = getMSTime ();
mSpellPetAuraMap . clear (); // need for reload case
// 0 1 2 3
QueryResult result = WorldDatabase . Query ( "SELECT spell, effectId, pet, aura FROM spell_pet_auras" );
if ( ! result )
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell pet auras. DB table `spell_pet_auras` is empty." );
2011-07-26 23:09:28 +02:00
return ;
}
uint32 count = 0 ;
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2011-07-26 23:09:28 +02:00
uint32 spell = fields [ 0 ]. GetUInt32 ();
uint8 eff = fields [ 1 ]. GetUInt8 ();
uint32 pet = fields [ 2 ]. GetUInt32 ();
uint32 aura = fields [ 3 ]. GetUInt32 ();
SpellPetAuraMap :: iterator itr = mSpellPetAuraMap . find (( spell << 8 ) + eff );
if ( itr != mSpellPetAuraMap . end ())
itr -> second . AddAura ( pet , aura );
else
2009-05-15 16:26:00 -05:00
{
2011-08-04 13:16:09 +02:00
SpellInfo const * spellInfo = GetSpellInfo ( spell );
2009-11-19 03:53:49 -08:00
if ( ! spellInfo )
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_pet_auras` does not exist" , spell );
2009-05-15 16:26:00 -05:00
continue ;
}
2011-07-26 23:09:28 +02:00
if ( spellInfo -> Effects [ eff ]. Effect != SPELL_EFFECT_DUMMY &&
( spellInfo -> Effects [ eff ]. Effect != SPELL_EFFECT_APPLY_AURA ||
spellInfo -> Effects [ eff ]. ApplyAuraName != SPELL_AURA_DUMMY ))
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SPELLS_AURAS , "Spell %u listed in `spell_pet_auras` does not have dummy aura or dummy effect" , spell );
2009-05-15 16:26:00 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2011-08-04 13:16:09 +02:00
SpellInfo const * spellInfo2 = GetSpellInfo ( aura );
2011-07-26 23:09:28 +02:00
if ( ! spellInfo2 )
2008-11-17 22:07:21 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Aura %u listed in `spell_pet_auras` does not exist" , aura );
2011-07-26 23:09:28 +02:00
continue ;
2009-05-15 16:26:00 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-27 12:35:59 +02:00
PetAura pa ( pet , aura , spellInfo -> Effects [ eff ]. TargetA . GetTarget () == TARGET_UNIT_PET , spellInfo -> Effects [ eff ]. CalcValue ());
2011-07-26 23:09:28 +02:00
mSpellPetAuraMap [( spell << 8 ) + eff ] = pa ;
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2008-11-17 22:07:21 -06:00
++ count ;
2010-04-07 19:13:19 +02:00
} while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u spell pet auras in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// Fill custom data about enchancments
void SpellMgr :: LoadEnchantCustomAttr ()
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
uint32 oldMSTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 size = sSpellItemEnchantmentStore . GetNumRows ();
mEnchantCustomAttr . resize ( size );
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
for ( uint32 i = 0 ; i < size ; ++ i )
mEnchantCustomAttr [ i ] = 0 ;
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2011-07-26 23:09:28 +02:00
for ( uint32 i = 0 ; i < GetSpellInfoStoreSize (); ++ i )
2009-05-15 16:26:00 -05:00
{
2011-07-26 23:09:28 +02:00
SpellInfo const * spellInfo = GetSpellInfo ( i );
if ( ! spellInfo )
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// TODO: find a better check
2012-05-30 08:01:02 +02:00
if ( ! ( spellInfo -> AttributesEx2 & SPELL_ATTR2_PRESERVE_ENCHANT_IN_ARENA ) || ! ( spellInfo -> Attributes & SPELL_ATTR0_NOT_SHAPESHIFT ))
2011-07-26 23:09:28 +02:00
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
for ( uint32 j = 0 ; j < MAX_SPELL_EFFECTS ; ++ j )
2009-09-23 00:45:47 -07:00
{
2011-07-26 23:09:28 +02:00
if ( spellInfo -> Effects [ j ]. Effect == SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY )
2009-09-23 00:45:47 -07:00
{
2011-07-26 23:09:28 +02:00
uint32 enchId = spellInfo -> Effects [ j ]. MiscValue ;
SpellItemEnchantmentEntry const * ench = sSpellItemEnchantmentStore . LookupEntry ( enchId );
if ( ! ench )
continue ;
mEnchantCustomAttr [ enchId ] = true ;
++ count ;
break ;
2009-09-23 00:45:47 -07:00
}
}
}
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u custom enchant attributes in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellEnchantProcData ()
2008-11-17 22:07:21 -06:00
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2011-07-26 23:09:28 +02:00
mSpellEnchantProcEventMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// 0 1 2 3
QueryResult result = WorldDatabase . Query ( "SELECT entry, customChance, PPMChance, procEx FROM spell_enchant_proc_data" );
if ( ! result )
2011-06-17 22:35:05 +02:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell enchant proc event conditions. DB table `spell_enchant_proc_data` is empty." );
2011-07-26 23:09:28 +02:00
return ;
2011-06-17 22:35:05 +02:00
}
2012-05-30 08:01:02 +02:00
uint32 count = 0 ;
2011-07-26 23:09:28 +02:00
do
2008-11-17 22:07:21 -06:00
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 enchantId = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellItemEnchantmentEntry const * ench = sSpellItemEnchantmentStore . LookupEntry ( enchantId );
if ( ! ench )
2011-05-15 18:55:38 +07:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Enchancment %u listed in `spell_enchant_proc_data` does not exist" , enchantId );
2011-07-26 23:09:28 +02:00
continue ;
2011-05-15 18:55:38 +07:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
SpellEnchantProcEntry spe ;
2010-02-14 19:13:14 -07:00
2011-07-26 23:09:28 +02:00
spe . customChance = fields [ 1 ]. GetUInt32 ();
spe . PPMChance = fields [ 2 ]. GetFloat ();
spe . procEx = fields [ 3 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellEnchantProcEventMap [ enchantId ] = spe ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
++ count ;
} while ( result -> NextRow ());
2010-12-27 22:27:11 +01:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u enchant proc data definitions in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2010-12-27 22:27:11 +01:00
}
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellLinked ()
2008-11-17 22:07:21 -06:00
{
2011-07-26 23:09:28 +02:00
uint32 oldMSTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mSpellLinkedMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// 0 1 2
QueryResult result = WorldDatabase . Query ( "SELECT spell_trigger, spell_effect, type FROM spell_linked_spell" );
if ( ! result )
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 linked spells. DB table `spell_linked_spell` is empty." );
2011-07-26 23:09:28 +02:00
return ;
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 count = 0 ;
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
int32 trigger = fields [ 0 ]. GetInt32 ();
2012-05-30 08:01:02 +02:00
int32 effect = fields [ 1 ]. GetInt32 ();
int32 type = fields [ 2 ]. GetUInt8 ();
2010-02-14 19:13:14 -07:00
2011-08-04 13:16:09 +02:00
SpellInfo const * spellInfo = GetSpellInfo ( abs ( trigger ));
2011-07-26 23:09:28 +02:00
if ( ! spellInfo )
2011-06-28 13:53:48 +02:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_linked_spell` does not exist" , abs ( trigger ));
2011-07-26 23:09:28 +02:00
continue ;
2011-06-28 13:53:48 +02:00
}
2011-08-04 13:16:09 +02:00
spellInfo = GetSpellInfo ( abs ( effect ));
2011-07-26 23:09:28 +02:00
if ( ! spellInfo )
2011-06-28 13:53:48 +02:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_linked_spell` does not exist" , abs ( effect ));
2011-07-26 23:09:28 +02:00
continue ;
}
2010-06-16 19:36:50 +02:00
2011-07-26 23:09:28 +02:00
if ( type ) //we will find a better way when more types are needed
{
if ( trigger > 0 )
trigger += SPELL_LINKED_MAX_SPELLS * type ;
else
trigger -= SPELL_LINKED_MAX_SPELLS * type ;
2011-06-28 13:53:48 +02:00
}
2011-07-26 23:09:28 +02:00
mSpellLinkedMap [ trigger ]. push_back ( effect );
2010-01-21 01:28:18 +01:00
2011-07-26 23:09:28 +02:00
++ count ;
} while ( result -> NextRow ());
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u linked spells in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadPetLevelupSpellMap ()
2009-05-15 16:26:00 -05:00
{
2011-07-26 23:09:28 +02:00
uint32 oldMSTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
mPetLevelupSpellMap . clear (); // need for reload case
2010-01-23 17:05:20 +01:00
2011-07-26 23:09:28 +02:00
uint32 count = 0 ;
uint32 family_count = 0 ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
for ( uint32 i = 0 ; i < sCreatureFamilyStore . GetNumRows (); ++ i )
2009-05-15 16:26:00 -05:00
{
2011-07-26 23:09:28 +02:00
CreatureFamilyEntry const * creatureFamily = sCreatureFamilyStore . LookupEntry ( i );
if ( ! creatureFamily ) // not exist
continue ;
2009-10-17 16:20:24 -07:00
2011-07-26 23:09:28 +02:00
for ( uint8 j = 0 ; j < 2 ; ++ j )
2009-08-23 10:22:58 -05:00
{
2011-07-26 23:09:28 +02:00
if ( ! creatureFamily -> skillLine [ j ])
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
for ( uint32 k = 0 ; k < sSkillLineAbilityStore . GetNumRows (); ++ k )
{
SkillLineAbilityEntry const * skillLine = sSkillLineAbilityStore . LookupEntry ( k );
if ( ! skillLine )
continue ;
2011-02-27 03:53:24 +01:00
2011-07-26 23:09:28 +02:00
//if (skillLine->skillId != creatureFamily->skillLine[0] &&
// (!creatureFamily->skillLine[1] || skillLine->skillId != creatureFamily->skillLine[1]))
// continue;
2011-02-27 03:53:24 +01:00
2011-07-26 23:09:28 +02:00
if ( skillLine -> skillId != creatureFamily -> skillLine [ j ])
continue ;
2011-02-27 03:53:24 +01:00
2011-07-26 23:09:28 +02:00
if ( skillLine -> learnOnGetSkill != ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL )
continue ;
2011-02-27 03:53:24 +01:00
2011-08-04 13:16:09 +02:00
SpellInfo const * spell = GetSpellInfo ( skillLine -> spellId );
2011-07-26 23:09:28 +02:00
if ( ! spell ) // not exist or triggered or talent
continue ;
2011-02-27 03:53:24 +01:00
2011-07-26 23:09:28 +02:00
if ( ! spell -> SpellLevel )
continue ;
2011-02-27 03:53:24 +01:00
2011-07-26 23:09:28 +02:00
PetLevelupSpellSet & spellSet = mPetLevelupSpellMap [ creatureFamily -> ID ];
if ( spellSet . empty ())
++ family_count ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
spellSet . insert ( PetLevelupSpellSet :: value_type ( spell -> SpellLevel , spell -> Id ));
++ count ;
}
}
2009-08-23 10:22:58 -05:00
}
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u pet levelup and default spells for %u families in %u ms" , count , family_count , GetMSTimeDiffToNow ( oldMSTime ));
2009-05-15 16:26:00 -05:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
bool LoadPetDefaultSpells_helper ( CreatureTemplate const * cInfo , PetDefaultSpellsEntry & petDefSpells )
2009-05-15 16:26:00 -05:00
{
2011-07-26 23:09:28 +02:00
// skip empty list;
bool have_spell = false ;
for ( uint8 j = 0 ; j < MAX_CREATURE_SPELL_DATA_SLOT ; ++ j )
{
if ( petDefSpells . spellid [ j ])
{
have_spell = true ;
break ;
}
}
if ( ! have_spell )
2009-05-16 20:23:56 +02:00
return false ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// remove duplicates with levelupSpells if any
if ( PetLevelupSpellSet const * levelupSpells = cInfo -> family ? sSpellMgr -> GetPetLevelupSpellList ( cInfo -> family ) : NULL )
{
for ( uint8 j = 0 ; j < MAX_CREATURE_SPELL_DATA_SLOT ; ++ j )
{
if ( ! petDefSpells . spellid [ j ])
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
for ( PetLevelupSpellSet :: const_iterator itr = levelupSpells -> begin (); itr != levelupSpells -> end (); ++ itr )
{
if ( itr -> second == petDefSpells . spellid [ j ])
{
petDefSpells . spellid [ j ] = 0 ;
break ;
}
}
}
}
2010-07-26 19:27:28 +02:00
2011-07-26 23:09:28 +02:00
// skip empty list;
have_spell = false ;
for ( uint8 j = 0 ; j < MAX_CREATURE_SPELL_DATA_SLOT ; ++ j )
{
if ( petDefSpells . spellid [ j ])
{
have_spell = true ;
break ;
}
}
2010-07-26 19:27:28 +02:00
2011-07-26 23:09:28 +02:00
return have_spell ;
2010-07-26 19:27:28 +02:00
}
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadPetDefaultSpells ()
2010-07-26 19:27:28 +02:00
{
2011-07-26 23:09:28 +02:00
uint32 oldMSTime = getMSTime ();
2010-07-26 19:27:28 +02:00
2011-07-26 23:09:28 +02:00
mPetDefaultSpellsMap . clear ();
2010-07-26 19:27:28 +02:00
2011-07-26 23:09:28 +02:00
uint32 countCreature = 0 ;
uint32 countData = 0 ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
CreatureTemplateContainer const * ctc = sObjectMgr -> GetCreatureTemplates ();
for ( CreatureTemplateContainer :: const_iterator itr = ctc -> begin (); itr != ctc -> end (); ++ itr )
{
2010-12-19 17:06:33 +01:00
2011-07-26 23:09:28 +02:00
if ( ! itr -> second . PetSpellDataId )
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// for creature with PetSpellDataId get default pet spells from dbc
CreatureSpellDataEntry const * spellDataEntry = sCreatureSpellDataStore . LookupEntry ( itr -> second . PetSpellDataId );
if ( ! spellDataEntry )
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
int32 petSpellsId = - int32 ( itr -> second . PetSpellDataId );
PetDefaultSpellsEntry petDefSpells ;
for ( uint8 j = 0 ; j < MAX_CREATURE_SPELL_DATA_SLOT ; ++ j )
petDefSpells . spellid [ j ] = spellDataEntry -> spellId [ j ];
if ( LoadPetDefaultSpells_helper ( & itr -> second , petDefSpells ))
{
mPetDefaultSpellsMap [ petSpellsId ] = petDefSpells ;
++ countData ;
}
2009-07-31 13:21:01 +02:00
}
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded addition spells for %u pet spell data entries in %u ms" , countData , GetMSTimeDiffToNow ( oldMSTime ));
2012-08-03 15:54:54 +02:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , "Loading summonable creature templates..." );
2011-07-26 23:09:28 +02:00
oldMSTime = getMSTime ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// different summon spells
for ( uint32 i = 0 ; i < GetSpellInfoStoreSize (); ++ i )
{
2011-08-04 13:16:09 +02:00
SpellInfo const * spellEntry = GetSpellInfo ( i );
2011-07-26 23:09:28 +02:00
if ( ! spellEntry )
continue ;
for ( uint8 k = 0 ; k < MAX_SPELL_EFFECTS ; ++ k )
2009-07-31 13:21:01 +02:00
{
2011-07-26 23:09:28 +02:00
if ( spellEntry -> Effects [ k ]. Effect == SPELL_EFFECT_SUMMON || spellEntry -> Effects [ k ]. Effect == SPELL_EFFECT_SUMMON_PET )
{
uint32 creature_id = spellEntry -> Effects [ k ]. MiscValue ;
CreatureTemplate const * cInfo = sObjectMgr -> GetCreatureTemplate ( creature_id );
if ( ! cInfo )
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// already loaded
if ( cInfo -> PetSpellDataId )
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// for creature without PetSpellDataId get default pet spells from creature_template
int32 petSpellsId = cInfo -> Entry ;
if ( mPetDefaultSpellsMap . find ( cInfo -> Entry ) != mPetDefaultSpellsMap . end ())
continue ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
PetDefaultSpellsEntry petDefSpells ;
for ( uint8 j = 0 ; j < MAX_CREATURE_SPELL_DATA_SLOT ; ++ j )
petDefSpells . spellid [ j ] = cInfo -> spells [ j ];
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( LoadPetDefaultSpells_helper ( cInfo , petDefSpells ))
{
mPetDefaultSpellsMap [ petSpellsId ] = petDefSpells ;
++ countCreature ;
}
}
}
}
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u summonable creature templates in %u ms" , countCreature , GetMSTimeDiffToNow ( oldMSTime ));
2009-07-31 13:21:01 +02:00
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellAreas ()
2009-05-15 16:26:00 -05:00
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2011-07-26 23:09:28 +02:00
mSpellAreaMap . clear (); // need for reload case
mSpellAreaForQuestMap . clear ();
mSpellAreaForQuestEndMap . clear ();
mSpellAreaForAuraMap . clear ();
2009-10-17 15:51:44 -07:00
2012-10-16 21:43:23 -05:00
// 0 1 2 3 4 5 6 7 8 9
QueryResult result = WorldDatabase . Query ( "SELECT spell, area, quest_start, quest_start_status, quest_end_status, quest_end, aura_spell, racemask, gender, autocast FROM spell_area" );
2010-01-01 14:19:29 -06:00
if ( ! result )
2009-05-15 16:26:00 -05:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 spell area requirements. DB table `spell_area` is empty." );
2012-08-03 15:54:54 +02:00
2009-05-15 16:26:00 -05:00
return ;
}
2011-07-26 23:09:28 +02:00
uint32 count = 0 ;
2009-05-15 16:26:00 -05:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
uint32 spell = fields [ 0 ]. GetUInt32 ();
SpellArea spellArea ;
spellArea . spellId = spell ;
spellArea . areaId = fields [ 1 ]. GetUInt32 ();
spellArea . questStart = fields [ 2 ]. GetUInt32 ();
2012-10-16 21:43:23 -05:00
spellArea . questStartStatus = fields [ 3 ]. GetUInt32 ();
spellArea . questEndStatus = fields [ 4 ]. GetUInt32 ();
spellArea . questEnd = fields [ 5 ]. GetUInt32 ();
spellArea . auraSpell = fields [ 6 ]. GetInt32 ();
spellArea . raceMask = fields [ 7 ]. GetUInt32 ();
spellArea . gender = Gender ( fields [ 8 ]. GetUInt8 ());
spellArea . autocast = fields [ 9 ]. GetBool ();
2011-07-26 23:09:28 +02:00
2011-08-04 13:16:09 +02:00
if ( SpellInfo const * spellInfo = GetSpellInfo ( spell ))
2010-01-30 19:25:04 +01:00
{
2011-07-26 23:09:28 +02:00
if ( spellArea . autocast )
const_cast < SpellInfo *> ( spellInfo ) -> Attributes |= SPELL_ATTR0_CANT_CANCEL ;
2010-01-30 19:25:04 +01:00
}
2011-07-26 23:09:28 +02:00
else
2010-01-30 19:25:04 +01:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` does not exist" , spell );
2010-01-30 19:25:04 +01:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-05-15 16:26:00 -05:00
{
2011-07-26 23:09:28 +02:00
bool ok = true ;
SpellAreaMapBounds sa_bounds = GetSpellAreaMapBounds ( spellArea . spellId );
for ( SpellAreaMap :: const_iterator itr = sa_bounds . first ; itr != sa_bounds . second ; ++ itr )
{
if ( spellArea . spellId != itr -> second . spellId )
continue ;
if ( spellArea . areaId != itr -> second . areaId )
continue ;
if ( spellArea . questStart != itr -> second . questStart )
continue ;
if ( spellArea . auraSpell != itr -> second . auraSpell )
continue ;
if (( spellArea . raceMask & itr -> second . raceMask ) == 0 )
continue ;
if ( spellArea . gender != itr -> second . gender )
continue ;
2010-01-29 17:54:29 +01:00
2011-07-26 23:09:28 +02:00
// duplicate by requirements
2012-10-16 21:43:23 -05:00
ok = false ;
2011-07-26 23:09:28 +02:00
break ;
}
2010-01-29 17:54:29 +01:00
2011-07-26 23:09:28 +02:00
if ( ! ok )
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` already listed with similar requirements." , spell );
2011-07-26 23:09:28 +02:00
continue ;
2009-05-15 16:26:00 -05:00
}
2010-01-29 17:54:29 +01:00
}
2011-07-26 23:09:28 +02:00
if ( spellArea . areaId && ! GetAreaEntryByAreaID ( spellArea . areaId ))
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` have wrong area (%u) requirement" , spell , spellArea . areaId );
2009-05-15 16:26:00 -05:00
continue ;
}
2011-07-26 23:09:28 +02:00
if ( spellArea . questStart && ! sObjectMgr -> GetQuestTemplate ( spellArea . questStart ))
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` have wrong start quest (%u) requirement" , spell , spellArea . questStart );
2010-01-29 17:54:29 +01:00
continue ;
2009-05-15 16:26:00 -05:00
}
2011-07-26 23:09:28 +02:00
if ( spellArea . questEnd )
2009-05-15 16:26:00 -05:00
{
2011-07-26 23:09:28 +02:00
if ( ! sObjectMgr -> GetQuestTemplate ( spellArea . questEnd ))
2009-05-15 16:26:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` have wrong end quest (%u) requirement" , spell , spellArea . questEnd );
2011-07-26 23:09:28 +02:00
continue ;
2010-01-29 17:54:29 +01:00
}
2009-05-15 16:26:00 -05:00
}
2011-07-26 23:09:28 +02:00
if ( spellArea . auraSpell )
{
2011-08-04 13:16:09 +02:00
SpellInfo const * spellInfo = GetSpellInfo ( abs ( spellArea . auraSpell ));
2011-07-26 23:09:28 +02:00
if ( ! spellInfo )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` have wrong aura spell (%u) requirement" , spell , abs ( spellArea . auraSpell ));
2011-07-26 23:09:28 +02:00
continue ;
}
if ( uint32 ( abs ( spellArea . auraSpell )) == spellArea . spellId )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` have aura spell (%u) requirement for itself" , spell , abs ( spellArea . auraSpell ));
2011-07-26 23:09:28 +02:00
continue ;
}
// not allow autocast chains by auraSpell field (but allow use as alternative if not present)
if ( spellArea . autocast && spellArea . auraSpell > 0 )
{
bool chain = false ;
SpellAreaForAuraMapBounds saBound = GetSpellAreaForAuraMapBounds ( spellArea . spellId );
for ( SpellAreaForAuraMap :: const_iterator itr = saBound . first ; itr != saBound . second ; ++ itr )
{
if ( itr -> second -> autocast && itr -> second -> auraSpell > 0 )
{
chain = true ;
break ;
}
}
if ( chain )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` have aura spell (%u) requirement that itself autocast from aura" , spell , spellArea . auraSpell );
2011-07-26 23:09:28 +02:00
continue ;
}
SpellAreaMapBounds saBound2 = GetSpellAreaMapBounds ( spellArea . auraSpell );
for ( SpellAreaMap :: const_iterator itr2 = saBound2 . first ; itr2 != saBound2 . second ; ++ itr2 )
{
if ( itr2 -> second . autocast && itr2 -> second . auraSpell > 0 )
{
chain = true ;
break ;
}
}
if ( chain )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` have aura spell (%u) requirement that itself autocast from aura" , spell , spellArea . auraSpell );
2011-07-26 23:09:28 +02:00
continue ;
}
}
}
if ( spellArea . raceMask && ( spellArea . raceMask & RACEMASK_ALL_PLAYABLE ) == 0 )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` have wrong race mask (%u) requirement" , spell , spellArea . raceMask );
2009-05-15 16:26:00 -05:00
continue ;
2011-07-26 23:09:28 +02:00
}
if ( spellArea . gender != GENDER_NONE && spellArea . gender != GENDER_FEMALE && spellArea . gender != GENDER_MALE )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Spell %u listed in `spell_area` have wrong gender (%u) requirement" , spell , spellArea . gender );
2011-07-26 23:09:28 +02:00
continue ;
}
SpellArea const * sa = & mSpellAreaMap . insert ( SpellAreaMap :: value_type ( spell , spellArea )) -> second ;
// for search by current zone/subzone at zone/subzone change
if ( spellArea . areaId )
mSpellAreaForAreaMap . insert ( SpellAreaForAreaMap :: value_type ( spellArea . areaId , sa ));
// for search at quest start/reward
if ( spellArea . questStart )
2012-10-16 21:43:23 -05:00
mSpellAreaForQuestMap . insert ( SpellAreaForQuestMap :: value_type ( spellArea . questStart , sa ));
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
// for search at quest start/reward
if ( spellArea . questEnd )
mSpellAreaForQuestEndMap . insert ( SpellAreaForQuestMap :: value_type ( spellArea . questEnd , sa ));
// for search at aura apply
if ( spellArea . auraSpell )
mSpellAreaForAuraMap . insert ( SpellAreaForAuraMap :: value_type ( abs ( spellArea . auraSpell ), sa ));
++ count ;
} while ( result -> NextRow ());
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u spell area requirements in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2008-11-17 22:07:21 -06:00
}
2009-10-17 15:51:44 -07:00
2012-09-16 00:35:48 +02:00
// Temporary structure to hold spell effect entries for faster loading
struct SpellEffectArray
{
SpellEffectArray ()
{
effects [ 0 ] = NULL ;
effects [ 1 ] = NULL ;
effects [ 2 ] = NULL ;
}
SpellEffectEntry const * effects [ MAX_SPELL_EFFECTS ];
};
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellInfoStore ()
2008-11-17 22:07:21 -06:00
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2011-07-26 23:09:28 +02:00
UnloadSpellInfoStore ();
mSpellInfoMap . resize ( sSpellStore . GetNumRows (), NULL );
2010-01-01 14:19:29 -06:00
2012-09-15 22:02:17 +02:00
std :: map < uint32 , SpellEffectArray > effectsBySpell ;
for ( uint32 i = 0 ; i < sSpellEffectStore . GetNumRows (); ++ i )
{
SpellEffectEntry const * effect = sSpellEffectStore . LookupEntry ( i );
if ( ! effect )
continue ;
2012-09-16 00:35:48 +02:00
effectsBySpell [ effect -> EffectSpellId ]. effects [ effect -> EffectIndex ] = effect ;
2012-09-15 22:02:17 +02:00
}
2010-12-27 22:27:11 +01:00
for ( uint32 i = 0 ; i < sSpellStore . GetNumRows (); ++ i )
2011-07-26 23:09:28 +02:00
if ( SpellEntry const * spellEntry = sSpellStore . LookupEntry ( i ))
2012-09-15 22:02:17 +02:00
mSpellInfoMap [ i ] = new SpellInfo ( spellEntry , effectsBySpell [ i ]. effects );
2011-07-26 23:09:28 +02:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded spell info store in %u ms" , GetMSTimeDiffToNow ( oldMSTime ));
2011-07-26 23:09:28 +02:00
}
void SpellMgr :: UnloadSpellInfoStore ()
{
for ( uint32 i = 0 ; i < mSpellInfoMap . size (); ++ i )
{
if ( mSpellInfoMap [ i ])
2012-02-21 20:03:27 +01:00
delete mSpellInfoMap [ i ];
2011-07-26 23:09:28 +02:00
}
mSpellInfoMap . clear ();
}
2012-02-21 20:03:27 +01:00
void SpellMgr :: UnloadSpellInfoImplicitTargetConditionLists ()
{
for ( uint32 i = 0 ; i < mSpellInfoMap . size (); ++ i )
{
if ( mSpellInfoMap [ i ])
mSpellInfoMap [ i ] -> _UnloadImplicitTargetConditionLists ();
}
}
2011-07-26 23:09:28 +02:00
void SpellMgr :: LoadSpellCustomAttr ()
{
uint32 oldMSTime = getMSTime ();
SpellInfo * spellInfo = NULL ;
for ( uint32 i = 0 ; i < GetSpellInfoStoreSize (); ++ i )
{
spellInfo = mSpellInfoMap [ i ];
2009-11-20 19:11:28 -08:00
if ( ! spellInfo )
2009-05-15 16:26:00 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
for ( uint8 j = 0 ; j < MAX_SPELL_EFFECTS ; ++ j )
2009-05-15 16:26:00 -05:00
{
2011-07-26 23:09:28 +02:00
switch ( spellInfo -> Effects [ j ]. ApplyAuraName )
{
case SPELL_AURA_MOD_POSSESS :
case SPELL_AURA_MOD_CONFUSE :
case SPELL_AURA_MOD_CHARM :
case SPELL_AURA_AOE_CHARM :
case SPELL_AURA_MOD_FEAR :
case SPELL_AURA_MOD_STUN :
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_AURA_CC ;
break ;
2011-08-21 12:00:36 +02:00
case SPELL_AURA_PERIODIC_HEAL :
case SPELL_AURA_PERIODIC_DAMAGE :
case SPELL_AURA_PERIODIC_DAMAGE_PERCENT :
case SPELL_AURA_PERIODIC_LEECH :
case SPELL_AURA_PERIODIC_MANA_LEECH :
case SPELL_AURA_PERIODIC_HEALTH_FUNNEL :
case SPELL_AURA_PERIODIC_ENERGIZE :
case SPELL_AURA_OBS_MOD_HEALTH :
case SPELL_AURA_OBS_MOD_POWER :
2011-09-03 18:07:27 +02:00
case SPELL_AURA_POWER_BURN :
2011-08-21 12:00:36 +02:00
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT ;
break ;
2011-07-26 23:09:28 +02:00
}
2011-08-26 09:41:33 +02:00
2011-07-26 23:09:28 +02:00
switch ( spellInfo -> Effects [ j ]. Effect )
2009-05-15 16:26:00 -05:00
{
case SPELL_EFFECT_SCHOOL_DAMAGE :
case SPELL_EFFECT_WEAPON_DAMAGE :
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL :
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG :
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE :
case SPELL_EFFECT_HEAL :
2011-07-26 23:09:28 +02:00
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_DIRECT_DAMAGE ;
2009-05-15 16:26:00 -05:00
break ;
2011-08-21 12:00:36 +02:00
case SPELL_EFFECT_POWER_DRAIN :
case SPELL_EFFECT_POWER_BURN :
case SPELL_EFFECT_HEAL_MAX_HEALTH :
case SPELL_EFFECT_HEALTH_LEECH :
case SPELL_EFFECT_HEAL_PCT :
case SPELL_EFFECT_ENERGIZE_PCT :
case SPELL_EFFECT_ENERGIZE :
case SPELL_EFFECT_HEAL_MECHANICAL :
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_NO_INITIAL_THREAT ;
break ;
2009-05-15 16:26:00 -05:00
case SPELL_EFFECT_CHARGE :
2010-07-19 19:22:05 +02:00
case SPELL_EFFECT_CHARGE_DEST :
2009-05-15 16:26:00 -05:00
case SPELL_EFFECT_JUMP :
2010-07-19 21:24:09 +02:00
case SPELL_EFFECT_JUMP_DEST :
2009-08-27 20:14:50 -05:00
case SPELL_EFFECT_LEAP_BACK :
2011-07-26 23:09:28 +02:00
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_CHARGE ;
2009-05-15 16:26:00 -05:00
break ;
2010-01-13 18:22:31 +01:00
case SPELL_EFFECT_PICKPOCKET :
2011-07-26 23:09:28 +02:00
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_PICKPOCKET ;
2009-05-15 16:26:00 -05:00
break ;
2010-12-27 22:27:11 +01:00
case SPELL_EFFECT_ENCHANT_ITEM :
case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY :
case SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC :
case SPELL_EFFECT_ENCHANT_HELD_ITEM :
{
// only enchanting profession enchantments procs can stack
if ( IsPartOfSkillLine ( SKILL_ENCHANTING , i ))
{
2011-07-26 23:09:28 +02:00
uint32 enchantId = spellInfo -> Effects [ j ]. MiscValue ;
2011-06-28 23:48:59 +07:00
SpellItemEnchantmentEntry const * enchant = sSpellItemEnchantmentStore . LookupEntry ( enchantId );
2010-12-27 22:27:11 +01:00
for ( uint8 s = 0 ; s < MAX_ITEM_ENCHANTMENT_EFFECTS ; ++ s )
{
if ( enchant -> type [ s ] != ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL )
continue ;
2011-08-26 09:41:33 +02:00
SpellInfo * procInfo = ( SpellInfo * ) GetSpellInfo ( enchant -> spellid [ s ]);
2010-12-27 22:27:11 +01:00
if ( ! procInfo )
continue ;
// if proced directly from enchantment, not via proc aura
// NOTE: Enchant Weapon - Blade Ward also has proc aura spell and is proced directly
// however its not expected to stack so this check is good
2011-07-26 23:09:28 +02:00
if ( procInfo -> HasAura ( SPELL_AURA_PROC_TRIGGER_SPELL ))
2010-12-27 22:27:11 +01:00
continue ;
2011-07-26 23:09:28 +02:00
procInfo -> AttributesCu |= SPELL_ATTR0_CU_ENCHANT_PROC ;
2010-12-27 22:27:11 +01:00
}
}
break ;
}
2009-05-15 16:26:00 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( ! spellInfo -> _IsPositiveEffect ( EFFECT_0 , false ))
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF0 ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( ! spellInfo -> _IsPositiveEffect ( EFFECT_1 , false ))
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF1 ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( ! spellInfo -> _IsPositiveEffect ( EFFECT_2 , false ))
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF2 ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
if ( spellInfo -> SpellVisual [ 0 ] == 3879 )
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_CONE_BACK ;
2009-10-17 15:51:44 -07:00
2011-07-26 23:09:28 +02:00
switch ( spellInfo -> Id )
2009-05-15 16:26:00 -05:00
{
2012-08-28 21:37:13 +02:00
case 60256 :
//Crashes client on pressing ESC (Maybe because of ReqSpellFocus and GameObject)
spellInfo -> AttributesEx4 &= ~ SPELL_ATTR4_TRIGGERED ;
break ;
2011-08-01 12:05:30 +02:00
case 1776 : // Gouge
case 1777 :
case 8629 :
case 11285 :
case 11286 :
case 12540 :
case 13579 :
case 24698 :
case 28456 :
case 29425 :
case 34940 :
case 36862 :
case 38764 :
case 38863 :
case 52743 : // Head Smack
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER ;
break ;
case 53 : // Backstab
case 2589 :
case 2590 :
case 2591 :
case 8721 :
case 11279 :
case 11280 :
case 11281 :
case 25300 :
case 26863 :
case 48656 :
case 48657 :
case 703 : // Garrote
case 8631 :
case 8632 :
case 8633 :
case 11289 :
case 11290 :
case 26839 :
case 26884 :
case 48675 :
case 48676 :
case 5221 : // Shred
case 6800 :
case 8992 :
case 9829 :
case 9830 :
case 27001 :
case 27002 :
case 48571 :
case 48572 :
case 8676 : // Ambush
case 8724 :
case 8725 :
case 11267 :
case 11268 :
case 11269 :
case 27441 :
case 48689 :
case 48690 :
case 48691 :
2011-12-05 10:20:06 -05:00
case 6785 : // Ravage
case 6787 :
case 9866 :
2011-12-05 23:11:53 +02:00
case 9867 :
2011-12-05 10:20:06 -05:00
case 27005 :
case 48578 :
case 48579 :
2011-08-01 12:05:30 +02:00
case 21987 : // Lash of Pain
case 23959 : // Test Stab R50
case 24825 : // Test Backstab
case 58563 : // Assassinate Restless Lookout
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET ;
break ;
case 26029 : // Dark Glare
case 37433 : // Spout
case 43140 : // Flame Breath
case 43215 : // Flame Breath
case 70461 : // Coldflame Trap
2011-10-05 20:48:34 +02:00
case 72133 : // Pain and Suffering
case 73788 : // Pain and Suffering
case 73789 : // Pain and Suffering
case 73790 : // Pain and Suffering
2011-08-01 12:05:30 +02:00
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_CONE_LINE ;
break ;
case 24340 : // Meteor
case 26558 : // Meteor
case 28884 : // Meteor
case 36837 : // Meteor
case 38903 : // Meteor
case 41276 : // Meteor
case 57467 : // Meteor
case 26789 : // Shard of the Fallen Star
case 31436 : // Malevolent Cleave
case 35181 : // Dive Bomb
case 40810 : // Saber Lash
case 43267 : // Saber Lash
case 43268 : // Saber Lash
case 42384 : // Brutal Swipe
case 45150 : // Meteor Slash
case 64688 : // Sonic Screech
case 72373 : // Shared Suffering
case 71904 : // Chaos Bane
case 70492 : // Ooze Eruption
case 72505 : // Ooze Eruption
case 72624 : // Ooze Eruption
case 72625 : // Ooze Eruption
// ONLY SPELLS WITH SPELLFAMILY_GENERIC and EFFECT_SCHOOL_DAMAGE
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE ;
break ;
case 18500 : // Wing Buffet
case 33086 : // Wild Bite
case 49749 : // Piercing Blow
case 52890 : // Penetrating Strike
case 53454 : // Impale
case 59446 : // Impale
case 62383 : // Shatter
case 64777 : // Machine Gun
case 65239 : // Machine Gun
case 65919 : // Impale
case 67858 : // Impale
case 67859 : // Impale
case 67860 : // Impale
case 69293 : // Wing Buffet
case 74439 : // Machine Gun
case 63278 : // Mark of the Faceless (General Vezax)
2012-01-30 00:21:42 +01:00
case 62544 : // Thrust (Argent Tournament)
case 64588 : // Thrust (Argent Tournament)
case 66479 : // Thrust (Argent Tournament)
case 68505 : // Thrust (Argent Tournament)
2012-02-05 13:17:10 +01:00
case 62709 : // Counterattack! (Argent Tournament)
2012-01-30 00:21:42 +01:00
case 62626 : // Break-Shield (Argent Tournament, Player)
case 64590 : // Break-Shield (Argent Tournament, Player)
case 64342 : // Break-Shield (Argent Tournament, NPC)
case 64686 : // Break-Shield (Argent Tournament, NPC)
case 65147 : // Break-Shield (Argent Tournament, NPC)
case 68504 : // Break-Shield (Argent Tournament, NPC)
case 62874 : // Charge (Argent Tournament, Player)
case 68498 : // Charge (Argent Tournament, Player)
case 64591 : // Charge (Argent Tournament, Player)
case 63003 : // Charge (Argent Tournament, NPC)
case 63010 : // Charge (Argent Tournament, NPC)
case 68321 : // Charge (Argent Tournament, NPC)
2011-09-27 21:44:29 +02:00
case 72255 : // Mark of the Fallen Champion (Deathbringer Saurfang)
case 72444 : // Mark of the Fallen Champion (Deathbringer Saurfang)
case 72445 : // Mark of the Fallen Champion (Deathbringer Saurfang)
case 72446 : // Mark of the Fallen Champion (Deathbringer Saurfang)
2011-08-01 12:05:30 +02:00
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR ;
break ;
case 64422 : // Sonic Screech (Auriaya)
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE ;
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR ;
break ;
2011-09-16 11:29:35 +02:00
case 72293 : // Mark of the Fallen Champion (Deathbringer Saurfang)
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF0 ;
break ;
2011-08-26 09:41:33 +02:00
default :
break ;
2011-07-26 23:09:28 +02:00
}
switch ( spellInfo -> SpellFamilyName )
{
case SPELLFAMILY_WARRIOR :
// Shout
if ( spellInfo -> SpellFamilyFlags [ 0 ] & 0x20000 || spellInfo -> SpellFamilyFlags [ 1 ] & 0x20 )
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_AURA_CC ;
break ;
case SPELLFAMILY_DRUID :
// Roar
if ( spellInfo -> SpellFamilyFlags [ 0 ] & 0x8 )
spellInfo -> AttributesCu |= SPELL_ATTR0_CU_AURA_CC ;
break ;
default :
break ;
}
}
CreatureAI :: FillAISpellInfo ();
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded spell custom attributes in %u ms" , GetMSTimeDiffToNow ( oldMSTime ));
2011-07-26 23:09:28 +02:00
}
2012-12-24 12:34:46 -05:00
void SpellMgr :: LoadSpellInfoCorrections ()
2011-07-26 23:09:28 +02:00
{
uint32 oldMSTime = getMSTime ();
2012-12-24 12:34:46 -05:00
SpellInfo * spellInfo = NULL ;
for ( uint32 i = 0 ; i < mSpellInfoMap . size (); ++ i )
2011-07-26 23:09:28 +02:00
{
2012-12-24 12:34:46 -05:00
spellInfo = ( SpellInfo * ) mSpellInfoMap [ i ];
2011-07-26 23:09:28 +02:00
if ( ! spellInfo )
continue ;
for ( uint8 j = 0 ; j < MAX_SPELL_EFFECTS ; ++ j )
{
2012-12-24 12:34:46 -05:00
switch ( spellInfo -> Effects [ j ]. Effect )
2011-07-26 23:09:28 +02:00
{
case SPELL_EFFECT_CHARGE :
case SPELL_EFFECT_CHARGE_DEST :
case SPELL_EFFECT_JUMP :
case SPELL_EFFECT_JUMP_DEST :
case SPELL_EFFECT_LEAP_BACK :
2012-12-24 12:34:46 -05:00
if ( ! spellInfo -> Speed && ! spellInfo -> SpellFamilyName )
spellInfo -> Speed = SPEED_CHARGE ;
2011-07-26 23:09:28 +02:00
break ;
}
}
2012-12-24 12:34:46 -05:00
if ( spellInfo -> ActiveIconID == 2158 ) // flight
2011-07-26 23:09:28 +02:00
spellInfo -> Attributes |= SPELL_ATTR0_PASSIVE ;
switch ( spellInfo -> Id )
{
2012-12-07 18:10:20 +01:00
case 53096 : // Quetz'lun's Judgment
2012-12-07 16:08:29 +01:00
spellInfo -> MaxAffectedTargets = 1 ;
break ;
2012-09-23 22:16:28 +01:00
case 42730 :
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. TriggerSpell = 42739 ;
2012-08-28 18:35:26 +02:00
break ;
case 59735 :
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. TriggerSpell = 59736 ;
2012-08-28 18:35:26 +02:00
break ;
case 52611 : // Summon Skeletons
case 52612 : // Summon Skeletons
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. MiscValueB = 64 ;
2012-08-28 18:35:26 +02:00
break ;
2012-05-28 04:07:51 +02:00
case 40244 : // Simon Game Visual
case 40245 : // Simon Game Visual
case 40246 : // Simon Game Visual
case 40247 : // Simon Game Visual
2012-01-06 01:19:07 +01:00
case 42835 : // Spout, remove damage effect, only anim is needed
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. Effect = 0 ;
2011-08-21 15:01:40 +02:00
break ;
case 30657 : // Quake
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TriggerSpell = 30571 ;
2011-08-21 15:01:40 +02:00
break ;
case 30541 : // Blaze (needs conditions entry)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_UNIT_TARGET_ENEMY );
spellInfo -> Effects [ EFFECT_0 ]. TargetB = SpellImplicitTargetInfo ();
2011-08-21 15:01:40 +02:00
break ;
2012-01-30 00:21:42 +01:00
case 63665 : // Charge (Argent Tournament emote on riders)
2011-08-21 15:01:40 +02:00
case 31298 : // Sleep (needs target selection script)
2011-11-26 21:42:40 +02:00
case 51904 : // Summon Ghouls On Scarlet Crusade (this should use conditions table, script for this spell needs to be fixed)
case 2895 : // Wrath of Air Totem rank 1 (Aura)
case 68933 : // Wrath of Air Totem rank 2 (Aura)
2011-11-26 14:59:56 -07:00
case 29200 : // Purify Helboar Meat
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_UNIT_CASTER );
spellInfo -> Effects [ EFFECT_0 ]. TargetB = SpellImplicitTargetInfo ();
2011-08-21 15:01:40 +02:00
break ;
case 31344 : // Howl of Azgalor
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_100_YARDS ); // 100yards instead of 50000?!
2011-08-21 15:01:40 +02:00
break ;
case 42818 : // Headless Horseman - Wisp Flight Port
case 42821 : // Headless Horseman - Wisp Flight Missile
2012-12-24 12:34:46 -05:00
spellInfo -> RangeEntry = sSpellRangeStore . LookupEntry ( 6 ); // 100 yards
2011-08-21 15:01:40 +02:00
break ;
case 36350 : //They Must Burn Bomb Aura (self)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TriggerSpell = 36325 ; // They Must Burn Bomb Drop (DND)
2011-08-21 15:01:40 +02:00
break ;
case 49838 : // Stop Time
spellInfo -> AttributesEx3 |= SPELL_ATTR3_NO_INITIAL_AGGRO ;
break ;
case 61407 : // Energize Cores
case 62136 : // Energize Cores
case 54069 : // Energize Cores
case 56251 : // Energize Cores
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_UNIT_SRC_AREA_ENTRY );
2011-08-26 18:04:35 +01:00
break ;
2011-08-21 15:01:40 +02:00
case 50785 : // Energize Cores
case 59372 : // Energize Cores
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_UNIT_SRC_AREA_ENEMY );
2011-08-21 15:01:40 +02:00
break ;
case 8494 : // Mana Shield (rank 2)
// because of bug in dbc
2012-12-24 12:34:46 -05:00
spellInfo -> ProcChance = 0 ;
2011-08-21 15:01:40 +02:00
break ;
case 20335 : // Heart of the Crusader
case 20336 :
case 20337 :
case 63320 : // Glyph of Life Tap
// Entries were not updated after spell effect change, we have to do that manually :/
spellInfo -> AttributesEx3 |= SPELL_ATTR3_CAN_PROC_WITH_TRIGGERED ;
break ;
case 59725 : // Improved Spell Reflection - aoe aura
// Target entry seems to be wrong for this spell :/
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_UNIT_CASTER_AREA_PARTY );
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_10_YARDS_2 );
2011-08-21 15:01:40 +02:00
break ;
2011-11-26 21:42:40 +02:00
case 44978 : // Wild Magic
case 45001 :
case 45002 :
case 45004 :
case 45006 :
case 45010 :
2011-08-21 15:01:40 +02:00
case 31347 : // Doom
case 41635 : // Prayer of Mending
case 44869 : // Spectral Blast
case 45027 : // Revitalize
case 45976 : // Muru Portal Channel
case 39365 : // Thundering Storm
case 41071 : // Raise Dead (HACK)
case 52124 : // Sky Darkener Assault
case 42442 : // Vengeance Landing Cannonfire
case 45863 : // Cosmetic - Incinerate to Random Target
case 25425 : // Shoot
case 45761 : // Shoot
case 42611 : // Shoot
case 61588 : // Blazing Harpoon
case 52479 : // Gift of the Harvester
2012-01-08 23:07:31 +00:00
case 48246 : // Ball of Flame
2011-08-21 15:01:40 +02:00
spellInfo -> MaxAffectedTargets = 1 ;
break ;
2012-06-06 19:05:17 -02:30
case 36384 : // Skartax Purple Beam
spellInfo -> MaxAffectedTargets = 2 ;
break ;
2011-08-21 15:01:40 +02:00
case 41376 : // Spite
case 39992 : // Needle Spine
case 29576 : // Multi-Shot
case 40816 : // Saber Lash
case 37790 : // Spread Shot
case 46771 : // Flame Sear
case 45248 : // Shadow Blades
case 41303 : // Soul Drain
case 54172 : // Divine Storm (heal)
case 29213 : // Curse of the Plaguebringer - Noth
case 28542 : // Life Drain - Sapphiron
case 66588 : // Flaming Spear
case 54171 : // Divine Storm
spellInfo -> MaxAffectedTargets = 3 ;
break ;
case 38310 : // Multi-Shot
case 53385 : // Divine Storm (Damage)
spellInfo -> MaxAffectedTargets = 4 ;
break ;
case 42005 : // Bloodboil
case 38296 : // Spitfire Totem
case 37676 : // Insidious Whisper
case 46008 : // Negative Energy
case 45641 : // Fire Bloom
case 55665 : // Life Drain - Sapphiron (H)
case 28796 : // Poison Bolt Volly - Faerlina
spellInfo -> MaxAffectedTargets = 5 ;
break ;
case 40827 : // Sinful Beam
case 40859 : // Sinister Beam
case 40860 : // Vile Beam
case 40861 : // Wicked Beam
case 54835 : // Curse of the Plaguebringer - Noth (H)
case 54098 : // Poison Bolt Volly - Faerlina (H)
spellInfo -> MaxAffectedTargets = 10 ;
break ;
case 50312 : // Unholy Frenzy
spellInfo -> MaxAffectedTargets = 15 ;
break ;
2012-06-03 22:12:04 -02:30
case 33711 : // Murmur's Touch
2011-11-26 21:42:40 +02:00
case 38794 :
2011-08-21 15:01:40 +02:00
spellInfo -> MaxAffectedTargets = 1 ;
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TriggerSpell = 33760 ;
2011-08-21 15:01:40 +02:00
break ;
case 17941 : // Shadow Trance
case 22008 : // Netherwind Focus
case 31834 : // Light's Grace
case 34754 : // Clearcasting
case 34936 : // Backlash
case 48108 : // Hot Streak
case 51124 : // Killing Machine
case 54741 : // Firestarter
case 57761 : // Fireball!
case 39805 : // Lightning Overload
case 64823 : // Item - Druid T8 Balance 4P Bonus
2011-09-03 18:26:39 +02:00
case 34477 : // Misdirection
2011-08-21 15:01:40 +02:00
case 44401 : // Missile Barrage
2012-12-24 12:34:46 -05:00
spellInfo -> ProcCharges = 1 ;
2011-08-21 15:01:40 +02:00
break ;
case 44544 : // Fingers of Frost
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. SpellClassMask = flag96 ( 685904631 , 1151048 , 0 );
2011-08-21 15:01:40 +02:00
break ;
case 74396 : // Fingers of Frost visual buff
2012-12-24 12:34:46 -05:00
spellInfo -> ProcCharges = 2 ;
2011-08-21 15:01:40 +02:00
spellInfo -> StackAmount = 0 ;
break ;
case 28200 : // Ascendance (Talisman of Ascendance trinket)
2012-12-24 12:34:46 -05:00
spellInfo -> ProcCharges = 6 ;
2011-08-21 15:01:40 +02:00
break ;
case 47201 : // Everlasting Affliction
case 47202 :
case 47203 :
case 47204 :
case 47205 :
// add corruption to affected spells
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ 1 ]. SpellClassMask [ 0 ] |= 2 ;
2011-08-21 15:01:40 +02:00
break ;
case 51852 : // The Eye of Acherus (no spawn in phase 2 in db)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ 0 ]. MiscValue |= 1 ;
2011-08-21 15:01:40 +02:00
break ;
2012-05-28 04:07:51 +02:00
case 51912 : // Crafty's Ultra-Advanced Proto-Typical Shortening Blaster
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ 0 ]. Amplitude = 3000 ;
2012-05-28 04:07:51 +02:00
break ;
2011-08-21 15:01:40 +02:00
case 29809 : // Desecration Arm - 36 instead of 37 - typo? :/
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_7_YARDS );
2011-08-21 15:01:40 +02:00
break ;
// Master Shapeshifter: missing stance data for forms other than bear - bear version has correct data
// To prevent aura staying on target after talent unlearned
case 48420 :
spellInfo -> Stances = 1 << ( FORM_CAT - 1 );
break ;
case 48421 :
spellInfo -> Stances = 1 << ( FORM_MOONKIN - 1 );
break ;
case 48422 :
spellInfo -> Stances = 1 << ( FORM_TREE - 1 );
break ;
2011-10-10 18:01:02 -03:00
case 51466 : // Elemental Oath (Rank 1)
case 51470 : // Elemental Oath (Rank 2)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. Effect = SPELL_EFFECT_APPLY_AURA ;
spellInfo -> Effects [ EFFECT_1 ]. ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER ;
spellInfo -> Effects [ EFFECT_1 ]. MiscValue = SPELLMOD_EFFECT2 ;
spellInfo -> Effects [ EFFECT_1 ]. SpellClassMask = flag96 ( 0x00000000 , 0x00004000 , 0x00000000 );
2011-10-10 18:01:02 -03:00
break ;
2011-08-21 15:01:40 +02:00
case 47569 : // Improved Shadowform (Rank 1)
// with this spell atrribute aura can be stacked several times
spellInfo -> Attributes &= ~ SPELL_ATTR0_NOT_SHAPESHIFT ;
break ;
2011-10-12 01:11:52 +03:00
case 64904 : // Hymn of Hope
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. ApplyAuraName = SPELL_AURA_MOD_INCREASE_ENERGY_PERCENT ;
2011-09-26 20:12:25 +03:00
break ;
2011-08-21 15:01:40 +02:00
case 30421 : // Nether Portal - Perseverence
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ 2 ]. BasePoints += 30000 ;
2011-08-21 15:01:40 +02:00
break ;
case 51735 : // Ebon Plague
case 51734 :
case 51726 :
spellInfo -> AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS ;
spellInfo -> SpellFamilyFlags [ 2 ] = 0x10 ;
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ 1 ]. ApplyAuraName = SPELL_AURA_MOD_DAMAGE_PERCENT_TAKEN ;
2011-08-21 15:01:40 +02:00
break ;
2011-08-25 10:21:19 +02:00
case 41913 : // Parasitic Shadowfiend Passive
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ 0 ]. ApplyAuraName = SPELL_AURA_DUMMY ; // proc debuff, and summon infinite fiends
2011-08-21 15:01:40 +02:00
break ;
case 27892 : // To Anchor 1
case 27928 : // To Anchor 1
case 27935 : // To Anchor 1
case 27915 : // Anchor to Skulls
case 27931 : // Anchor to Skulls
case 27937 : // Anchor to Skulls
2012-12-24 12:34:46 -05:00
spellInfo -> RangeEntry = sSpellRangeStore . LookupEntry ( 13 );
2011-08-21 15:01:40 +02:00
break ;
// target allys instead of enemies, target A is src_caster, spells with effect like that have ally target
// this is the only known exception, probably just wrong data
case 29214 : // Wrath of the Plaguebringer
case 54836 : // Wrath of the Plaguebringer
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetB = SpellImplicitTargetInfo ( TARGET_UNIT_SRC_AREA_ALLY );
spellInfo -> Effects [ EFFECT_1 ]. TargetB = SpellImplicitTargetInfo ( TARGET_UNIT_SRC_AREA_ALLY );
2011-08-21 15:01:40 +02:00
break ;
case 63675 : // Improved Devouring Plague
spellInfo -> AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS ;
break ;
case 8145 : // Tremor Totem (instant pulse)
case 6474 : // Earthbind Totem (instant pulse)
spellInfo -> AttributesEx5 |= SPELL_ATTR5_START_PERIODIC_AT_APPLY ;
break ;
case 53241 : // Marked for Death (Rank 1)
case 53243 : // Marked for Death (Rank 2)
case 53244 : // Marked for Death (Rank 3)
case 53245 : // Marked for Death (Rank 4)
case 53246 : // Marked for Death (Rank 5)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. SpellClassMask = flag96 ( 0x00067801 , 0x10820001 , 0x00000801 );
2011-08-21 15:01:40 +02:00
break ;
2012-08-16 19:55:01 +01:00
case 5176 : // Wrath
case 2912 : // Starfire
case 78674 : // Starsurge
spellInfo -> Effects [ 1 ]. Effect = SPELL_EFFECT_DUMMY ;
spellInfo -> Effects [ 1 ]. TargetA = TARGET_UNIT_CASTER ;
break ;
2011-09-25 13:29:17 +02:00
case 70728 : // Exploit Weakness (needs target selection script)
case 70840 : // Devious Minds (needs target selection script)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_UNIT_CASTER );
spellInfo -> Effects [ EFFECT_0 ]. TargetB = SpellImplicitTargetInfo ( TARGET_UNIT_PET );
2011-08-21 15:01:40 +02:00
break ;
2011-09-25 13:29:17 +02:00
case 70893 : // Culling The Herd (needs target selection script)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_UNIT_CASTER );
spellInfo -> Effects [ EFFECT_0 ]. TargetB = SpellImplicitTargetInfo ( TARGET_UNIT_MASTER );
2011-08-21 15:01:40 +02:00
break ;
case 54800 : // Sigil of the Frozen Conscience - change class mask to custom extended flags of Icy Touch
// this is done because another spell also uses the same SpellFamilyFlags as Icy Touch
// SpellFamilyFlags[0] & 0x00000040 in SPELLFAMILY_DEATHKNIGHT is currently unused (3.3.5a)
// this needs research on modifier applying rules, does not seem to be in Attributes fields
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. SpellClassMask = flag96 ( 0x00000040 , 0x00000000 , 0x00000000 );
2011-08-21 15:01:40 +02:00
break ;
2012-08-21 23:40:38 +01:00
case 64949 : // Idol of the Flourishing Life
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. SpellClassMask = flag96 ( 0x00000000 , 0x02000000 , 0x00000000 );
spellInfo -> Effects [ EFFECT_0 ]. ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER ;
2012-08-21 23:40:38 +01:00
break ;
case 34231 : // Libram of the Lightbringer
case 60792 : // Libram of Tolerance
case 64956 : // Libram of the Resolute
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. SpellClassMask = flag96 ( 0x80000000 , 0x00000000 , 0x00000000 );
spellInfo -> Effects [ EFFECT_0 ]. ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER ;
2012-08-21 23:40:38 +01:00
break ;
case 28851 : // Libram of Light
case 28853 : // Libram of Divinity
case 32403 : // Blessed Book of Nagrand
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. SpellClassMask = flag96 ( 0x40000000 , 0x00000000 , 0x00000000 );
spellInfo -> Effects [ EFFECT_0 ]. ApplyAuraName = SPELL_AURA_ADD_FLAT_MODIFIER ;
2012-08-21 23:40:38 +01:00
break ;
2012-06-03 15:12:32 +01:00
case 45602 : // Ride Carpet
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. BasePoints = 0 ; // force seat 0, vehicle doesn't have the required seat flags for "no seat specified (-1)"
2012-06-03 15:12:32 +01:00
break ;
2012-05-30 08:01:02 +02:00
case 64745 : // Item - Death Knight T8 Tank 4P Bonus
case 64936 : // Item - Warrior T8 Protection 4P Bonus
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ 0 ]. BasePoints = 100 ; // 100% chance of procc'ing, not -10% (chance calculated in PrepareTriggersExecutedOnHit)
2012-05-30 08:01:02 +02:00
break ;
2012-06-08 22:25:33 +02:00
case 59414 : // Pulsing Shockwave Aura (Loken)
// this flag breaks movement, remove it
spellInfo -> AttributesEx &= ~ SPELL_ATTR1_CHANNELED_1 ;
break ;
2011-08-21 15:01:40 +02:00
case 61719 : // Easter Lay Noblegarden Egg Aura - Interrupt flags copied from aura which this aura is linked with
spellInfo -> AuraInterruptFlags = AURA_INTERRUPT_FLAG_HITBYSPELL | AURA_INTERRUPT_FLAG_TAKE_DAMAGE ;
break ;
2012-06-27 00:12:07 +03:00
case 70650 : // Death Knight T10 Tank 2P Bonus
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ 0 ]. ApplyAuraName = SPELL_AURA_ADD_PCT_MODIFIER ;
2011-08-21 15:01:40 +02:00
break ;
2012-11-19 22:13:07 +01:00
case 71838 : // Drain Life - Bryntroll Normal
case 71839 : // Drain Life - Bryntroll Heroic
spellInfo -> AttributesEx2 |= SPELL_ATTR2_CANT_CRIT ;
break ;
case 34471 : // The Beast Within
spellInfo -> AttributesEx5 |= SPELL_ATTR5_USABLE_WHILE_CONFUSED | SPELL_ATTR5_USABLE_WHILE_FEARED | SPELL_ATTR5_USABLE_WHILE_STUNNED ;
break ;
2011-08-21 15:01:40 +02:00
// ULDUAR SPELLS
//
2011-10-07 13:47:03 +02:00
case 62374 : // Pursued (Flame Leviathan)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // 50000yd
2011-10-07 13:47:03 +02:00
break ;
2011-08-21 15:01:40 +02:00
case 63342 : // Focused Eyebeam Summon Trigger (Kologarn)
spellInfo -> MaxAffectedTargets = 1 ;
break ;
case 62716 : // Growth of Nature (Freya)
case 65584 : // Growth of Nature (Freya)
case 64381 : // Strength of the Pack (Auriaya)
spellInfo -> AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS ;
break ;
case 63018 : // Searing Light (XT-002)
case 65121 : // Searing Light (25m) (XT-002)
case 63024 : // Gravity Bomb (XT-002)
case 64234 : // Gravity Bomb (25m) (XT-002)
spellInfo -> MaxAffectedTargets = 1 ;
break ;
case 62834 : // Boom (XT-002)
// This hack is here because we suspect our implementation of spell effect execution on targets
// is done in the wrong order. We suspect that EFFECT_0 needs to be applied on all targets,
// then EFFECT_1, etc - instead of applying each effect on target1, then target2, etc.
// The above situation causes the visual for this spell to be bugged, so we remove the instakill
// effect and implement a script hack for that.
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. Effect = 0 ;
2011-08-21 15:01:40 +02:00
break ;
case 64386 : // Terrifying Screech (Auriaya)
case 64389 : // Sentinel Blast (Auriaya)
case 64678 : // Sentinel Blast (Auriaya)
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 28 ); // 5 seconds, wrong DBC data?
2011-08-21 15:01:40 +02:00
break ;
case 64321 : // Potent Pheromones (Freya)
// spell should dispel area aura, but doesn't have the attribute
// may be db data bug, or blizz may keep reapplying area auras every update with checking immunity
// that will be clear if we get more spells with problem like this
spellInfo -> AttributesEx |= SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY ;
break ;
2012-05-30 08:01:02 +02:00
case 62301 : // Cosmic Smash (Algalon the Observer)
spellInfo -> MaxAffectedTargets = 1 ;
break ;
case 64598 : // Cosmic Smash (Algalon the Observer)
spellInfo -> MaxAffectedTargets = 3 ;
break ;
case 62293 : // Cosmic Smash (Algalon the Observer)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetB = SpellImplicitTargetInfo ( TARGET_DEST_CASTER );
2012-05-30 08:01:02 +02:00
break ;
case 62311 : // Cosmic Smash (Algalon the Observer)
case 64596 : // Cosmic Smash (Algalon the Observer)
2012-12-24 12:34:46 -05:00
spellInfo -> RangeEntry = sSpellRangeStore . LookupEntry ( 6 ); // 100yd
2012-05-30 08:01:02 +02:00
break ;
2011-08-21 15:01:40 +02:00
// ENDOF ULDUAR SPELLS
//
// TRIAL OF THE CRUSADER SPELLS
//
case 66258 : // Infernal Eruption (10N)
case 67901 : // Infernal Eruption (25N)
// increase duration from 15 to 18 seconds because caster is already
// unsummoned when spell missile hits the ground so nothing happen in result
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 85 );
2011-08-21 15:01:40 +02:00
break ;
// ENDOF TRIAL OF THE CRUSADER SPELLS
//
// ICECROWN CITADEL SPELLS
//
// THESE SPELLS ARE WORKING CORRECTLY EVEN WITHOUT THIS HACK
// THE ONLY REASON ITS HERE IS THAT CURRENT GRID SYSTEM
// DOES NOT ALLOW FAR OBJECT SELECTION (dist > 333)
case 70781 : // Light's Hammer Teleport
case 70856 : // Oratory of the Damned Teleport
case 70857 : // Rampart of Skulls Teleport
case 70858 : // Deathbringer's Rise Teleport
case 70859 : // Upper Spire Teleport
case 70860 : // Frozen Throne Teleport
case 70861 : // Sindragosa's Lair Teleport
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_DEST_DB );
2011-08-21 15:01:40 +02:00
break ;
case 69055 : // Saber Lash (Lord Marrowgar)
case 70814 : // Saber Lash (Lord Marrowgar)
2013-02-02 00:16:11 +01:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_8_YARDS ); // 8yd
2011-08-21 15:01:40 +02:00
break ;
case 69075 : // Bone Storm (Lord Marrowgar)
case 70834 : // Bone Storm (Lord Marrowgar)
case 70835 : // Bone Storm (Lord Marrowgar)
case 70836 : // Bone Storm (Lord Marrowgar)
case 72864 : // Death Plague (Rotting Frost Giant)
case 71160 : // Plague Stench (Stinky)
case 71161 : // Plague Stench (Stinky)
case 71123 : // Decimate (Stinky & Precious)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_100_YARDS ); // 100yd
2011-08-21 15:01:40 +02:00
break ;
2012-12-22 17:49:51 +01:00
case 71169 : // Shadow's Fate
spellInfo -> AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS ;
break ;
2012-05-30 08:01:02 +02:00
case 72378 : // Blood Nova (Deathbringer Saurfang)
case 73058 : // Blood Nova (Deathbringer Saurfang)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS );
spellInfo -> Effects [ EFFECT_1 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS );
2012-05-30 08:01:02 +02:00
break ;
case 72769 : // Scent of Blood (Deathbringer Saurfang)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS );
2012-05-30 08:01:02 +02:00
// no break
case 72771 : // Scent of Blood (Deathbringer Saurfang)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS );
2012-05-30 08:01:02 +02:00
break ;
2011-08-21 15:01:40 +02:00
case 72723 : // Resistant Skin (Deathbringer Saurfang adds)
// this spell initially granted Shadow damage immunity, however it was removed but the data was left in client
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_2 ]. Effect = 0 ;
2011-08-21 15:01:40 +02:00
break ;
case 70460 : // Coldflame Jets (Traps after Saurfang)
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 1 ); // 10 seconds
2011-08-21 15:01:40 +02:00
break ;
2012-05-30 08:01:02 +02:00
case 71412 : // Green Ooze Summon (Professor Putricide)
case 71415 : // Orange Ooze Summon (Professor Putricide)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_UNIT_TARGET_ANY );
2011-08-21 15:01:40 +02:00
break ;
2011-08-26 10:29:23 +02:00
case 71159 : // Awaken Plagued Zombies
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 21 );
2011-08-26 10:29:23 +02:00
break ;
2012-09-10 20:32:13 +02:00
case 70530 : // Volatile Ooze Beam Protection (Professor Putricide)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. Effect = SPELL_EFFECT_APPLY_AURA ; // for an unknown reason this was SPELL_EFFECT_APPLY_AREA_AURA_RAID
2012-09-10 20:32:13 +02:00
break ;
2011-08-21 15:01:40 +02:00
// THIS IS HERE BECAUSE COOLDOWN ON CREATURE PROCS IS NOT IMPLEMENTED
case 71604 : // Mutated Strength (Professor Putricide)
case 72673 : // Mutated Strength (Professor Putricide)
case 72674 : // Mutated Strength (Professor Putricide)
case 72675 : // Mutated Strength (Professor Putricide)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. Effect = 0 ;
2011-08-21 15:01:40 +02:00
break ;
case 72454 : // Mutated Plague (Professor Putricide)
case 72464 : // Mutated Plague (Professor Putricide)
case 72506 : // Mutated Plague (Professor Putricide)
case 72507 : // Mutated Plague (Professor Putricide)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // 50000yd
2011-08-21 15:01:40 +02:00
break ;
2011-09-25 13:29:17 +02:00
case 70911 : // Unbound Plague (Professor Putricide) (needs target selection script)
case 72854 : // Unbound Plague (Professor Putricide) (needs target selection script)
case 72855 : // Unbound Plague (Professor Putricide) (needs target selection script)
case 72856 : // Unbound Plague (Professor Putricide) (needs target selection script)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetB = SpellImplicitTargetInfo ( TARGET_UNIT_TARGET_ENEMY );
2011-08-21 15:01:40 +02:00
break ;
case 71518 : // Unholy Infusion Quest Credit (Professor Putricide)
case 72934 : // Blood Infusion Quest Credit (Blood-Queen Lana'thel)
case 72289 : // Frost Infusion Quest Credit (Sindragosa)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // another missing radius
2011-08-21 15:01:40 +02:00
break ;
case 71708 : // Empowered Flare (Blood Prince Council)
case 72785 : // Empowered Flare (Blood Prince Council)
case 72786 : // Empowered Flare (Blood Prince Council)
case 72787 : // Empowered Flare (Blood Prince Council)
spellInfo -> AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS ;
break ;
case 71266 : // Swarming Shadows
case 72890 : // Swarming Shadows
spellInfo -> AreaGroupId = 0 ; // originally, these require area 4522, which is... outside of Icecrown Citadel
break ;
case 70602 : // Corruption
2012-01-08 23:07:31 +00:00
case 48278 : // Paralyze
2011-08-21 15:01:40 +02:00
spellInfo -> AttributesEx3 |= SPELL_ATTR3_STACK_FOR_DIFF_CASTERS ;
break ;
case 70715 : // Column of Frost (visual marker)
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 32 ); // 6 seconds (missing)
2011-08-21 15:01:40 +02:00
break ;
case 71085 : // Mana Void (periodic aura)
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 9 ); // 30 seconds (missing)
2011-08-21 15:01:40 +02:00
break ;
2012-10-13 00:43:20 +02:00
case 72015 : // Frostbolt Volley (only heroic)
case 72016 : // Frostbolt Volley (only heroic)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_2 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_40_YARDS );
2012-10-13 00:43:20 +02:00
break ;
2011-09-25 13:29:17 +02:00
case 70936 : // Summon Suppressor (needs target selection script)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_UNIT_TARGET_ANY );
spellInfo -> Effects [ EFFECT_0 ]. TargetB = SpellImplicitTargetInfo ();
2011-08-21 15:01:40 +02:00
break ;
case 72706 : // Achievement Check (Valithria Dreamwalker)
case 71357 : // Order Whelp
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
2011-08-21 15:01:40 +02:00
break ;
case 70598 : // Sindragosa's Fury
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. TargetA = SpellImplicitTargetInfo ( TARGET_DEST_DEST );
2011-08-21 15:01:40 +02:00
break ;
case 69846 : // Frost Bomb
2012-12-24 12:34:46 -05:00
spellInfo -> Speed = 0.0f ; // This spell's summon happens instantly
2011-08-21 15:01:40 +02:00
break ;
2011-10-05 20:48:34 +02:00
case 71614 : // Ice Lock
spellInfo -> Mechanic = MECHANIC_STUN ;
break ;
case 72762 : // Defile
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 559 ); // 53 seconds
2011-10-05 20:48:34 +02:00
break ;
case 72743 : // Defile
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 22 ); // 45 seconds
2011-10-05 20:48:34 +02:00
break ;
case 72754 : // Defile
case 73708 : // Defile
case 73709 : // Defile
case 73710 : // Defile
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
spellInfo -> Effects [ EFFECT_1 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
2011-10-05 20:48:34 +02:00
break ;
case 69030 : // Val'kyr Target Search
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
spellInfo -> Effects [ EFFECT_1 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
2011-10-05 20:48:34 +02:00
break ;
case 69198 : // Raging Spirit Visual
2012-12-24 12:34:46 -05:00
spellInfo -> RangeEntry = sSpellRangeStore . LookupEntry ( 13 ); // 50000yd
2011-10-05 20:48:34 +02:00
break ;
case 73654 : // Harvest Souls
case 74295 : // Harvest Souls
case 74296 : // Harvest Souls
case 74297 : // Harvest Souls
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // 50000yd
spellInfo -> Effects [ EFFECT_1 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // 50000yd
spellInfo -> Effects [ EFFECT_2 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // 50000yd
2011-10-05 20:48:34 +02:00
break ;
case 73655 : // Harvest Soul
spellInfo -> AttributesEx3 |= SPELL_ATTR3_NO_DONE_BONUS ;
break ;
case 73540 : // Summon Shadow Trap
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 23 ); // 90 seconds
2011-10-05 20:48:34 +02:00
break ;
case 73530 : // Shadow Trap (visual)
2012-12-24 12:34:46 -05:00
spellInfo -> DurationEntry = sSpellDurationStore . LookupEntry ( 28 ); // 5 seconds
2011-10-05 20:48:34 +02:00
break ;
case 73529 : // Shadow Trap
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_10_YARDS ); // 10yd
2011-10-05 20:48:34 +02:00
break ;
case 74282 : // Shadow Trap (searcher)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_3_YARDS ); // 3yd
2011-10-05 20:48:34 +02:00
break ;
case 72595 : // Restore Soul
case 73650 : // Restore Soul
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
2011-10-05 20:48:34 +02:00
break ;
case 74086 : // Destroy Soul
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
2011-10-05 20:48:34 +02:00
break ;
case 74302 : // Summon Spirit Bomb
case 74342 : // Summon Spirit Bomb
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
2011-10-05 20:48:34 +02:00
spellInfo -> MaxAffectedTargets = 1 ;
break ;
case 74341 : // Summon Spirit Bomb
case 74343 : // Summon Spirit Bomb
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
2011-10-05 20:48:34 +02:00
spellInfo -> MaxAffectedTargets = 3 ;
break ;
case 73579 : // Summon Spirit Bomb
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_25_YARDS ); // 25yd
2011-10-05 20:48:34 +02:00
break ;
case 72350 : // Fury of Frostmourne
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // 50000yd
spellInfo -> Effects [ EFFECT_1 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // 50000yd
2011-10-05 20:48:34 +02:00
break ;
case 75127 : // Kill Frostmourne Players
case 72351 : // Fury of Frostmourne
2011-10-06 14:30:33 +02:00
case 72431 : // Jump (removes Fury of Frostmourne debuff)
2011-10-05 20:48:34 +02:00
case 72429 : // Mass Resurrection
case 73159 : // Play Movie
case 73582 : // Trigger Vile Spirit (Inside, Heroic)
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // 50000yd
2011-10-05 20:48:34 +02:00
break ;
case 72376 : // Raise Dead
spellInfo -> MaxAffectedTargets = 3 ;
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_50000_YARDS ); // 50000yd
2011-10-05 20:48:34 +02:00
break ;
case 71809 : // Jump
2012-12-24 12:34:46 -05:00
spellInfo -> RangeEntry = sSpellRangeStore . LookupEntry ( 3 ); // 20yd
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_25_YARDS ); // 25yd
2011-10-05 20:48:34 +02:00
break ;
2011-10-06 17:57:28 +02:00
case 72405 : // Broken Frostmourne
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_200_YARDS ); // 200yd
2012-10-06 22:47:52 +02:00
break ;
// ENDOF ICECROWN CITADEL SPELLS
//
// RUBY SANCTUM SPELLS
//
case 74769 : // Twilight Cutter
case 77844 : // Twilight Cutter
case 77845 : // Twilight Cutter
case 77846 : // Twilight Cutter
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. RadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_100_YARDS ); // 100yd
2011-10-06 17:57:28 +02:00
break ;
2012-10-06 22:47:52 +02:00
case 75509 : // Twilight Mending
spellInfo -> AttributesEx6 |= SPELL_ATTR6_CAN_TARGET_INVISIBLE ;
spellInfo -> AttributesEx2 |= SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS ;
break ;
2012-10-22 21:18:21 +02:00
case 75888 : // Awaken Flames
case 75889 : // Awaken Flames
spellInfo -> AttributesEx |= SPELL_ATTR1_CANT_TARGET_SELF ;
break ;
2012-10-06 22:47:52 +02:00
// ENDOF RUBY SANCTUM SPELLS
//
2012-01-06 01:19:07 +01:00
case 40055 : // Introspection
case 40165 : // Introspection
case 40166 : // Introspection
case 40167 : // Introspection
spellInfo -> Attributes |= SPELL_ATTR0_NEGATIVE_1 ;
2012-05-30 08:01:02 +02:00
break ;
case 2378 : // Minor Fortitude
2012-12-24 12:34:46 -05:00
spellInfo -> ManaCost = 0 ;
spellInfo -> ManaPerSecond = 0 ;
2012-05-30 08:01:02 +02:00
break ;
2012-10-02 22:13:40 +03:00
// OCULUS SPELLS
// The spells below are here, because their effect 1 is giving warning, because the triggered spell is not found in dbc and is missing from encounter sniff.
case 49462 : // Call Ruby Drake
case 49461 : // Call Amber Drake
case 49345 : // Call Emerald Drake
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_1 ]. Effect = 0 ;
2012-10-02 22:13:40 +03:00
break ;
2012-12-24 18:24:30 -05:00
// Halls Of Origination spells
// Temple Guardian Anhuur
case 76606 : // Disable Beacon Beams L
case 76608 : // Disable Beacon Beams R
// Little hack, Increase the radius so it can hit the Cave In Stalkers in the platform.
spellInfo -> Effects [ EFFECT_0 ]. MaxRadiusEntry = sSpellRadiusStore . LookupEntry ( EFFECT_RADIUS_45_YARDS );
break ;
2012-12-24 19:02:10 -05:00
case 75323 : // Reverberating Hymn
// Aura is refreshed at 3 seconds, and the tick should happen at the fourth.
spellInfo -> AttributesEx8 |= SPELL_ATTR8_DONT_RESET_PERIODIC_TIMER ;
break ;
2013-01-16 00:41:03 -03:30
case 24314 : // Threatening Gaze
spellInfo -> AuraInterruptFlags |= AURA_INTERRUPT_FLAG_CAST | AURA_INTERRUPT_FLAG_MOVE | AURA_INTERRUPT_FLAG_JUMP ;
2013-01-22 17:43:18 +01:00
break ;
2013-01-22 15:44:47 +01:00
case 5420 : // Tree of Life (Passive)
spellInfo -> Stances = 1 << ( FORM_TREE - 1 );
break ;
2011-08-21 15:01:40 +02:00
default :
break ;
2009-05-15 16:26:00 -05:00
}
2009-10-17 15:51:44 -07:00
2011-02-07 17:21:44 +01:00
switch ( spellInfo -> SpellFamilyName )
2009-05-15 16:26:00 -05:00
{
2011-05-31 23:10:58 +07:00
case SPELLFAMILY_PALADIN :
// Seals of the Pure should affect Seal of Righteousness
if ( spellInfo -> SpellIconID == 25 && spellInfo -> Attributes & SPELL_ATTR0_PASSIVE )
2012-12-24 12:34:46 -05:00
spellInfo -> Effects [ EFFECT_0 ]. SpellClassMask [ 1 ] |= 0x20000000 ;
2011-05-31 23:10:58 +07:00
break ;
2011-03-31 23:44:39 +02:00
case SPELLFAMILY_DEATHKNIGHT :
// Icy Touch - extend FamilyFlags (unused value) for Sigil of the Frozen Conscience to use
if ( spellInfo -> SpellIconID == 2721 && spellInfo -> SpellFamilyFlags [ 0 ] & 0x2 )
spellInfo -> SpellFamilyFlags [ 0 ] |= 0x40 ;
break ;
2009-05-15 16:26:00 -05:00
}
}
2009-10-17 15:51:44 -07:00
2011-06-28 23:48:59 +07:00
SummonPropertiesEntry * properties = const_cast < SummonPropertiesEntry *> ( sSummonPropertiesStore . LookupEntry ( 121 ));
2009-05-15 16:26:00 -05:00
properties -> Type = SUMMON_TYPE_TOTEM ;
2009-08-17 23:09:17 -05:00
properties = const_cast < SummonPropertiesEntry *> ( sSummonPropertiesStore . LookupEntry ( 647 )); // 52893
properties -> Type = SUMMON_TYPE_TOTEM ;
2012-12-27 20:22:22 +01:00
2012-12-24 12:34:46 -05:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded SpellInfo corrections in %u ms" , GetMSTimeDiffToNow ( oldMSTime ));
2011-08-03 08:18:24 +02:00
}