root/trunk/src/game/SpellEffects.cpp @ 79

Revision 79, 237.1 kB (checked in by yumileroy, 17 years ago)

[svn] * Minor code fixes
* Move account related functions from ObjectMgr? to AccountMgr? and drop duplicate functions - source mangos
* recognize the dummy spells 38637, 38638 and 38639 as negative - source mangos
* added new command ".reload all_locales". Now all locales_* tables can be reloaded - source mangos

Original author: KingPin?
Date: 2008-10-20 12:59:45-05:00

Line 
1/*
2 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
3 *
4 * Thanks to the original authors: MaNGOS <http://www.mangosproject.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "Common.h"
22#include "SharedDefines.h"
23#include "Database/DatabaseEnv.h"
24#include "WorldPacket.h"
25#include "WorldSession.h"
26#include "Opcodes.h"
27#include "Log.h"
28#include "UpdateMask.h"
29#include "World.h"
30#include "ObjectMgr.h"
31#include "SpellMgr.h"
32#include "Player.h"
33#include "SkillExtraItems.h"
34#include "Unit.h"
35#include "CreatureAI.h"
36#include "Spell.h"
37#include "DynamicObject.h"
38#include "SpellAuras.h"
39#include "Group.h"
40#include "UpdateData.h"
41#include "MapManager.h"
42#include "ObjectAccessor.h"
43#include "SharedDefines.h"
44#include "Pet.h"
45#include "GameObject.h"
46#include "GossipDef.h"
47#include "Creature.h"
48#include "Totem.h"
49#include "CreatureAI.h"
50#include "BattleGround.h"
51#include "BattleGroundEY.h"
52#include "BattleGroundWS.h"
53#include "OutdoorPvPMgr.h"
54#include "VMapFactory.h"
55#include "Language.h"
56#include "SocialMgr.h"
57#include "Util.h"
58#include "TemporarySummon.h"
59
60
61pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
62{
63    &Spell::EffectNULL,                                     //  0
64    &Spell::EffectInstaKill,                                //  1 SPELL_EFFECT_INSTAKILL
65    &Spell::EffectSchoolDMG,                                //  2 SPELL_EFFECT_SCHOOL_DAMAGE
66    &Spell::EffectDummy,                                    //  3 SPELL_EFFECT_DUMMY
67    &Spell::EffectUnused,                                   //  4 SPELL_EFFECT_PORTAL_TELEPORT          unused
68    &Spell::EffectTeleportUnits,                            //  5 SPELL_EFFECT_TELEPORT_UNITS
69    &Spell::EffectApplyAura,                                //  6 SPELL_EFFECT_APPLY_AURA
70    &Spell::EffectEnvirinmentalDMG,                         //  7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
71    &Spell::EffectPowerDrain,                               //  8 SPELL_EFFECT_POWER_DRAIN
72    &Spell::EffectHealthLeech,                              //  9 SPELL_EFFECT_HEALTH_LEECH
73    &Spell::EffectHeal,                                     // 10 SPELL_EFFECT_HEAL
74    &Spell::EffectUnused,                                   // 11 SPELL_EFFECT_BIND
75    &Spell::EffectNULL,                                     // 12 SPELL_EFFECT_PORTAL
76    &Spell::EffectUnused,                                   // 13 SPELL_EFFECT_RITUAL_BASE              unused
77    &Spell::EffectUnused,                                   // 14 SPELL_EFFECT_RITUAL_SPECIALIZE        unused
78    &Spell::EffectUnused,                                   // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL   unused
79    &Spell::EffectQuestComplete,                            // 16 SPELL_EFFECT_QUEST_COMPLETE
80    &Spell::EffectWeaponDmg,                                // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
81    &Spell::EffectResurrect,                                // 18 SPELL_EFFECT_RESURRECT
82    &Spell::EffectAddExtraAttacks,                          // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
83    &Spell::EffectUnused,                                   // 20 SPELL_EFFECT_DODGE                    one spell: Dodge
84    &Spell::EffectUnused,                                   // 21 SPELL_EFFECT_EVADE                    one spell: Evade (DND)
85    &Spell::EffectParry,                                    // 22 SPELL_EFFECT_PARRY
86    &Spell::EffectBlock,                                    // 23 SPELL_EFFECT_BLOCK                    one spell: Block
87    &Spell::EffectCreateItem,                               // 24 SPELL_EFFECT_CREATE_ITEM
88    &Spell::EffectUnused,                                   // 25 SPELL_EFFECT_WEAPON
89    &Spell::EffectUnused,                                   // 26 SPELL_EFFECT_DEFENSE                  one spell: Defense
90    &Spell::EffectPersistentAA,                             // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
91    &Spell::EffectSummonType,                               // 28 SPELL_EFFECT_SUMMON
92    &Spell::EffectMomentMove,                               // 29 SPELL_EFFECT_LEAP
93    &Spell::EffectEnergize,                                 // 30 SPELL_EFFECT_ENERGIZE
94    &Spell::EffectWeaponDmg,                                // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
95    &Spell::EffectTriggerMissileSpell,                      // 32 SPELL_EFFECT_TRIGGER_MISSILE
96    &Spell::EffectOpenLock,                                 // 33 SPELL_EFFECT_OPEN_LOCK
97    &Spell::EffectSummonChangeItem,                         // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
98    &Spell::EffectApplyAreaAura,                            // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
99    &Spell::EffectLearnSpell,                               // 36 SPELL_EFFECT_LEARN_SPELL
100    &Spell::EffectUnused,                                   // 37 SPELL_EFFECT_SPELL_DEFENSE            one spell: SPELLDEFENSE (DND)
101    &Spell::EffectDispel,                                   // 38 SPELL_EFFECT_DISPEL
102    &Spell::EffectUnused,                                   // 39 SPELL_EFFECT_LANGUAGE
103    &Spell::EffectDualWield,                                // 40 SPELL_EFFECT_DUAL_WIELD
104    &Spell::EffectSummonWild,                               // 41 SPELL_EFFECT_SUMMON_WILD
105    &Spell::EffectSummonGuardian,                           // 42 SPELL_EFFECT_SUMMON_GUARDIAN
106    &Spell::EffectTeleUnitsFaceCaster,                      // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
107    &Spell::EffectLearnSkill,                               // 44 SPELL_EFFECT_SKILL_STEP
108    &Spell::EffectAddHonor,                                 // 45 SPELL_EFFECT_ADD_HONOR                honor/pvp related
109    &Spell::EffectNULL,                                     // 46 SPELL_EFFECT_SPAWN                    we must spawn pet there
110    &Spell::EffectTradeSkill,                               // 47 SPELL_EFFECT_TRADE_SKILL
111    &Spell::EffectUnused,                                   // 48 SPELL_EFFECT_STEALTH                  one spell: Base Stealth
112    &Spell::EffectUnused,                                   // 49 SPELL_EFFECT_DETECT                   one spell: Detect
113    &Spell::EffectTransmitted,                              // 50 SPELL_EFFECT_TRANS_DOOR
114    &Spell::EffectUnused,                                   // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT       unused
115    &Spell::EffectUnused,                                   // 52 SPELL_EFFECT_GUARANTEE_HIT            one spell: zzOLDCritical Shot
116    &Spell::EffectEnchantItemPerm,                          // 53 SPELL_EFFECT_ENCHANT_ITEM
117    &Spell::EffectEnchantItemTmp,                           // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
118    &Spell::EffectTameCreature,                             // 55 SPELL_EFFECT_TAMECREATURE
119    &Spell::EffectSummonPet,                                // 56 SPELL_EFFECT_SUMMON_PET
120    &Spell::EffectLearnPetSpell,                            // 57 SPELL_EFFECT_LEARN_PET_SPELL
121    &Spell::EffectWeaponDmg,                                // 58 SPELL_EFFECT_WEAPON_DAMAGE
122    &Spell::EffectOpenSecretSafe,                           // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
123    &Spell::EffectProficiency,                              // 60 SPELL_EFFECT_PROFICIENCY
124    &Spell::EffectSendEvent,                                // 61 SPELL_EFFECT_SEND_EVENT
125    &Spell::EffectPowerBurn,                                // 62 SPELL_EFFECT_POWER_BURN
126    &Spell::EffectThreat,                                   // 63 SPELL_EFFECT_THREAT
127    &Spell::EffectTriggerSpell,                             // 64 SPELL_EFFECT_TRIGGER_SPELL
128    &Spell::EffectUnused,                                   // 65 SPELL_EFFECT_HEALTH_FUNNEL            unused
129    &Spell::EffectUnused,                                   // 66 SPELL_EFFECT_POWER_FUNNEL             unused
130    &Spell::EffectHealMaxHealth,                            // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
131    &Spell::EffectInterruptCast,                            // 68 SPELL_EFFECT_INTERRUPT_CAST
132    &Spell::EffectDistract,                                 // 69 SPELL_EFFECT_DISTRACT
133    &Spell::EffectPull,                                     // 70 SPELL_EFFECT_PULL                     one spell: Distract Move
134    &Spell::EffectPickPocket,                               // 71 SPELL_EFFECT_PICKPOCKET
135    &Spell::EffectAddFarsight,                              // 72 SPELL_EFFECT_ADD_FARSIGHT
136    &Spell::EffectSummonGuardian,                           // 73 SPELL_EFFECT_SUMMON_POSSESSED
137    &Spell::EffectSummonTotem,                              // 74 SPELL_EFFECT_SUMMON_TOTEM
138    &Spell::EffectHealMechanical,                           // 75 SPELL_EFFECT_HEAL_MECHANICAL          one spell: Mechanical Patch Kit
139    &Spell::EffectSummonObjectWild,                         // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
140    &Spell::EffectScriptEffect,                             // 77 SPELL_EFFECT_SCRIPT_EFFECT
141    &Spell::EffectUnused,                                   // 78 SPELL_EFFECT_ATTACK
142    &Spell::EffectSanctuary,                                // 79 SPELL_EFFECT_SANCTUARY
143    &Spell::EffectAddComboPoints,                           // 80 SPELL_EFFECT_ADD_COMBO_POINTS
144    &Spell::EffectUnused,                                   // 81 SPELL_EFFECT_CREATE_HOUSE             one spell: Create House (TEST)
145    &Spell::EffectNULL,                                     // 82 SPELL_EFFECT_BIND_SIGHT
146    &Spell::EffectDuel,                                     // 83 SPELL_EFFECT_DUEL
147    &Spell::EffectStuck,                                    // 84 SPELL_EFFECT_STUCK
148    &Spell::EffectSummonPlayer,                             // 85 SPELL_EFFECT_SUMMON_PLAYER
149    &Spell::EffectActivateObject,                           // 86 SPELL_EFFECT_ACTIVATE_OBJECT
150    &Spell::EffectSummonTotem,                              // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1
151    &Spell::EffectSummonTotem,                              // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2
152    &Spell::EffectSummonTotem,                              // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3
153    &Spell::EffectSummonTotem,                              // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4
154    &Spell::EffectUnused,                                   // 91 SPELL_EFFECT_THREAT_ALL               one spell: zzOLDBrainwash
155    &Spell::EffectEnchantHeldItem,                          // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
156    &Spell::EffectUnused,                                   // 93 SPELL_EFFECT_SUMMON_PHANTASM
157    &Spell::EffectSelfResurrect,                            // 94 SPELL_EFFECT_SELF_RESURRECT
158    &Spell::EffectSkinning,                                 // 95 SPELL_EFFECT_SKINNING
159    &Spell::EffectCharge,                                   // 96 SPELL_EFFECT_CHARGE
160    &Spell::EffectSummonCritter,                            // 97 SPELL_EFFECT_SUMMON_CRITTER
161    &Spell::EffectKnockBack,                                // 98 SPELL_EFFECT_KNOCK_BACK
162    &Spell::EffectDisEnchant,                               // 99 SPELL_EFFECT_DISENCHANT
163    &Spell::EffectInebriate,                                //100 SPELL_EFFECT_INEBRIATE
164    &Spell::EffectFeedPet,                                  //101 SPELL_EFFECT_FEED_PET
165    &Spell::EffectDismissPet,                               //102 SPELL_EFFECT_DISMISS_PET
166    &Spell::EffectReputation,                               //103 SPELL_EFFECT_REPUTATION
167    &Spell::EffectSummonObject,                             //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
168    &Spell::EffectSummonObject,                             //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
169    &Spell::EffectSummonObject,                             //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
170    &Spell::EffectSummonObject,                             //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
171    &Spell::EffectDispelMechanic,                           //108 SPELL_EFFECT_DISPEL_MECHANIC
172    &Spell::EffectSummonDeadPet,                            //109 SPELL_EFFECT_SUMMON_DEAD_PET
173    &Spell::EffectDestroyAllTotems,                         //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
174    &Spell::EffectDurabilityDamage,                         //111 SPELL_EFFECT_DURABILITY_DAMAGE
175    &Spell::EffectSummonDemon,                              //112 SPELL_EFFECT_SUMMON_DEMON
176    &Spell::EffectResurrectNew,                             //113 SPELL_EFFECT_RESURRECT_NEW
177    &Spell::EffectTaunt,                                    //114 SPELL_EFFECT_ATTACK_ME
178    &Spell::EffectDurabilityDamagePCT,                      //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
179    &Spell::EffectSkinPlayerCorpse,                         //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE       one spell: Remove Insignia, bg usage, required special corpse flags...
180    &Spell::EffectSpiritHeal,                               //117 SPELL_EFFECT_SPIRIT_HEAL              one spell: Spirit Heal
181    &Spell::EffectSkill,                                    //118 SPELL_EFFECT_SKILL                    professions and more
182    &Spell::EffectApplyAreaAura,                            //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
183    &Spell::EffectUnused,                                   //120 SPELL_EFFECT_TELEPORT_GRAVEYARD       one spell: Graveyard Teleport Test
184    &Spell::EffectWeaponDmg,                                //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
185    &Spell::EffectUnused,                                   //122 SPELL_EFFECT_122                      unused
186    &Spell::EffectSendTaxi,                                 //123 SPELL_EFFECT_SEND_TAXI                taxi/flight related (misc value is taxi path id)
187    &Spell::EffectPlayerPull,                               //124 SPELL_EFFECT_PLAYER_PULL              opposite of knockback effect (pulls player twoard caster)
188    &Spell::EffectModifyThreatPercent,                      //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
189    &Spell::EffectStealBeneficialBuff,                      //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF    spell steal effect?
190    &Spell::EffectProspecting,                              //127 SPELL_EFFECT_PROSPECTING              Prospecting spell
191    &Spell::EffectApplyAreaAura,                            //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
192    &Spell::EffectApplyAreaAura,                            //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
193    &Spell::EffectNULL,                                     //130 SPELL_EFFECT_REDIRECT_THREAT
194    &Spell::EffectUnused,                                   //131 SPELL_EFFECT_131                      used in some test spells
195    &Spell::EffectNULL,                                     //132 SPELL_EFFECT_PLAY_MUSIC               sound id in misc value
196    &Spell::EffectUnlearnSpecialization,                    //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION   unlearn profession specialization
197    &Spell::EffectKillCredit,                               //134 SPELL_EFFECT_KILL_CREDIT              misc value is creature entry
198    &Spell::EffectNULL,                                     //135 SPELL_EFFECT_CALL_PET
199    &Spell::EffectHealPct,                                  //136 SPELL_EFFECT_HEAL_PCT
200    &Spell::EffectEnergisePct,                              //137 SPELL_EFFECT_ENERGIZE_PCT
201    &Spell::EffectNULL,                                     //138 SPELL_EFFECT_138                      Leap
202    &Spell::EffectUnused,                                   //139 SPELL_EFFECT_139                      unused
203    &Spell::EffectForceCast,                                //140 SPELL_EFFECT_FORCE_CAST
204    &Spell::EffectNULL,                                     //141 SPELL_EFFECT_141                      damage and reduce speed?
205    &Spell::EffectTriggerSpellWithValue,                    //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
206    &Spell::EffectApplyAreaAura,                            //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
207    &Spell::EffectNULL,                                     //144 SPELL_EFFECT_144                      Spectral Blast
208    &Spell::EffectNULL,                                     //145 SPELL_EFFECT_145                      Black Hole Effect
209    &Spell::EffectUnused,                                   //146 SPELL_EFFECT_146                      unused
210    &Spell::EffectQuestFail,                                //147 SPELL_EFFECT_QUEST_FAIL               quest fail
211    &Spell::EffectUnused,                                   //148 SPELL_EFFECT_148                      unused
212    &Spell::EffectNULL,                                     //149 SPELL_EFFECT_149                      swoop
213    &Spell::EffectUnused,                                   //150 SPELL_EFFECT_150                      unused
214    &Spell::EffectTriggerRitualOfSummoning,                 //151 SPELL_EFFECT_TRIGGER_SPELL_2
215    &Spell::EffectNULL,                                     //152 SPELL_EFFECT_152                      summon Refer-a-Friend
216    &Spell::EffectNULL,                                     //153 SPELL_EFFECT_CREATE_PET               misc value is creature entry
217};
218
219void Spell::EffectNULL(uint32 /*i*/)
220{
221    sLog.outDebug("WORLD: Spell Effect DUMMY");
222}
223
224void Spell::EffectUnused(uint32 /*i*/)
225{
226    // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN TRINITY
227}
228
229void Spell::EffectResurrectNew(uint32 i)
230{
231    if(!unitTarget || unitTarget->isAlive())
232        return;
233
234    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
235        return;
236
237    if(!unitTarget->IsInWorld())
238        return;
239
240    Player* pTarget = ((Player*)unitTarget);
241
242    if(pTarget->isRessurectRequested())       // already have one active request
243        return;
244
245    uint32 health = damage;
246    uint32 mana = m_spellInfo->EffectMiscValue[i];
247    pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
248    SendResurrectRequest(pTarget);
249}
250
251void Spell::EffectInstaKill(uint32 /*i*/)
252{
253    if( !unitTarget || !unitTarget->isAlive() )
254        return;
255
256    // Demonic Sacrifice
257    if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
258    {
259        uint32 entry = unitTarget->GetEntry();
260        uint32 spellID;
261        switch(entry)
262        {
263            case   416: spellID=18789; break;               //imp
264            case   417: spellID=18792; break;               //fellhunter
265            case  1860: spellID=18790; break;               //void
266            case  1863: spellID=18791; break;               //succubus
267            case 17252: spellID=35701; break;               //fellguard
268            default:
269                sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
270                return;
271        }
272
273        m_caster->CastSpell(m_caster,spellID,true);
274    }
275
276    if(m_caster==unitTarget)                                // prevent interrupt message
277        finish();
278
279    uint32 health = unitTarget->GetHealth();
280    m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
281}
282
283void Spell::EffectEnvirinmentalDMG(uint32 i)
284{
285    uint32 absorb = 0;
286    uint32 resist = 0;
287
288    // Note: this hack with damage replace required until GO casting not implemented
289    // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
290    // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
291    damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i];
292
293    m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
294
295    m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
296    if(m_caster->GetTypeId() == TYPEID_PLAYER)
297        ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage);
298}
299
300void Spell::EffectSchoolDMG(uint32 effect_idx)
301{
302    if( unitTarget && unitTarget->isAlive())
303    {
304        switch(m_spellInfo->SpellFamilyName)
305        {
306            case SPELLFAMILY_GENERIC:
307            {
308                //Gore
309                if(m_spellInfo->SpellIconID == 2269 )
310                {
311                    damage+= rand()%2 ? damage : 0;
312                }
313
314                switch(m_spellInfo->Id)                     // better way to check unknown
315                {
316                    // Meteor like spells (divided damage to targets)
317                    case 24340: case 26558: case 28884:     // Meteor
318                    case 36837: case 38903: case 41276:     // Meteor
319                    case 26789:                             // Shard of the Fallen Star
320                    case 31436:                             // Malevolent Cleave
321                    case 35181:                             // Dive Bomb
322                    case 40810: case 43267: case 43268:     // Saber Lash
323                    case 42384:                             // Brutal Swipe
324                    case 45150:                             // Meteor Slash
325                    {
326                        uint32 count = 0;
327                        for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
328                            if(ihit->effectMask & (1<<effect_idx))
329                                ++count;
330
331                        damage /= count;                    // divide to all targets
332                        break;
333                    }
334                    // percent from health with min
335                    case 25599:                             // Thundercrash
336                    {
337                        damage = unitTarget->GetHealth() / 2;
338                        if(damage < 200)
339                            damage = 200;
340                        break;
341                    }
342                    // must only affect demons
343                    case 45072:
344                    {
345                        if(unitTarget->GetCreatureType() != CREATURE_TYPE_DEMON)
346                            return;
347                        break;
348                    }
349                }
350                break;
351            }
352
353            case SPELLFAMILY_MAGE:
354            {
355                // Arcane Blast
356                if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
357                {
358                    m_caster->CastSpell(m_caster,36032,true);
359                }
360                break;
361            }
362            case SPELLFAMILY_WARRIOR:
363            {
364                // Bloodthirst
365                if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
366                {
367                    damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
368                }
369                // Shield Slam
370                else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
371                    damage += int32(m_caster->GetShieldBlockValue());
372                // Victory Rush
373                else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
374                {
375                    damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
376                    m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
377                }
378                break;
379            }
380            case SPELLFAMILY_WARLOCK:
381            {
382                // Incinerate Rank 1 & 2
383                if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
384                {
385                    // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
386                    if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
387                        damage += int32(damage*0.25);
388                }
389                break;
390            }
391            case SPELLFAMILY_DRUID:
392            {
393                // Ferocious Bite
394                if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587)
395                {
396                    // converts each extra point of energy into ($f1+$AP/630) additional damage
397                    float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx];
398                    damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
399                    m_caster->SetPower(POWER_ENERGY,0);
400                }
401                // Rake
402                else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
403                {
404                    damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
405                }
406                // Swipe
407                else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
408                {
409                    damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
410                }
411                // Starfire
412                else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL )
413                {
414                    Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
415                    for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
416                    {
417                        // Starfire Bonus (caster)
418                        switch((*i)->GetModifier()->m_miscvalue)
419                        {
420                            case 5481:                      // Nordrassil Regalia - bonus
421                            {
422                                Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
423                                for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr)
424                                {
425                                    // Moonfire or Insect Swarm (target debuff from any casters)
426                                    if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL )
427                                    {
428                                        int32 mod = (*i)->GetModifier()->m_amount;
429                                        damage += damage*mod/100;
430                                        break;
431                                    }
432                                }
433                                break;
434                            }
435                            case 5148:                      //Improved Starfire - Ivory Idol of the Moongoddes Aura
436                            {
437                                damage += (*i)->GetModifier()->m_amount;
438                                break;
439                            }
440                        }
441                    }
442                }
443                //Mangle Bonus for the initial damage of Lacerate and Rake
444                if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
445                    (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
446                {
447                    Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
448                    for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
449                        if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
450                        {
451                            damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
452                            break;
453                        }
454                }
455                break;
456            }
457            case SPELLFAMILY_ROGUE:
458            {
459                // Envenom
460                if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
461                {
462                    // consume from stack dozes not more that have combo-points
463                    if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
464                    {
465                        // count consumed deadly poison doses at target
466                        uint32 doses = 0;
467
468                        // remove consumed poison doses
469                        Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
470                        for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;)
471                        {
472                            // Deadly poison (only attacker applied)
473                            if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) &&
474                                (*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() )
475                            {
476                                --combo;
477                                ++doses;
478
479                                unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex());
480
481                                itr = auras.begin();
482                            }
483                            else
484                                ++itr;
485                        }
486
487                        damage *= doses;
488                        damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
489
490                        // Eviscerate and Envenom Bonus Damage (item set effect)
491                        if(m_caster->GetDummyAura(37169))
492                            damage += ((Player*)m_caster)->GetComboPoints()*40;
493                    }
494                }
495                // Eviscerate
496                else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
497                {
498                    if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
499                    {
500                        damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f);
501
502                        // Eviscerate and Envenom Bonus Damage (item set effect)
503                        if(m_caster->GetDummyAura(37169))
504                            damage += combo*40;
505                    }
506                }
507                break;
508            }
509            case SPELLFAMILY_HUNTER:
510            {
511                // Mongoose Bite
512                if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342)
513                {
514                    damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2);
515                }
516                // Arcane Shot
517                else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
518                {
519                    damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15);
520                }
521                // Steady Shot
522                else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
523                {
524                    int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
525                    damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
526                }
527                //Explosive Trap Effect
528                else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
529                {
530                    damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1);
531                }
532                break;
533            }
534            case SPELLFAMILY_PALADIN:
535            {
536                //Judgement of Vengeance
537                if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
538                {
539                    uint32 stacks = 0;
540                    Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
541                    for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
542                        if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
543                            ++stacks;
544                    if(!stacks)
545                        //No damage if the target isn't affected by this
546                        damage = -1;
547                    else
548                        damage *= stacks;
549                }
550                break;
551            }
552        }
553
554        if(damage >= 0)
555        {
556            uint32 finalDamage;
557            if(m_originalCaster)                            // m_caster only passive source of cast
558                finalDamage = m_originalCaster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
559            else
560                finalDamage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
561
562            // post effects
563            switch(m_spellInfo->SpellFamilyName)
564            {
565                case SPELLFAMILY_WARRIOR:
566                {
567                    // Bloodthirst
568                    if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
569                    {
570                        uint32 BTAura = 0;
571                        switch(m_spellInfo->Id)
572                        {
573                            case 23881: BTAura = 23885; break;
574                            case 23892: BTAura = 23886; break;
575                            case 23893: BTAura = 23887; break;
576                            case 23894: BTAura = 23888; break;
577                            case 25251: BTAura = 25252; break;
578                            case 30335: BTAura = 30339; break;
579                            default:
580                                sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id);
581                                break;
582                        }
583
584                        if (BTAura)
585                            m_caster->CastSpell(m_caster,BTAura,true);
586                    }
587                    break;
588                }
589                case SPELLFAMILY_PRIEST:
590                {
591                    // Shadow Word: Death
592                    if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL) && unitTarget->isAlive())
593                        // deals damage equal to damage done to caster if victim is not killed
594                        m_caster->SpellNonMeleeDamageLog( m_caster, m_spellInfo->Id, finalDamage, m_IsTriggeredSpell, false);
595
596                    break;
597                }
598                case SPELLFAMILY_PALADIN:
599                {
600                    // Judgement of Blood
601                    if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000800000000LL) && m_spellInfo->SpellIconID==153)
602                    {
603                        int32 damagePoint  = finalDamage * 33 / 100;
604                        m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true);
605                    }
606                    break;
607                }
608            }
609        }
610    }
611}
612
613void Spell::EffectDummy(uint32 i)
614{
615    if(!unitTarget && !gameObjTarget && !itemTarget)
616        return;
617
618    // selection by spell family
619    switch(m_spellInfo->SpellFamilyName)
620    {
621        case SPELLFAMILY_GENERIC:
622            // Gnomish Poultryizer trinket
623            switch(m_spellInfo->Id )
624            {
625                case 8063:                                  // Deviate Fish
626                {
627                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
628                        return;
629
630                    uint32 spell_id = 0;
631                    switch(urand(1,5))
632                    {
633                        case 1: spell_id = 8064; break;     // Sleepy
634                        case 2: spell_id = 8065; break;     // Invigorate
635                        case 3: spell_id = 8066; break;     // Shrink
636                        case 4: spell_id = 8067; break;     // Party Time!
637                        case 5: spell_id = 8068; break;     // Healthy Spirit
638                    }
639                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
640                    return;
641                }
642                case 8213:                                  // Savory Deviate Delight
643                {
644                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
645                        return;
646
647                    uint32 spell_id = 0;
648                    switch(urand(1,2))
649                    {
650                        // Flip Out - ninja
651                        case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
652                        // Yaaarrrr - pirate
653                        case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
654                    }
655                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
656                    return;
657                }
658                case 8593:                                  // Symbol of life (restore creature to life)
659                case 31225:                                 // Shimmering Vessel (restore creature to life)
660                {
661                    if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
662                        return;
663                    ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
664                    return;
665                }
666                case 12162:                                 // Deep wounds
667                case 12850:                                 // (now good common check for this spells)
668                case 12868:
669                {
670                    if(!unitTarget)
671                        return;
672
673                    float damage;
674                    // DW should benefit of attack power, damage percent mods etc.
675                    // TODO: check if using offhand damage is correct and if it should be divided by 2
676                    if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
677                        damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
678                    else
679                        damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
680
681                    switch (m_spellInfo->Id)
682                    {
683                        case 12850: damage *= 0.2f; break;
684                        case 12162: damage *= 0.4f; break;
685                        case 12868: damage *= 0.6f; break;
686                        default:
687                            sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
688                            return;
689                    };
690
691                    int32 deepWoundsDotBasePoints0 = int32(damage / 4);
692                    m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
693                    return;
694                }
695                case 12975:                                 //Last Stand
696                {
697                    int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
698                    m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
699                    return;
700                }
701                case 13120:                                 // net-o-matic
702                {
703                    if(!unitTarget)
704                        return;
705
706                    uint32 spell_id = 0;
707
708                    uint32 roll = urand(0, 99);
709
710                    if(roll < 2)                            // 2% for 30 sec self root (off-like chance unknown)
711                        spell_id = 16566;
712                    else if(roll < 4)                       // 2% for 20 sec root, charge to target (off-like chance unknown)
713                        spell_id = 13119;
714                    else                                    // normal root
715                        spell_id = 13099;
716
717                    m_caster->CastSpell(unitTarget,spell_id,true,NULL);
718                    return;
719                }
720                case 13567:                                 // Dummy Trigger
721                {
722                    // can be used for different aura triggreing, so select by aura
723                    if(!m_triggeredByAuraSpell || !unitTarget)
724                        return;
725
726                    switch(m_triggeredByAuraSpell->Id)
727                    {
728                        case 26467:                         // Persistent Shield
729                            m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
730                            break;
731                        default:
732                            sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
733                            break;
734                    }
735                    return;
736                }
737                case 14185:                                 // Preparation Rogue
738                {
739                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
740                        return;
741
742                    //immediately finishes the cooldown on certain Rogue abilities
743                    const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
744                    for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
745                    {
746                        uint32 classspell = itr->first;
747                        SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
748
749                        if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL))
750                        {
751                            ((Player*)m_caster)->RemoveSpellCooldown(classspell);
752
753                            WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
754                            data << uint32(classspell);
755                            data << uint64(m_caster->GetGUID());
756                            ((Player*)m_caster)->GetSession()->SendPacket(&data);
757                        }
758                    }
759                    return;
760                }
761                case 15998:                                 // Capture Worg Pup
762                case 29435:                                 // Capture Female Kaliri Hatchling
763                {
764                    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
765                        return;
766
767                    Creature* creatureTarget = (Creature*)unitTarget;
768                    creatureTarget->setDeathState(JUST_DIED);
769                    creatureTarget->RemoveCorpse();
770                    creatureTarget->SetHealth(0);           // just for nice GM-mode view
771                    return;
772                }
773                case 16589:                                 // Noggenfogger Elixir
774                {
775                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
776                        return;
777
778                    uint32 spell_id = 0;
779                    switch(urand(1,3))
780                    {
781                        case 1: spell_id = 16595; break;
782                        case 2: spell_id = 16593; break;
783                        default:spell_id = 16591; break;
784                    }
785
786                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
787                    return;
788                }
789                case 17251:                                 // Spirit Healer Res
790                {
791                    if(!unitTarget || !m_originalCaster)
792                        return;
793
794                    if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
795                    {
796                        WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
797                        data << unitTarget->GetGUID();
798                        ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
799                    }
800                    return;
801                }
802                case 17271:                                 // Test Fetid Skull
803                {
804                    if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
805                        return;
806
807                    uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
808
809                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
810                    return;
811                }
812                case 20577:                                 // Cannibalize
813                    if (unitTarget)
814                        m_caster->CastSpell(m_caster,20578,false,NULL);
815                    return;
816                case 23019:                                 // Crystal Prison Dummy DND
817                {
818                    if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
819                        return;
820
821                    Creature* creatureTarget = (Creature*)unitTarget;
822                    if(creatureTarget->isPet())
823                        return;
824
825                    creatureTarget->setDeathState(JUST_DIED);
826                    creatureTarget->RemoveCorpse();
827                    creatureTarget->SetHealth(0);                   // just for nice GM-mode view
828
829                    GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime()-time(NULL));
830                    sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019\n");
831                    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
832                    data << uint64(Crystal_Prison->GetGUID());
833                    m_caster->SendMessageToSet(&data,true);
834
835                    return;
836                }
837                case 23074:                                 // Arc. Dragonling
838                    if (!m_CastItem) return;
839                    m_caster->CastSpell(m_caster,19804,true,m_CastItem);
840                    return;
841                case 23075:                                 // Mithril Mechanical Dragonling
842                    if (!m_CastItem) return;
843                    m_caster->CastSpell(m_caster,12749,true,m_CastItem);
844                    return;
845                case 23076:                                 // Mechanical Dragonling
846                    if (!m_CastItem) return;
847                    m_caster->CastSpell(m_caster,4073,true,m_CastItem);
848                    return;
849                case 23133:                                 // Gnomish Battle Chicken
850                    if (!m_CastItem) return;
851                    m_caster->CastSpell(m_caster,13166,true,m_CastItem);
852                    return;
853                case 23448:                                 // Ultrasafe Transporter: Gadgetzan - backfires
854                {
855                    int32 r = irand(0, 119);
856                    if ( r < 20 )                           // 1/6 polymorph
857                        m_caster->CastSpell(m_caster,23444,true);
858                    else if ( r < 100 )                     // 4/6 evil twin
859                        m_caster->CastSpell(m_caster,23445,true);
860                    else                                    // 1/6 miss the target
861                        m_caster->CastSpell(m_caster,36902,true);
862                    return;
863                }
864                case 23453:                                 // Ultrasafe Transporter: Gadgetzan
865                    if ( roll_chance_i(50) )                // success
866                        m_caster->CastSpell(m_caster,23441,true);
867                    else                                    // failure
868                        m_caster->CastSpell(m_caster,23446,true);
869                    return;
870                case 23645:                                 // Hourglass Sand
871                    m_caster->RemoveAurasDueToSpell(23170);
872                    return;
873                case 23725:                                 // Gift of Life (warrior bwl trinket)
874                    m_caster->CastSpell(m_caster,23782,true);
875                    m_caster->CastSpell(m_caster,23783,true);
876                    return;
877                case 25860:                                 // Reindeer Transformation
878                {
879                    if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
880                        return;
881
882                    float flyspeed = m_caster->GetSpeedRate(MOVE_FLY);
883                    float speed = m_caster->GetSpeedRate(MOVE_RUN);
884
885                    m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
886
887                    //5 different spells used depending on mounted speed and if mount can fly or not
888                    if (flyspeed >= 4.1f)
889                        m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
890                    else if (flyspeed >= 3.8f)
891                        m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
892                    else if (flyspeed >= 1.6f)
893                        m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
894                    else if (speed >= 2.0f)
895                        m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
896                    else
897                        m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
898
899                    return;
900                }
901                //case 26074:                               // Holiday Cheer
902                //    return; -- implemented at client side
903                case 28006:                                 // Arcane Cloaking
904                {
905                    if( unitTarget->GetTypeId() == TYPEID_PLAYER )
906                        m_caster->CastSpell(unitTarget,29294,true);
907                    return;
908                }
909                case 28730:                                 // Arcane Torrent (Mana)
910                {
911                    int32 count = 0;
912                    Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
913                    for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
914                        if ((*i)->GetId() == 28734)
915                            ++count;
916                    if (count)
917                    {
918                        m_caster->RemoveAurasDueToSpell(28734);
919                        int32 bp = damage * count;
920                        m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
921                    }
922                    return;
923                }
924                case 29200:                                 // Purify Helboar Meat
925                {
926                    if( m_caster->GetTypeId() != TYPEID_PLAYER )
927                        return;
928
929                    uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
930
931                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
932                    return;
933                }
934                case 29858:                                 // Soulshatter
935                    if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
936                        m_caster->CastSpell(unitTarget,32835,true);
937                    return;
938                case 30458:                                 // Nigh Invulnerability
939                    if (!m_CastItem) return;
940                    if(roll_chance_i(86))                   // success
941                        m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
942                    else                                    // backfire in 14% casts
943                        m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
944                    return;
945                case 30507:                                 // Poultryizer
946                    if (!m_CastItem) return;
947                    if(roll_chance_i(80))                   // success
948                        m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
949                    else                                    // backfire 20%
950                        m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
951                    return;
952                case 33060:                                         // Make a Wish
953                {
954                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
955                        return;
956
957                    uint32 spell_id = 0;
958
959                    switch(urand(1,5))
960                    {
961                        case 1: spell_id = 33053; break;
962                        case 2: spell_id = 33057; break;
963                        case 3: spell_id = 33059; break;
964                        case 4: spell_id = 33062; break;
965                        case 5: spell_id = 33064; break;
966                    }
967
968                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
969                    return;
970                }
971                case 35745:
972                {
973                    uint32 spell_id;
974                    switch(m_caster->GetAreaId())
975                    {
976                        case 3900: spell_id = 35743; break;
977                        case 3742: spell_id = 35744; break;
978                        default: return;
979                    }
980
981                    m_caster->CastSpell(m_caster,spell_id,true);
982                    return;
983                }
984                case 37674:                                 // Chaos Blast
985                    if(unitTarget)
986                        m_caster->CastSpell(unitTarget,37675,true);
987                    return;
988                case 44875:                                 // Complete Raptor Capture
989                {
990                    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
991                        return;
992
993                    Creature* creatureTarget = (Creature*)unitTarget;
994
995                    creatureTarget->setDeathState(JUST_DIED);
996                    creatureTarget->RemoveCorpse();
997                    creatureTarget->SetHealth(0);           // just for nice GM-mode view
998
999                    //cast spell Raptor Capture Credit
1000                    m_caster->CastSpell(m_caster,42337,true,NULL);
1001                    return;
1002                }
1003                case 37573:                                 //Temporal Phase Modulator
1004                {
1005                    if(!unitTarget)
1006                        return;
1007
1008                    TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1009                    if(!tempSummon)
1010                        return;
1011
1012                    uint32 health = tempSummon->GetHealth();
1013                    const uint32 entry_list[6] = {21821, 21820, 21817};
1014
1015                    float x = tempSummon->GetPositionX();
1016                    float y = tempSummon->GetPositionY();
1017                    float z = tempSummon->GetPositionZ();
1018                    float o = tempSummon->GetOrientation();
1019
1020                    tempSummon->UnSummon();
1021
1022                    Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1023                    if (!pCreature)
1024                        return;
1025
1026                    pCreature->SetHealth(health);
1027
1028                    if(pCreature->AI())
1029                        pCreature->AI()->AttackStart(m_caster);
1030
1031                    return;
1032                }
1033                case 34665:                                 //Administer Antidote
1034                {
1035                    if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1036                        return;
1037
1038                    if(!unitTarget)
1039                        return;
1040
1041                    TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1042                    if(!tempSummon)
1043                        return;
1044
1045                    uint32 health = tempSummon->GetHealth();
1046
1047                    float x = tempSummon->GetPositionX();
1048                    float y = tempSummon->GetPositionY();
1049                    float z = tempSummon->GetPositionZ();
1050                    float o = tempSummon->GetOrientation();
1051                    tempSummon->UnSummon();
1052
1053                    Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1054                    if (!pCreature)
1055                        return;
1056
1057                    pCreature->SetHealth(health);
1058                    ((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID());
1059
1060                    if (pCreature->AI())
1061                        pCreature->AI()->AttackStart(m_caster);
1062
1063                    return;
1064                }
1065                case 44997:                                 // Converting Sentry
1066                {
1067                    //Converted Sentry Credit
1068                    m_caster->CastSpell(m_caster, 45009, true);
1069                    return;
1070                }               
1071                case 45030:                                 // Impale Emissary
1072                {
1073                    // Emissary of Hate Credit
1074                    m_caster->CastSpell(m_caster, 45088, true);
1075                    return;
1076                }
1077                case 50243:                                 // Teach Language
1078                {
1079                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
1080                        return;
1081
1082                    // spell has a 1/3 chance to trigger one of the below
1083                    if(roll_chance_i(66))
1084                        return;
1085                    if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1086                    {
1087                        // 1000001 - gnomish binary
1088                        m_caster->CastSpell(m_caster, 50242, true);
1089                    }
1090                    else
1091                    {
1092                        // 01001000 - goblin binary
1093                        m_caster->CastSpell(m_caster, 50246, true);
1094                    }
1095
1096                    return;
1097                }
1098                case 51582:                                 //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1099                {
1100                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
1101                        return;
1102
1103                    if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1104                        bg->EventPlayerDroppedFlag((Player*)m_caster);
1105
1106                    m_caster->CastSpell(m_caster, 30452, true, NULL);
1107                    return;
1108                }
1109            }
1110
1111            //All IconID Check in there
1112            switch(m_spellInfo->SpellIconID)
1113            {
1114                // Berserking (troll racial traits)
1115                case 1661:
1116                {
1117                    uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1118                    int32 melee_mod = 10;
1119                    if (healthPerc <= 40)
1120                        melee_mod = 30;
1121                    if (healthPerc < 100 && healthPerc > 40)
1122                        melee_mod = 10+(100-healthPerc)/3;
1123
1124                    int32 hasteModBasePoints0 = melee_mod;          // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1125                    int32 hasteModBasePoints1 = (5-melee_mod);
1126                    int32 hasteModBasePoints2 = 5;
1127
1128                    // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1129                    m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1130                    m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1131                    return;
1132                }
1133            }
1134            break;
1135        case SPELLFAMILY_MAGE:
1136            switch(m_spellInfo->Id )
1137            {
1138                case 11958:                                 // Cold Snap
1139                {
1140                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1141                        return;
1142
1143                    // immediately finishes the cooldown on Frost spells
1144                    const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1145                    for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1146                    {
1147                        if (itr->second->state == PLAYERSPELL_REMOVED)
1148                            continue;
1149
1150                        uint32 classspell = itr->first;
1151                        SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1152
1153                        if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1154                            (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1155                            spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1156                        {
1157                            ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1158
1159                            WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1160                            data << uint32(classspell);
1161                            data << uint64(m_caster->GetGUID());
1162                            ((Player*)m_caster)->GetSession()->SendPacket(&data);
1163                        }
1164                    }
1165                    return;
1166                }
1167                case 32826:
1168                {
1169                    if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1170                    {
1171                        //Polymorph Cast Visual Rank 1
1172                        const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1173                        unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true); 
1174                    }
1175                    return;
1176                }
1177            }
1178            break;
1179        case SPELLFAMILY_WARRIOR:
1180            // Charge
1181            if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867)
1182            {
1183                int32 chargeBasePoints0 = damage;
1184                m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1185                return;
1186            }
1187            // Execute
1188            if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1189            {
1190                if(!unitTarget)
1191                    return;
1192
1193                int32 basePoints0 = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]);
1194                m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1195                m_caster->SetPower(POWER_RAGE,0);
1196                return;
1197            }
1198            if(m_spellInfo->Id==21977)                      //Warrior's Wrath
1199            {
1200                if(!unitTarget)
1201                    return;
1202
1203                m_caster->CastSpell(unitTarget,21887,true); // spell mod
1204                return;
1205            }
1206            break;
1207        case SPELLFAMILY_WARLOCK:
1208            //Life Tap (only it have this with dummy effect)
1209            if (m_spellInfo->SpellFamilyFlags == 0x40000)
1210            {
1211                float cost = m_currentBasePoints[0]+1;
1212
1213                if(Player* modOwner = m_caster->GetSpellModOwner())
1214                    modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this);
1215
1216                int32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE);
1217
1218                if(int32(m_caster->GetHealth()) > dmg)
1219                {
1220                    // Shouldn't Appear in Combat Log
1221                    m_caster->ModifyHealth(-dmg);
1222
1223                    int32 mana = dmg;
1224
1225                    Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1226                    for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1227                    {
1228                        // only Imp. Life Tap have this in combination with dummy aura
1229                        if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1230                            mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1231                    }
1232
1233                    m_caster->CastCustomSpell(m_caster,31818,&mana,NULL,NULL,true,NULL);
1234
1235                    // Mana Feed
1236                    int32 manaFeedVal = m_caster->CalculateSpellDamage(m_spellInfo,1, m_spellInfo->EffectBasePoints[1],m_caster);
1237                    manaFeedVal = manaFeedVal * mana / 100;
1238                    if(manaFeedVal > 0)
1239                        m_caster->CastCustomSpell(m_caster,32553,&manaFeedVal,NULL,NULL,true,NULL);
1240                }
1241                else
1242                    SendCastResult(SPELL_FAILED_FIZZLE);
1243                return;
1244            }
1245            break;
1246        case SPELLFAMILY_PRIEST:
1247            switch(m_spellInfo->Id )
1248            {
1249                case 28598:                                 // Touch of Weakness triggered spell
1250                {
1251                    if(!unitTarget || !m_triggeredByAuraSpell)
1252                        return;
1253
1254                    uint32 spellid = 0;
1255                    switch(m_triggeredByAuraSpell->Id)
1256                    {
1257                        case 2652:  spellid =  2943; break; // Rank 1
1258                        case 19261: spellid = 19249; break; // Rank 2
1259                        case 19262: spellid = 19251; break; // Rank 3
1260                        case 19264: spellid = 19252; break; // Rank 4
1261                        case 19265: spellid = 19253; break; // Rank 5
1262                        case 19266: spellid = 19254; break; // Rank 6
1263                        case 25461: spellid = 25460; break; // Rank 7
1264                        default:
1265                            sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell->Id);
1266                            return;
1267                    }
1268                    m_caster->CastSpell(unitTarget, spellid, true, NULL);
1269                    return;
1270                }
1271            }
1272            break;
1273        case SPELLFAMILY_DRUID:
1274            switch(m_spellInfo->Id )
1275            {
1276                case 5420:                                  // Tree of Life passive
1277                {
1278                    // Tree of Life area effect
1279                    int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4);
1280                    m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL);
1281                    return;
1282                }
1283            }
1284            break;
1285        case SPELLFAMILY_ROGUE:
1286            switch(m_spellInfo->Id )
1287            {
1288                case 31231:                                 // Cheat Death
1289                {
1290                    m_caster->CastSpell(m_caster,45182,true);
1291                    return;
1292                }
1293                case 5938:                                  // Shiv
1294                {
1295                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
1296                        return;
1297
1298                    Player *pCaster = ((Player*)m_caster);
1299
1300                    Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1301                    if(!item)
1302                        return;
1303
1304                    // all poison enchantments is temporary
1305                    uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1306                    if(!enchant_id)
1307                        return;
1308
1309                    SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1310                    if(!pEnchant)
1311                        return;
1312
1313                    for (int s=0;s<3;s++)
1314                    {
1315                        if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1316                            continue;
1317
1318                        SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1319                        if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1320                            continue;
1321
1322                        m_caster->CastSpell(unitTarget, combatEntry, true, item);
1323                    }
1324
1325                    m_caster->CastSpell(unitTarget, 5940, true);
1326                    return;
1327                }
1328            }
1329            break;
1330        case SPELLFAMILY_HUNTER:
1331            // Steady Shot
1332            if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1333            {
1334                if( !unitTarget || !unitTarget->isAlive())
1335                    return;
1336
1337                bool found = false;
1338
1339                // check dazed affect
1340                Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1341                for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1342                {
1343                    if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1344                    {
1345                        found = true;
1346                        break;
1347                    }
1348                }
1349
1350                if(found)
1351                    m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
1352                return;
1353            }
1354            // Kill command
1355            if(m_spellInfo->SpellFamilyFlags & 0x00080000000000LL)
1356            {
1357                if(m_caster->getClass()!=CLASS_HUNTER)
1358                    return;
1359
1360                // clear hunter crit aura state
1361                m_caster->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE,false);
1362
1363                // additional damage from pet to pet target
1364                Pet* pet = m_caster->GetPet();
1365                if(!pet || !pet->getVictim())
1366                    return;
1367
1368                uint32 spell_id = 0;
1369                switch (m_spellInfo->Id)
1370                {
1371                case 34026: spell_id = 34027; break;        // rank 1
1372                default:
1373                    sLog.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo->Id);
1374                    return;
1375                }
1376
1377                pet->CastSpell(pet->getVictim(), spell_id, true);
1378                return;
1379            }
1380
1381            switch(m_spellInfo->Id)
1382            {
1383                case 23989:                                 //Readiness talent
1384                {
1385                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1386                        return;
1387
1388                    //immediately finishes the cooldown for hunter abilities
1389                    const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1390                    for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1391                    {
1392                        uint32 classspell = itr->first;
1393                        SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1394
1395                        if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1396                        {
1397                            ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1398
1399                            WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1400                            data << uint32(classspell);
1401                            data << uint64(m_caster->GetGUID());
1402                            ((Player*)m_caster)->GetSession()->SendPacket(&data);
1403                        }
1404                    }
1405                    return;
1406                }
1407                case 37506:                                 // Scatter Shot
1408                {
1409                    if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1410                        return;
1411
1412                    // break Auto Shot and autohit
1413                    m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1414                    m_caster->AttackStop();
1415                    ((Player*)m_caster)->SendAttackSwingCancelAttack();
1416                    return;
1417                }
1418            }
1419            break;
1420        case SPELLFAMILY_PALADIN:
1421            switch(m_spellInfo->SpellIconID)
1422            {
1423                case  156:                                  // Holy Shock
1424                {
1425                    if(!unitTarget)
1426                        return;
1427
1428                    int hurt = 0;
1429                    int heal = 0;
1430
1431                    switch(m_spellInfo->Id)
1432                    {
1433                        case 20473: hurt = 25912; heal = 25914; break;
1434                        case 20929: hurt = 25911; heal = 25913; break;
1435                        case 20930: hurt = 25902; heal = 25903; break;
1436                        case 27174: hurt = 27176; heal = 27175; break;
1437                        case 33072: hurt = 33073; heal = 33074; break;
1438                        default:
1439                            sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1440                            return;
1441                    }
1442
1443                    if(m_caster->IsFriendlyTo(unitTarget))
1444                        m_caster->CastSpell(unitTarget, heal, true, 0);
1445                    else
1446                        m_caster->CastSpell(unitTarget, hurt, true, 0);
1447
1448                    return;
1449                }
1450                case 561:                                   // Judgement of command
1451                {
1452                    if(!unitTarget)
1453                        return;
1454
1455                    uint32 spell_id = m_currentBasePoints[i]+1;
1456                    SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1457                    if(!spell_proto)
1458                        return;
1459
1460                    if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1461                    {
1462                        // decreased damage (/2) for non-stunned target.
1463                        SpellModifier *mod = new SpellModifier;
1464                        mod->op = SPELLMOD_DAMAGE;
1465                        mod->value = -50;
1466                        mod->type = SPELLMOD_PCT;
1467                        mod->spellId = m_spellInfo->Id;
1468                        mod->effectId = i;
1469                        mod->lastAffected = NULL;
1470                        mod->mask = 0x0000020000000000LL;
1471                        mod->charges = 0;
1472
1473                        ((Player*)m_caster)->AddSpellMod(mod, true);
1474                        m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1475                                                            // mod deleted
1476                        ((Player*)m_caster)->AddSpellMod(mod, false);
1477                    }
1478                    else
1479                        m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1480
1481                    return;
1482                }
1483            }
1484
1485            switch(m_spellInfo->Id)
1486            {
1487                case 31789:                                 // Righteous Defense (step 1)
1488                {
1489                    // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1490
1491                    // non-standard cast requirement check
1492                    if (!unitTarget || unitTarget->getAttackers().empty())
1493                    {
1494                        // clear cooldown at fail
1495                        if(m_caster->GetTypeId()==TYPEID_PLAYER)
1496                        {
1497                            ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1498
1499                            WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1500                            data << uint32(m_spellInfo->Id);
1501                            data << uint64(m_caster->GetGUID());
1502                            ((Player*)m_caster)->GetSession()->SendPacket(&data);
1503                        }
1504
1505                        SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1506                        return;
1507                    }
1508
1509                    // Righteous Defense (step 2) (in old version 31980 dummy effect)
1510                    // Clear targets for eff 1
1511                    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1512                        ihit->effectMask &= ~(1<<1);
1513
1514                    // not empty (checked)
1515                    Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1516
1517                    // chance to be selected from list
1518                    float chance = 100.0f/attackers.size();
1519                    uint32 count=0;
1520                    for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1521                    {
1522                        if(!roll_chance_f(chance))
1523                            continue;
1524                        ++count;
1525                        AddUnitTarget((*aItr), 1);
1526                    }
1527
1528                    // now let next effect cast spell at each target.
1529                    return;
1530                }
1531                case 37877:                                 // Blessing of Faith
1532                {
1533                    if(!unitTarget)
1534                        return;
1535
1536                    uint32 spell_id = 0;
1537                    switch(unitTarget->getClass())
1538                    {
1539                        case CLASS_DRUID:   spell_id = 37878; break;
1540                        case CLASS_PALADIN: spell_id = 37879; break;
1541                        case CLASS_PRIEST:  spell_id = 37880; break;
1542                        case CLASS_SHAMAN:  spell_id = 37881; break;
1543                        default: return;                    // ignore for not healing classes
1544                    }
1545
1546                    m_caster->CastSpell(m_caster,spell_id,true);
1547                    return;
1548                }
1549            }
1550            break;
1551        case SPELLFAMILY_SHAMAN:
1552            //Shaman Rockbiter Weapon
1553            if (m_spellInfo->SpellFamilyFlags == 0x400000)
1554            {
1555                uint32 spell_id = 0;
1556                switch(m_spellInfo->Id)
1557                {
1558                    case  8017: spell_id = 36494; break;    // Rank 1
1559                    case  8018: spell_id = 36750; break;    // Rank 2
1560                    case  8019: spell_id = 36755; break;    // Rank 3
1561                    case 10399: spell_id = 36759; break;    // Rank 4
1562                    case 16314: spell_id = 36763; break;    // Rank 5
1563                    case 16315: spell_id = 36766; break;    // Rank 6
1564                    case 16316: spell_id = 36771; break;    // Rank 7
1565                    case 25479: spell_id = 36775; break;    // Rank 8
1566                    case 25485: spell_id = 36499; break;    // Rank 9
1567                    default:
1568                        sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1569                        return;
1570                }
1571
1572                SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1573
1574                if(!spellInfo)
1575                {
1576                    sLog.outError("WORLD: unknown spell id %i\n", spell_id);
1577                    return;
1578                }
1579
1580                if(m_caster->GetTypeId() != TYPEID_PLAYER)
1581                    return;
1582
1583                for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
1584                {
1585                    if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i)))
1586                    {
1587                        if(item->IsFitToSpellRequirements(m_spellInfo))
1588                        {
1589                            Spell *spell = new Spell(m_caster, spellInfo, true);
1590
1591                            // enchanting spell selected by calculated damage-per-sec in enchanting effect
1592                            // at calculation applied affect from Elemental Weapons talent
1593                            // real enchantment damage-1
1594                            spell->m_currentBasePoints[1] = damage-1;
1595
1596                            SpellCastTargets targets;
1597                            targets.setItemTarget( item );
1598                            spell->prepare(&targets);
1599                        }
1600                    }
1601                }
1602                return;
1603            }
1604
1605            if(m_spellInfo->Id == 39610)                    // Mana-Tide Totem effect
1606            {
1607                if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1608                    return;
1609
1610                // Regenerate 6% of Total Mana Every 3 secs
1611                int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA)  * damage / 100;
1612                m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1613                return;
1614            }
1615
1616            break;
1617    }
1618
1619    // pet auras
1620    if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1621    {
1622        m_caster->AddPetAura(petSpell);
1623        return;
1624    }
1625}
1626
1627void Spell::EffectTriggerSpellWithValue(uint32 i)
1628{
1629    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1630
1631    // normal case
1632    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1633
1634    if(!spellInfo)
1635    {
1636        sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id);
1637        return;
1638    }
1639
1640    int32 bp = damage;
1641    m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1642}
1643
1644void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1645{
1646    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1647    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1648
1649    if(!spellInfo)
1650    {
1651        sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1652        return;
1653    }
1654
1655    finish();
1656    Spell *spell = new Spell(m_caster, spellInfo, true);
1657
1658    SpellCastTargets targets;
1659    targets.setUnitTarget( unitTarget);
1660    spell->prepare(&targets);
1661
1662    m_caster->SetCurrentCastedSpell(spell);
1663    spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1664
1665}
1666
1667void Spell::EffectForceCast(uint32 i)
1668{
1669    if( !unitTarget )
1670        return;
1671
1672    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1673
1674    // normal case
1675    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1676
1677    if(!spellInfo)
1678    {
1679        sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1680        return;
1681    }
1682
1683    unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1684}
1685
1686void Spell::EffectTriggerSpell(uint32 i)
1687{
1688    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1689
1690    // special cases
1691    switch(triggered_spell_id)
1692    {
1693        // Vanish
1694        case 18461:
1695        {
1696            m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1697            m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1698            m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1699
1700            // if this spell is given to NPC it must handle rest by it's own AI
1701            if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1702                return;
1703
1704            // get highest rank of the Stealth spell
1705            uint32 spellId = 0;
1706            const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1707            for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1708            {
1709                // only highest rank is shown in spell book, so simply check if shown in spell book
1710                if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1711                    continue;
1712
1713                SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1714                if (!spellInfo)
1715                    continue;
1716
1717                if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1718                {
1719                    spellId = spellInfo->Id;
1720                    break;
1721                }
1722            }
1723
1724            // no Stealth spell found
1725            if (!spellId)
1726                return;
1727
1728            // reset cooldown on it if needed
1729            if(((Player*)m_caster)->HasSpellCooldown(spellId))
1730                ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1731
1732            m_caster->CastSpell(m_caster, spellId, true);
1733            return;
1734        }
1735        // just skip
1736        case 23770:                                         // Sayge's Dark Fortune of *
1737            // not exist, common cooldown can be implemented in scripts if need.
1738            return;
1739        // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1740        case 29284:
1741        {
1742            const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1743            if (!spell)
1744                return;
1745
1746            for (int i=0; i < spell->StackAmount; ++i)
1747                m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1748            return;
1749        }
1750        // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1751        case 29286:
1752        {
1753            const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1754            if (!spell)
1755                return;
1756
1757            for (int i=0; i < spell->StackAmount; ++i)
1758                m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1759            return;
1760        }
1761        // Righteous Defense
1762        case 31980:
1763        {
1764            m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1765            return;
1766        }
1767        // Cloak of Shadows
1768        case 35729 :
1769        {
1770            Unit::AuraMap& Auras = m_caster->GetAuras();
1771            for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1772            {
1773                // remove all harmful spells on you...
1774                if( // ignore positive and passive auras
1775                    !iter->second->IsPositive() && !iter->second->IsPassive()    &&
1776                    // ignore physical auras
1777                    (GetSpellSchoolMask(iter->second->GetSpellProto()) & SPELL_SCHOOL_MASK_NORMAL)==0 &&
1778                    // ignore immunity persistent spells
1779                    !( iter->second->GetSpellProto()->AttributesEx & 0x10000 ) )
1780                {
1781                    m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1782                    iter = Auras.begin();
1783                }
1784            }
1785            return;
1786        }
1787        // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1788        case 41967:
1789        {
1790            if (Unit *pet = m_caster->GetPet())
1791                pet->CastSpell(pet, 28305, true);
1792            return;
1793        }
1794    }
1795
1796    // normal case
1797    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1798
1799    if(!spellInfo)
1800    {
1801        sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1802        return;
1803    }
1804
1805    // some triggered spells require specific equipment
1806    if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1807    {
1808        // main hand weapon required
1809        if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1810        {
1811            Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1812
1813            // skip spell if no weapon in slot or broken
1814            if(!item || item->IsBroken() )
1815                return;
1816
1817            // skip spell if weapon not fit to triggered spell
1818            if(!item->IsFitToSpellRequirements(spellInfo))
1819                return;
1820        }
1821
1822        // offhand hand weapon required
1823        if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1824        {
1825            Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1826
1827            // skip spell if no weapon in slot or broken
1828            if(!item || item->IsBroken() )
1829                return;
1830
1831            // skip spell if weapon not fit to triggered spell
1832            if(!item->IsFitToSpellRequirements(spellInfo))
1833                return;
1834        }
1835    }
1836
1837    // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1838    bool instant = false;
1839    for(uint32 j = i+1; j < 3; ++j)
1840    {
1841        if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
1842        {
1843            instant = true;
1844            break;
1845        }
1846    }
1847
1848    if(instant)
1849    {
1850        if (unitTarget)
1851            m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
1852    }
1853    else
1854        m_TriggerSpells.push_back(spellInfo);
1855}
1856
1857void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
1858{
1859    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
1860
1861    // normal case
1862    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1863
1864    if(!spellInfo)
1865    {
1866        sLog.outError("EffectTriggerMissileSpell of spell %u: triggering unknown spell id %effect_idx", m_spellInfo->Id,triggered_spell_id);
1867        return;
1868    }
1869
1870    if (m_CastItem)
1871        DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1872
1873    Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID );
1874
1875    SpellCastTargets targets;
1876    targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ);
1877    spell->m_CastItem = m_CastItem;
1878    spell->prepare(&targets, NULL);
1879}
1880
1881void Spell::EffectTeleportUnits(uint32 i)
1882{
1883    if(!unitTarget || unitTarget->isInFlight())
1884        return;
1885
1886    switch (m_spellInfo->EffectImplicitTargetB[i])
1887    {
1888        case TARGET_INNKEEPER_COORDINATES:
1889        {
1890            // Only players can teleport to innkeeper
1891            if (unitTarget->GetTypeId() != TYPEID_PLAYER)
1892                return;
1893
1894            ((Player*)unitTarget)->TeleportTo(((Player*)unitTarget)->m_homebindMapId,((Player*)unitTarget)->m_homebindX,((Player*)unitTarget)->m_homebindY,((Player*)unitTarget)->m_homebindZ,unitTarget->GetOrientation(),unitTarget==m_caster ? TELE_TO_SPELL : 0);
1895            return;
1896        }
1897        case TARGET_TABLE_X_Y_Z_COORDINATES:
1898        {
1899            // TODO: Only players can teleport?
1900            if (unitTarget->GetTypeId() != TYPEID_PLAYER)
1901                return;
1902            SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id);
1903            if(!st)
1904            {
1905                sLog.outError( "Spell::EffectTeleportUnits - unknown Teleport coordinates for spell ID %u\n", m_spellInfo->Id );
1906                return;
1907            }
1908            ((Player*)unitTarget)->TeleportTo(st->target_mapId,st->target_X,st->target_Y,st->target_Z,st->target_Orientation,unitTarget==m_caster ? TELE_TO_SPELL : 0);
1909            break;
1910        }
1911        default:
1912        {
1913            // If not exist data for dest location - return
1914            if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
1915            {
1916                sLog.outError( "Spell::EffectTeleportUnits - unknown EffectImplicitTargetB[%u] = %u for spell ID %u\n", i, m_spellInfo->EffectImplicitTargetB[i], m_spellInfo->Id );
1917                return;
1918            }
1919            // Init dest coordinates
1920            uint32 mapid = m_caster->GetMapId();
1921            float x = m_targets.m_destX;
1922            float y = m_targets.m_destY;
1923            float z = m_targets.m_destZ;
1924            float orientation = unitTarget->GetOrientation();
1925            // Teleport
1926            if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1927                ((Player*)unitTarget)->TeleportTo(mapid, x, y, z, orientation, TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
1928            else
1929            {
1930                MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
1931                WorldPacket data;
1932                unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
1933                unitTarget->SendMessageToSet(&data, false);
1934            }
1935            return;
1936        }
1937    }
1938
1939    // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
1940    switch ( m_spellInfo->Id )
1941    {
1942        // Dimensional Ripper - Everlook
1943        case 23442:
1944        {
1945            int32 r = irand(0, 119);
1946            if ( r >= 70 )                                  // 7/12 success
1947            {
1948                if ( r < 100 )                              // 4/12 evil twin
1949                    m_caster->CastSpell(m_caster,23445,true);
1950                else                                        // 1/12 fire
1951                    m_caster->CastSpell(m_caster,23449,true);
1952            }
1953            return;
1954        }
1955        // Ultrasafe Transporter: Toshley's Station
1956        case 36941:
1957        {
1958            if ( roll_chance_i(50) )                        // 50% success
1959            {
1960                int32 rand_eff = urand(1,7);
1961                switch ( rand_eff )
1962                {
1963                    case 1:
1964                        // soul split - evil
1965                        m_caster->CastSpell(m_caster,36900,true);
1966                        break;
1967                    case 2:
1968                        // soul split - good
1969                        m_caster->CastSpell(m_caster,36901,true);
1970                        break;
1971                    case 3:
1972                        // Increase the size
1973                        m_caster->CastSpell(m_caster,36895,true);
1974                        break;
1975                    case 4:
1976                        // Decrease the size
1977                        m_caster->CastSpell(m_caster,36893,true);
1978                        break;
1979                    case 5:
1980                    // Transform
1981                    {
1982                        if (((Player*)m_caster)->GetTeam() == ALLIANCE )
1983                            m_caster->CastSpell(m_caster,36897,true);
1984                        else
1985                            m_caster->CastSpell(m_caster,36899,true);
1986                        break;
1987                    }
1988                    case 6:
1989                        // chicken
1990                        m_caster->CastSpell(m_caster,36940,true);
1991                        break;
1992                    case 7:
1993                        // evil twin
1994                        m_caster->CastSpell(m_caster,23445,true);
1995                        break;
1996                }
1997            }
1998            return;
1999        }
2000        // Dimensional Ripper - Area 52
2001        case 36890:
2002        {
2003            if ( roll_chance_i(50) )                        // 50% success
2004            {
2005                int32 rand_eff = urand(1,4);
2006                switch ( rand_eff )
2007                {
2008                    case 1:
2009                        // soul split - evil
2010                        m_caster->CastSpell(m_caster,36900,true);
2011                        break;
2012                    case 2:
2013                        // soul split - good
2014                        m_caster->CastSpell(m_caster,36901,true);
2015                        break;
2016                    case 3:
2017                        // Increase the size
2018                        m_caster->CastSpell(m_caster,36895,true);
2019                        break;
2020                    case 4:
2021                    // Transform
2022                    {
2023                        if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2024                            m_caster->CastSpell(m_caster,36897,true);
2025                        else
2026                            m_caster->CastSpell(m_caster,36899,true);
2027                        break;
2028                    }
2029                }
2030            }
2031            return;
2032        }
2033    }
2034}
2035
2036void Spell::EffectApplyAura(uint32 i)
2037{
2038    if(!unitTarget)
2039        return;
2040
2041    SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE];
2042    for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
2043        if(itr->type == m_spellInfo->EffectApplyAuraName[i])
2044            return;
2045
2046    // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2047    if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2048        (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2049        return;
2050
2051    Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2052    if(!caster)
2053        return;
2054
2055    sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2056
2057    Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2058
2059    // Now Reduce spell duration using data received at spell hit
2060    int32 duration = Aur->GetAuraMaxDuration();
2061    unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,m_caster,m_diminishLevel);
2062    Aur->setDiminishGroup(m_diminishGroup);
2063
2064    // if Aura removed and deleted, do not continue.
2065    if(duration== 0 && !(Aur->IsPermanent()))
2066    {
2067        delete Aur;
2068        return;
2069    }
2070
2071    if(duration != Aur->GetAuraMaxDuration())
2072    {
2073        Aur->SetAuraMaxDuration(duration);
2074        Aur->SetAuraDuration(duration);
2075    }
2076
2077    bool added = unitTarget->AddAura(Aur);
2078
2079    // Aura not added and deleted in AddAura call;
2080    if (!added)
2081        return;
2082
2083    // found crash at character loading, broken pointer to Aur...
2084    // Aur was deleted in AddAura()...
2085    if(!Aur)
2086        return;
2087
2088    // TODO Make a way so it works for every related spell!
2089    if(unitTarget->GetTypeId()==TYPEID_PLAYER)              // Negative buff should only be applied on players
2090    {
2091        uint32 spellId = 0;
2092        if(m_spellInfo->CasterAuraStateNot==AURA_STATE_WEAKENED_SOUL || m_spellInfo->TargetAuraStateNot==AURA_STATE_WEAKENED_SOUL)
2093            spellId = 6788;                                 // Weakened Soul
2094        else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_FORBEARANCE || m_spellInfo->TargetAuraStateNot==AURA_STATE_FORBEARANCE)
2095            spellId = 25771;                                // Forbearance
2096        else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_HYPOTHERMIA)
2097            spellId = 41425;                                // Hypothermia
2098        else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
2099            spellId = 11196;                                // Recently Bandaged
2100        else if( (m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000) )
2101            spellId = 23230;                                // Blood Fury - Healing Reduction
2102
2103        SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId);
2104        if (AdditionalSpellInfo)
2105        {
2106            // applied at target by target
2107            Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, &m_currentBasePoints[0], unitTarget,unitTarget, 0);
2108            unitTarget->AddAura(AdditionalAura);
2109            sLog.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]);
2110        }
2111    }
2112
2113    // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2114    if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2115        m_caster->CastSpell(unitTarget,41637,true,NULL,Aur);
2116}
2117
2118void Spell::EffectUnlearnSpecialization( uint32 i )
2119{
2120    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2121        return;
2122
2123    Player *_player = (Player*)unitTarget;
2124    uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2125
2126    _player->removeSpell(spellToUnlearn);
2127
2128    sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2129}
2130
2131void Spell::EffectPowerDrain(uint32 i)
2132{
2133    if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2134        return;
2135
2136    Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2137
2138    if(!unitTarget)
2139        return;
2140    if(!unitTarget->isAlive())
2141        return;
2142    if(unitTarget->getPowerType() != drain_power)
2143        return;
2144    if(damage < 0)
2145        return;
2146
2147    uint32 curPower = unitTarget->GetPower(drain_power);
2148
2149    //add spell damage bonus
2150    damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2151
2152    // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2153    uint32 power = damage;
2154    if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2155        power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2156
2157    int32 new_damage;
2158    if(curPower < power)
2159        new_damage = curPower;
2160    else
2161        new_damage = power;
2162
2163    unitTarget->ModifyPower(drain_power,-new_damage);
2164
2165    if(drain_power == POWER_MANA)
2166    {
2167        float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2168        if(manaMultiplier==0)
2169            manaMultiplier = 1;
2170
2171        if(Player *modOwner = m_caster->GetSpellModOwner())
2172            modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2173
2174        int32 gain = int32(new_damage*manaMultiplier);
2175
2176        m_caster->ModifyPower(POWER_MANA,gain);
2177        //send log
2178        m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA,false);
2179    }
2180}
2181
2182void Spell::EffectSendEvent(uint32 EffectIndex)
2183{
2184    if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround())
2185    {
2186        BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
2187        if(bg && bg->GetStatus() == STATUS_IN_PROGRESS)
2188        {
2189            switch(m_spellInfo->Id)
2190            {
2191                case 23333:                                 // Pickup Horde Flag
2192                    /*do not uncomment .
2193                    if(bg->GetTypeID()==BATTLEGROUND_WS)
2194                        bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2195                    sLog.outDebug("Send Event Horde Flag Picked Up");
2196                    break;
2197                    /* not used :
2198                    case 23334:                                 // Drop Horde Flag
2199                        if(bg->GetTypeID()==BATTLEGROUND_WS)
2200                            bg->EventPlayerDroppedFlag((Player*)m_caster);
2201                        sLog.outDebug("Drop Horde Flag");
2202                        break;
2203                    */
2204                case 23335:                                 // Pickup Alliance Flag
2205                    /*do not uncomment ... (it will cause crash, because of null targetobject!) anyway this is a bad way to call that event, because it would cause recursion
2206                    if(bg->GetTypeID()==BATTLEGROUND_WS)
2207                        bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2208                    sLog.outDebug("Send Event Alliance Flag Picked Up");
2209                    break;
2210                    /* not used :
2211                    case 23336:                                 // Drop Alliance Flag
2212                        if(bg->GetTypeID()==BATTLEGROUND_WS)
2213                            bg->EventPlayerDroppedFlag((Player*)m_caster);
2214                        sLog.outDebug("Drop Alliance Flag");
2215                        break;
2216                    case 23385:                                 // Alliance Flag Returns
2217                        if(bg->GetTypeID()==BATTLEGROUND_WS)
2218                            bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2219                        sLog.outDebug("Alliance Flag Returned");
2220                        break;
2221                    case 23386:                                   // Horde Flag Returns
2222                        if(bg->GetTypeID()==BATTLEGROUND_WS)
2223                            bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2224                        sLog.outDebug("Horde Flag Returned");
2225                        break;*/
2226                case 34976:
2227                    /*
2228                    if(bg->GetTypeID()==BATTLEGROUND_EY)
2229                        bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2230                    */
2231                    break;
2232                default:
2233                    sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id);
2234                    break;
2235            }
2236        }
2237    }
2238    sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2239    sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2240}
2241
2242void Spell::EffectPowerBurn(uint32 i)
2243{
2244    if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2245        return;
2246
2247    Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2248
2249    if(!unitTarget)
2250        return;
2251    if(!unitTarget->isAlive())
2252        return;
2253    if(unitTarget->getPowerType()!=powertype)
2254        return;
2255    if(damage < 0)
2256        return;
2257
2258    int32 curPower = int32(unitTarget->GetPower(powertype));
2259
2260    // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2261    uint32 power = damage;
2262    if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2263        power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2264
2265    int32 new_damage = (curPower < power) ? curPower : power;
2266
2267    unitTarget->ModifyPower(powertype,-new_damage);
2268    float multiplier = m_spellInfo->EffectMultipleValue[i];
2269
2270    if(Player *modOwner = m_caster->GetSpellModOwner())
2271        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2272
2273    new_damage = int32(new_damage*multiplier);
2274    m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2275}
2276
2277void Spell::EffectHeal( uint32 /*i*/ )
2278{
2279    if( unitTarget && unitTarget->isAlive() && damage >= 0)
2280    {
2281        // Try to get original caster
2282        Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2283
2284        // Skip if m_originalCaster not available
2285        if (!caster)
2286            return;
2287
2288        int32 addhealth = damage;
2289
2290        // Vessel of the Naaru (Vial of the Sunwell trinket)
2291        if (m_spellInfo->Id == 45064)
2292        {
2293            // Amount of heal - depends from stacked Holy Energy
2294            int damageAmount = 0;
2295            Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2296            for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2297                if((*i)->GetId() == 45062)
2298                    damageAmount+=(*i)->GetModifier()->m_amount;
2299            if (damageAmount)
2300                m_caster->RemoveAurasDueToSpell(45062);
2301
2302            addhealth += damageAmount;
2303        }
2304        // Swiftmend - consumes Regrowth or Rejuvenation
2305        else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2306        {
2307            Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2308            // find most short by duration
2309            Aura *targetAura = NULL;
2310            for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2311            {
2312                if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2313                    && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2314                {
2315                    if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2316                        targetAura = *i;
2317                }
2318            }
2319
2320            if(!targetAura)
2321            {
2322                sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2323                return;
2324            }
2325            int idx = 0;
2326            while(idx < 3)
2327            {
2328                if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2329                    break;
2330                idx++;
2331            }
2332
2333            int32 tickheal = caster->SpellHealingBonus(targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT, unitTarget);
2334            int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2335            unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2336
2337            addhealth += tickheal * tickcount;
2338        }
2339        else
2340            addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget);
2341
2342        bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask, m_attackType);
2343        if (crit)
2344            addhealth = caster->SpellCriticalBonus(m_spellInfo, addhealth, unitTarget);
2345        caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, crit);
2346
2347        int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2348        unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2349
2350        if(caster->GetTypeId()==TYPEID_PLAYER)
2351            if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2352                bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2353
2354        // ignore item heals
2355        if(m_CastItem)
2356            return;
2357
2358        uint32 procHealer = PROC_FLAG_HEAL;
2359        if (crit)
2360            procHealer |= PROC_FLAG_CRIT_HEAL;
2361
2362        m_caster->ProcDamageAndSpell(unitTarget,procHealer,PROC_FLAG_HEALED,addhealth,SPELL_SCHOOL_MASK_NONE,m_spellInfo,m_IsTriggeredSpell);
2363    }
2364}
2365
2366void Spell::EffectHealPct( uint32 /*i*/ )
2367{
2368    if( unitTarget && unitTarget->isAlive() && damage >= 0)
2369    {
2370        // Try to get original caster
2371        Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2372
2373        // Skip if m_originalCaster not available
2374        if (!caster)
2375            return;
2376
2377        uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2378        caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2379
2380        int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2381        unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2382
2383        if(caster->GetTypeId()==TYPEID_PLAYER)
2384            if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2385                bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2386    }
2387}
2388
2389void Spell::EffectHealMechanical( uint32 /*i*/ )
2390{
2391    // Mechanic creature type should be correctly checked by targetCreatureType field
2392    if( unitTarget && unitTarget->isAlive() && damage >= 0)
2393    {
2394        // Try to get original caster
2395        Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2396
2397        // Skip if m_originalCaster not available
2398        if (!caster)
2399            return;
2400
2401        uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget);
2402        caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2403        unitTarget->ModifyHealth( int32(damage) );
2404    }
2405}
2406
2407void Spell::EffectHealthLeech(uint32 i)
2408{
2409    if(!unitTarget)
2410        return;
2411    if(!unitTarget->isAlive())
2412        return;
2413
2414    if(damage < 0)
2415        return;
2416
2417    sLog.outDebug("HealthLeech :%i", damage);
2418
2419    float multiplier = m_spellInfo->EffectMultipleValue[i];
2420
2421    if(Player *modOwner = m_caster->GetSpellModOwner())
2422        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2423
2424    int32 new_damage = int32(damage*multiplier);
2425    uint32 curHealth = unitTarget->GetHealth();
2426    new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2427    if(curHealth < new_damage)
2428        new_damage = curHealth;
2429
2430    if(m_caster->isAlive())
2431    {
2432        new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster);
2433
2434        m_caster->ModifyHealth(new_damage);
2435
2436        if(m_caster->GetTypeId() == TYPEID_PLAYER)
2437            m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage));
2438    }
2439}
2440
2441void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2442{
2443    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2444        return;
2445
2446    Player* player = (Player*)unitTarget;
2447
2448    uint32 newitemid = itemtype;
2449    ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2450    if(!pProto)
2451    {
2452        player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2453        return;
2454    }
2455
2456    uint32 num_to_add;
2457
2458    // TODO: maybe all this can be replaced by using correct calculated `damage` value
2459    if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2460    {
2461        int32 basePoints = m_currentBasePoints[i];
2462        int32 randomPoints = m_spellInfo->EffectDieSides[i];
2463        if (randomPoints)
2464            num_to_add = basePoints + irand(1, randomPoints);
2465        else
2466            num_to_add = basePoints + 1;
2467    }
2468    else if (pProto->MaxCount == 1)
2469        num_to_add = 1;
2470    else if(player->getLevel() >= m_spellInfo->spellLevel)
2471    {
2472        int32 basePoints = m_currentBasePoints[i];
2473        float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2474        num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2475    }
2476    else
2477        num_to_add = 2;
2478
2479    if (num_to_add < 1)
2480        num_to_add = 1;
2481    if (num_to_add > pProto->Stackable)
2482        num_to_add = pProto->Stackable;
2483
2484    // init items_count to 1, since 1 item will be created regardless of specialization
2485    int items_count=1;
2486    // the chance to create additional items
2487    float additionalCreateChance=0.0f;
2488    // the maximum number of created additional items
2489    uint8 additionalMaxNum=0;
2490    // get the chance and maximum number for creating extra items
2491    if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2492    {
2493        // roll with this chance till we roll not to create or we create the max num
2494        while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2495            ++items_count;
2496    }
2497
2498    // really will be created more items
2499    num_to_add *= items_count;
2500
2501    // can the player store the new item?
2502    ItemPosCountVec dest;
2503    uint32 no_space = 0;
2504    uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2505    if( msg != EQUIP_ERR_OK )
2506    {
2507        // convert to possible store amount
2508        if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2509            num_to_add -= no_space;
2510        else
2511        {
2512            // if not created by another reason from full inventory or unique items amount limitation
2513            player->SendEquipError( msg, NULL, NULL );
2514            return;
2515        }
2516    }
2517
2518    if(num_to_add)
2519    {
2520        // create the new item and store it
2521        Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2522
2523        // was it successful? return error if not
2524        if(!pItem)
2525        {
2526            player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2527            return;
2528        }
2529
2530        // set the "Crafted by ..." property of the item
2531        if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2532            pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2533
2534        // send info to the client
2535        if(pItem)
2536            player->SendNewItem(pItem, num_to_add, true, true);
2537
2538        // we succeeded in creating at least one item, so a levelup is possible
2539        player->UpdateCraftSkill(m_spellInfo->Id);
2540    }
2541
2542    // for battleground marks send by mail if not add all expected
2543    if(no_space > 0 )
2544    {
2545        BattleGroundTypeId bgType;
2546        switch(m_spellInfo->Id)
2547        {
2548            case SPELL_AV_MARK_WINNER:
2549            case SPELL_AV_MARK_LOSER:
2550                bgType = BATTLEGROUND_AV;
2551                break;
2552            case SPELL_WS_MARK_WINNER:
2553            case SPELL_WS_MARK_LOSER:
2554                bgType = BATTLEGROUND_WS;
2555                break;
2556            case SPELL_AB_MARK_WINNER:
2557            case SPELL_AB_MARK_LOSER:
2558                bgType = BATTLEGROUND_AB;
2559                break;
2560            default:
2561                return;
2562        }
2563
2564        if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2565            bg->SendRewardMarkByMail(player,newitemid,no_space);
2566    }
2567}
2568
2569void Spell::EffectCreateItem(uint32 i)
2570{
2571    DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2572}
2573
2574void Spell::EffectPersistentAA(uint32 i)
2575{
2576    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2577
2578    if(Player* modOwner = m_caster->GetSpellModOwner())
2579        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2580
2581    int32 duration = GetSpellDuration(m_spellInfo);
2582    DynamicObject* dynObj = new DynamicObject;
2583    if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
2584    {
2585        delete dynObj;
2586        return;
2587    }
2588    dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2589    dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2590    dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2591    m_caster->AddDynObject(dynObj);
2592    MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj);
2593}
2594
2595void Spell::EffectEnergize(uint32 i)
2596{
2597    if(!unitTarget)
2598        return;
2599    if(!unitTarget->isAlive())
2600        return;
2601
2602    if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2603        return;
2604
2605    // Some level depends spells
2606    int multipler  = 0;
2607    int level_diff = 0;
2608    switch (m_spellInfo->Id)
2609    {
2610        // Restore Energy
2611        case 9512:
2612            level_diff = m_caster->getLevel() - 40;
2613            multipler  = 2;
2614            break;
2615        // Blood Fury
2616        case 24571:
2617            level_diff = m_caster->getLevel() - 60;
2618            multipler  = 10;
2619            break;
2620        // Burst of Energy
2621        case 24532:
2622            level_diff = m_caster->getLevel() - 60;
2623            multipler  = 4;
2624            break;
2625        default:
2626            break;
2627    }
2628
2629    if (level_diff > 0)
2630        damage -= multipler * level_diff;
2631
2632    if(damage < 0)
2633        return;
2634
2635    Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2636
2637    if(unitTarget->GetMaxPower(power) == 0)
2638        return;
2639
2640    unitTarget->ModifyPower(power,damage);
2641    m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2642
2643    // Mad Alchemist's Potion
2644    if (m_spellInfo->Id == 45051)
2645    {
2646        // find elixirs on target
2647        uint32 elixir_mask = 0;
2648        Unit::AuraMap& Auras = unitTarget->GetAuras();
2649        for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2650        {
2651            uint32 spell_id = itr->second->GetId();
2652            if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2653                elixir_mask |= mask;
2654        }
2655
2656        // get available elixir mask any not active type from battle/guardian (and flask if no any)
2657        elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2658
2659        // get all available elixirs by mask and spell level
2660        std::vector<uint32> elixirs;
2661        SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2662        for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2663        {
2664            if (itr->second & elixir_mask)
2665            {
2666                if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2667                    continue;
2668
2669                SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2670                if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2671                    continue;
2672
2673                elixirs.push_back(itr->first);
2674            }
2675        }
2676
2677        if (!elixirs.empty())
2678        {
2679            // cast random elixir on target
2680            uint32 rand_spell = urand(0,elixirs.size()-1);
2681            m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2682        }
2683    }
2684}
2685
2686void Spell::EffectEnergisePct(uint32 i)
2687{
2688    if(!unitTarget)
2689        return;
2690    if(!unitTarget->isAlive())
2691        return;
2692
2693    if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2694        return;
2695
2696    Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2697
2698    uint32 maxPower = unitTarget->GetMaxPower(power);
2699    if(maxPower == 0)
2700        return;
2701
2702    uint32 gain = damage * maxPower / 100;
2703    unitTarget->ModifyPower(power, gain);
2704    m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2705}
2706
2707void Spell::SendLoot(uint64 guid, LootType loottype)
2708{
2709    Player* player = (Player*)m_caster;
2710    if (!player)
2711        return;
2712
2713    if (gameObjTarget)
2714    {
2715        switch (gameObjTarget->GetGoType())
2716        {
2717            case GAMEOBJECT_TYPE_DOOR:
2718            case GAMEOBJECT_TYPE_BUTTON:
2719                gameObjTarget->UseDoorOrButton();
2720                sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2721                return;
2722
2723            case GAMEOBJECT_TYPE_QUESTGIVER:
2724                // start or end quest
2725                player->PrepareQuestMenu(guid);
2726                player->SendPreparedQuest(guid);
2727                return;
2728
2729            case GAMEOBJECT_TYPE_SPELL_FOCUS:
2730                // triggering linked GO
2731                if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2732                    gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2733                return;
2734
2735            case GAMEOBJECT_TYPE_GOOBER:
2736                // goober_scripts can be triggered if the player don't have the quest
2737                if (gameObjTarget->GetGOInfo()->goober.eventId)
2738                {
2739                    sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2740                    sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2741                }
2742
2743                // cast goober spell
2744                if (gameObjTarget->GetGOInfo()->goober.questId)
2745                    ///Quest require to be active for GO using
2746                    if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2747                        return;
2748
2749                gameObjTarget->AddUniqueUse(player);
2750                gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2751
2752                //TODO? Objective counting called without spell check but with quest objective check
2753                // if send spell id then this line will duplicate to spell casting call (double counting)
2754                // So we or have this line and not required in quest_template have reqSpellIdN
2755                // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2756                player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2757
2758                // triggering linked GO
2759                if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2760                    gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2761
2762                return;
2763
2764            case GAMEOBJECT_TYPE_CHEST:
2765                // TODO: possible must be moved to loot release (in different from linked triggering)
2766                if (gameObjTarget->GetGOInfo()->chest.eventId)
2767                {
2768                    sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2769                    sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2770                }
2771
2772                // triggering linked GO
2773                if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2774                    gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2775
2776                // Don't return, let loots been taken
2777        }
2778    }
2779
2780    // Send loot
2781    player->SendLoot(guid, loottype);
2782}
2783
2784void Spell::EffectOpenLock(uint32 /*i*/)
2785{
2786    if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2787    {
2788        sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2789        return;
2790    }
2791
2792    Player* player = (Player*)m_caster;
2793
2794    LootType loottype = LOOT_CORPSE;
2795    uint32 lockId = 0;
2796    uint64 guid = 0;
2797
2798    // Get lockId
2799    if(gameObjTarget)
2800    {
2801        GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2802        // Arathi Basin banner opening !
2803        if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2804            goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2805        {
2806            //isAllowUseBattleGroundObject() already called in CanCast()
2807            // in battleground check
2808            if(BattleGround *bg = player->GetBattleGround())
2809            {
2810                // check if it's correct bg
2811                if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2812                    bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2813                return;
2814            }
2815        }
2816        else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2817        {
2818            //isAllowUseBattleGroundObject() already called in CanCast()
2819            // in battleground check
2820            if(BattleGround *bg = player->GetBattleGround())
2821            {
2822                if(bg->GetTypeID() == BATTLEGROUND_EY)
2823                    bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2824                return;
2825            }
2826        }
2827        // handle outdoor pvp object opening, return true if go was registered for handling
2828        // these objects must have been spawned by outdoorpvp!
2829        else if(gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr.HandleOpenGo(player, gameObjTarget->GetGUID()))
2830            return;
2831        lockId = gameObjTarget->GetLockId();
2832        guid = gameObjTarget->GetGUID();
2833    }
2834    else if(itemTarget)
2835    {
2836        lockId = itemTarget->GetProto()->LockID;
2837        guid = itemTarget->GetGUID();
2838    }
2839    else
2840    {
2841        sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2842        return;
2843    }
2844
2845    if(!lockId)                                             // possible case for GO and maybe for items.
2846    {
2847        SendLoot(guid, loottype);
2848        return;
2849    }
2850
2851    // Get LockInfo
2852    LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
2853
2854    if (!lockInfo)
2855    {
2856        sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2857            (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
2858        SendCastResult(SPELL_FAILED_BAD_TARGETS);
2859        return;
2860    }
2861
2862    // check key
2863    for(int i = 0; i < 5; ++i)
2864    {
2865        // type==1 This means lockInfo->key[i] is an item
2866        if(lockInfo->keytype[i]==LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[i])
2867        {
2868            SendLoot(guid, loottype);
2869            return;
2870        }
2871    }
2872
2873    uint32 SkillId = 0;
2874    // Check and skill-up skill
2875    if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL )
2876        SkillId = m_spellInfo->EffectMiscValue[1];
2877                                                            // pickpocketing spells
2878    else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK )
2879        SkillId = SKILL_LOCKPICKING;
2880
2881    // skill bonus provided by casting spell (mostly item spells)
2882    uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1);
2883
2884    uint32 reqSkillValue = lockInfo->requiredminingskill;
2885
2886    if(lockInfo->requiredlockskill)                         // required pick lock skill applying
2887    {
2888        if(SkillId != SKILL_LOCKPICKING)                    // wrong skill (cheating?)
2889        {
2890            SendCastResult(SPELL_FAILED_FIZZLE);
2891            return;
2892        }
2893
2894        reqSkillValue = lockInfo->requiredlockskill;
2895    }
2896    else if(SkillId == SKILL_LOCKPICKING)                   // apply picklock skill to wrong target
2897    {
2898        SendCastResult(SPELL_FAILED_BAD_TARGETS);
2899        return;
2900    }
2901
2902    if ( SkillId )
2903    {
2904        loottype = LOOT_SKINNING;
2905        if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
2906        {
2907            SendCastResult(SPELL_FAILED_LOW_CASTLEVEL);
2908            return;
2909        }
2910
2911        // update skill if really known
2912        uint32 SkillValue = player->GetPureSkillValue(SkillId);
2913        if(SkillValue)                                      // non only item base skill
2914        {
2915            if(gameObjTarget)
2916            {
2917                // Allow one skill-up until respawned
2918                if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
2919                    player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) )
2920                    gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
2921            }
2922            else if(itemTarget)
2923            {
2924                // Do one skill-up
2925                uint32 SkillValue = player->GetPureSkillValue(SkillId);
2926                player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
2927            }
2928        }
2929    }
2930
2931    SendLoot(guid, loottype);
2932}
2933
2934void Spell::EffectSummonChangeItem(uint32 i)
2935{
2936    if(m_caster->GetTypeId() != TYPEID_PLAYER)
2937        return;
2938
2939    Player *player = (Player*)m_caster;
2940
2941    // applied only to using item
2942    if(!m_CastItem)
2943        return;
2944
2945    // ... only to item in own inventory/bank/equip_slot
2946    if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
2947        return;
2948
2949    uint32 newitemid = m_spellInfo->EffectItemType[i];
2950    if(!newitemid)
2951        return;
2952
2953    uint16 pos = m_CastItem->GetPos();
2954
2955    Item *pNewItem = Item::CreateItem( newitemid, 1, player);
2956    if( !pNewItem )
2957        return;
2958
2959    for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i)
2960    {
2961        if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i)))
2962            pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i)));
2963    }
2964
2965    if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
2966    {
2967        double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
2968        player->DurabilityLoss(pNewItem, loosePercent);
2969    }
2970
2971    if( player->IsInventoryPos( pos ) )
2972    {
2973        ItemPosCountVec dest;
2974        uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
2975        if( msg == EQUIP_ERR_OK )
2976        {
2977            player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
2978
2979            // prevent crash at access and unexpected charges counting with item update queue corrupt
2980            if(m_CastItem==m_targets.getItemTarget())
2981                m_targets.setItemTarget(NULL);
2982
2983            m_CastItem = NULL;
2984
2985            player->StoreItem( dest, pNewItem, true);
2986            return;
2987        }
2988    }
2989    else if( player->IsBankPos ( pos ) )
2990    {
2991        ItemPosCountVec dest;
2992        uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
2993        if( msg == EQUIP_ERR_OK )
2994        {
2995            player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
2996
2997            // prevent crash at access and unexpected charges counting with item update queue corrupt
2998            if(m_CastItem==m_targets.getItemTarget())
2999                m_targets.setItemTarget(NULL);
3000
3001            m_CastItem = NULL;
3002
3003            player->BankItem( dest, pNewItem, true);
3004            return;
3005        }
3006    }
3007    else if( player->IsEquipmentPos ( pos ) )
3008    {
3009        uint16 dest;
3010        uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3011        if( msg == EQUIP_ERR_OK )
3012        {
3013            player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3014
3015            // prevent crash at access and unexpected charges counting with item update queue corrupt
3016            if(m_CastItem==m_targets.getItemTarget())
3017                m_targets.setItemTarget(NULL);
3018
3019            m_CastItem = NULL;
3020
3021            player->EquipItem( dest, pNewItem, true);
3022            player->AutoUnequipOffhandIfNeed();
3023            return;
3024        }
3025    }
3026
3027    // fail
3028    delete pNewItem;
3029}
3030
3031void Spell::EffectOpenSecretSafe(uint32 i)
3032{
3033    EffectOpenLock(i);                                      //no difference for now
3034}
3035
3036void Spell::EffectProficiency(uint32 /*i*/)
3037{
3038    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3039        return;
3040    Player *p_target = (Player*)unitTarget;
3041
3042    uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3043    if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3044    {
3045        p_target->AddWeaponProficiency(subClassMask);
3046        p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3047    }
3048    if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3049    {
3050        p_target->AddArmorProficiency(subClassMask);
3051        p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3052    }
3053}
3054
3055void Spell::EffectApplyAreaAura(uint32 i)
3056{
3057    if(!unitTarget)
3058        return;
3059    if(!unitTarget->isAlive())
3060        return;
3061
3062    AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3063    unitTarget->AddAura(Aur);
3064}
3065
3066void Spell::EffectSummonType(uint32 i)
3067{
3068    switch(m_spellInfo->EffectMiscValueB[i])
3069    {
3070        case SUMMON_TYPE_GUARDIAN:
3071        case SUMMON_TYPE_POSESSED:
3072        case SUMMON_TYPE_POSESSED2:
3073            EffectSummonGuardian(i);
3074            break;
3075        case SUMMON_TYPE_WILD:
3076            EffectSummonWild(i);
3077            break;
3078        case SUMMON_TYPE_DEMON:
3079            EffectSummonDemon(i);
3080            break;
3081        case SUMMON_TYPE_SUMMON:
3082            EffectSummon(i);
3083            break;
3084        case SUMMON_TYPE_CRITTER:
3085        case SUMMON_TYPE_CRITTER2:
3086        case SUMMON_TYPE_CRITTER3:
3087            EffectSummonCritter(i);
3088            break;
3089        case SUMMON_TYPE_TOTEM_SLOT1:
3090        case SUMMON_TYPE_TOTEM_SLOT2:
3091        case SUMMON_TYPE_TOTEM_SLOT3:
3092        case SUMMON_TYPE_TOTEM_SLOT4:
3093        case SUMMON_TYPE_TOTEM:
3094            EffectSummonTotem(i);
3095            break;
3096        case SUMMON_TYPE_UNKNOWN1:
3097        case SUMMON_TYPE_UNKNOWN2:
3098        case SUMMON_TYPE_UNKNOWN3:
3099        case SUMMON_TYPE_UNKNOWN4:
3100        case SUMMON_TYPE_UNKNOWN5:
3101            break;
3102        default:
3103            sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3104            break;
3105    }
3106}
3107
3108void Spell::EffectSummon(uint32 i)
3109{
3110    if(m_caster->GetPetGUID())
3111        return;
3112
3113    if(!unitTarget)
3114        return;
3115    uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3116    if(!pet_entry)
3117        return;
3118    uint32 level = m_caster->getLevel();
3119    Pet* spawnCreature = new Pet(SUMMON_PET);
3120
3121    if(spawnCreature->LoadPetFromDB(m_caster,pet_entry))
3122    {
3123        // set timer for unsummon
3124        int32 duration = GetSpellDuration(m_spellInfo);
3125        if(duration > 0)
3126            spawnCreature->SetDuration(duration);
3127
3128        return;
3129    }
3130
3131    Map *map = m_caster->GetMap();
3132    uint32 pet_number = objmgr.GeneratePetNumber();
3133    if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_spellInfo->EffectMiscValue[i], pet_number))
3134    {
3135        sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3136        delete spawnCreature;
3137        return;
3138    }
3139
3140    // Summon in dest location
3141    float x,y,z;
3142    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3143    {
3144        x = m_targets.m_destX;
3145        y = m_targets.m_destY;
3146        z = m_targets.m_destZ;
3147    }
3148    else
3149        m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3150
3151    spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3152
3153    if(!spawnCreature->IsPositionValid())
3154    {
3155        sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3156        delete spawnCreature;
3157        return;
3158    }
3159
3160    // set timer for unsummon
3161    int32 duration = GetSpellDuration(m_spellInfo);
3162    if(duration > 0)
3163        spawnCreature->SetDuration(duration);
3164
3165    spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
3166    spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3167    spawnCreature->setPowerType(POWER_MANA);
3168    spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3169    spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3170    spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
3171    spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3172    spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3173    spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
3174    spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
3175    spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
3176    spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3177
3178    spawnCreature->InitStatsForLevel(level);
3179
3180    spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3181
3182    spawnCreature->AIM_Initialize();
3183    spawnCreature->InitPetCreateSpells();
3184    spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3185    spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3186
3187    std::string name = m_caster->GetName();
3188    name.append(petTypeSuffix[spawnCreature->getPetType()]);
3189    spawnCreature->SetName( name );
3190
3191    map->Add((Creature*)spawnCreature);
3192
3193    if(m_caster->GetTypeId() == TYPEID_PLAYER)
3194    {
3195        m_caster->SetPet(spawnCreature);
3196        spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3197        spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3198        ((Player*)m_caster)->PetSpellInitialize();
3199    }
3200}
3201
3202void Spell::EffectLearnSpell(uint32 i)
3203{
3204    if(!unitTarget)
3205        return;
3206
3207    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3208    {
3209        if(m_caster->GetTypeId() == TYPEID_PLAYER)
3210            EffectLearnPetSpell(i);
3211
3212        return;
3213    }
3214
3215    Player *player = (Player*)unitTarget;
3216
3217    uint32 spellToLearn = (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[i];
3218    player->learnSpell(spellToLearn);
3219
3220    sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3221}
3222
3223void Spell::EffectDispel(uint32 i)
3224{
3225    if(!unitTarget)
3226        return;
3227
3228    // Fill possible dispell list
3229    std::vector <Aura *> dispel_list;
3230
3231    // Create dispel mask by dispel type
3232    uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3233    uint32 dispelMask  = GetDispellMask( DispelType(dispel_type) );
3234    Unit::AuraMap const& auras = unitTarget->GetAuras();
3235    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3236    {
3237        Aura *aur = (*itr).second;
3238        if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3239        {
3240            if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3241            {
3242                bool positive = true;
3243                if (!aur->IsPositive())
3244                    positive = false;
3245                else
3246                    positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3247
3248                // do not remove positive auras if friendly target
3249                //               negative auras if non-friendly target
3250                if(positive == unitTarget->IsFriendlyTo(m_caster))
3251                    continue;
3252            }
3253            // Add aura to dispel list
3254            dispel_list.push_back(aur);
3255        }
3256    }
3257    // Ok if exist some buffs for dispel try dispel it
3258    if (!dispel_list.empty())
3259    {
3260        std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3261        std::list < uint32 > fail_list;                     // spell_id
3262        int32 list_size = dispel_list.size();
3263        // Dispell N = damage buffs (or while exist buffs for dispel)
3264        for (int32 count=0; count < damage && list_size > 0; ++count)
3265        {
3266            // Random select buff for dispel
3267            Aura *aur = dispel_list[urand(0, list_size-1)];
3268
3269            SpellEntry const* spellInfo = aur->GetSpellProto();
3270            // Base dispel chance
3271            // TODO: possible chance depend from spell level??
3272            int32 miss_chance = 0;
3273            // Apply dispel mod from aura caster
3274            if (Unit *caster = aur->GetCaster())
3275            {
3276                if ( Player* modOwner = caster->GetSpellModOwner() )
3277                    modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3278            }
3279            // Try dispel
3280            if (roll_chance_i(miss_chance))
3281                fail_list.push_back(aur->GetId());
3282            else
3283                success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3284            // Remove buff from list for prevent doubles
3285            for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3286            {
3287                Aura *dispeled = *j;
3288                if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3289                {
3290                    j = dispel_list.erase(j);
3291                    --list_size;
3292                }
3293                else
3294                    ++j;
3295            }
3296        }
3297        // Send success log and really remove auras
3298        if (!success_list.empty())
3299        {
3300            int32 count = success_list.size();
3301            WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3302            data.append(unitTarget->GetPackGUID());         // Victim GUID
3303            data.append(m_caster->GetPackGUID());           // Caster GUID
3304            data << uint32(m_spellInfo->Id);                // Dispell spell id
3305            data << uint8(0);                               // not used
3306            data << uint32(count);                          // count
3307            for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3308            {
3309                SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3310                data << uint32(spellInfo->Id);              // Spell Id
3311                data << uint8(0);                           // 0 - dispeled !=0 cleansed
3312                unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3313            }
3314            m_caster->SendMessageToSet(&data, true);
3315
3316            // On succes dispel
3317            // Devour Magic
3318            if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12)
3319            {
3320                uint32 heal_spell = 0;
3321                switch (m_spellInfo->Id)
3322                {
3323                    case 19505: heal_spell = 19658; break;
3324                    case 19731: heal_spell = 19732; break;
3325                    case 19734: heal_spell = 19733; break;
3326                    case 19736: heal_spell = 19735; break;
3327                    case 27276: heal_spell = 27278; break;
3328                    case 27277: heal_spell = 27279; break;
3329                    default:
3330                        sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3331                        break;
3332                }
3333                if (heal_spell)
3334                    m_caster->CastSpell(m_caster, heal_spell, true);
3335            }
3336        }
3337        // Send fail log to client
3338        if (!fail_list.empty())
3339        {
3340            // Failed to dispell
3341            WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3342            data << uint64(m_caster->GetGUID());            // Caster GUID
3343            data << uint64(unitTarget->GetGUID());          // Victim GUID
3344            data << uint32(m_spellInfo->Id);                // Dispell spell id
3345            for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3346                data << uint32(*j);                         // Spell Id
3347            m_caster->SendMessageToSet(&data, true);
3348        }
3349    }
3350}
3351
3352void Spell::EffectDualWield(uint32 /*i*/)
3353{
3354    if (unitTarget->GetTypeId() == TYPEID_PLAYER)
3355        ((Player*)unitTarget)->SetCanDualWield(true);
3356}
3357
3358void Spell::EffectPull(uint32 /*i*/)
3359{
3360    // TODO: create a proper pull towards distract spell center for distract
3361    sLog.outDebug("WORLD: Spell Effect DUMMY");
3362}
3363
3364void Spell::EffectDistract(uint32 /*i*/)
3365{
3366    // Check for possible target
3367    if (!unitTarget || unitTarget->isInCombat())
3368        return;
3369
3370    // target must be OK to do this
3371    if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3372        return;
3373
3374    float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3375
3376    if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3377    {
3378        // For players just turn them
3379        WorldPacket data;
3380        ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3381        ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3382        ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3383    }
3384    else
3385    {
3386        // Set creature Distracted, Stop it, And turn it
3387        unitTarget->SetOrientation(angle);
3388        unitTarget->StopMoving();
3389        unitTarget->GetMotionMaster()->MoveDistract(damage*1000);
3390    }
3391}
3392
3393void Spell::EffectPickPocket(uint32 /*i*/)
3394{
3395    if( m_caster->GetTypeId() != TYPEID_PLAYER )
3396        return;
3397
3398    // victim must be creature and attackable
3399    if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3400        return;
3401
3402    // victim have to be alive and humanoid or undead
3403    if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3404    {
3405        int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3406
3407        if (chance > irand(0, 19))
3408        {
3409            // Stealing successful
3410            //sLog.outDebug("Sending loot from pickpocket");
3411            ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3412        }
3413        else
3414        {
3415            // Reveal action + get attack
3416            m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3417            if (((Creature*)unitTarget)->AI())
3418                ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3419        }
3420    }
3421}
3422
3423void Spell::EffectAddFarsight(uint32 i)
3424{
3425    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3426    int32 duration = GetSpellDuration(m_spellInfo);
3427    DynamicObject* dynObj = new DynamicObject;
3428    if(!dynObj->Create(objmgr.GenerateLowGuid(HIGHGUID_DYNAMICOBJECT), m_caster, m_spellInfo->Id, i, m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ, duration, radius))
3429    {
3430        delete dynObj;
3431        return;
3432    }
3433    dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3434    dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3435    m_caster->AddDynObject(dynObj);
3436    MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj);
3437    m_caster->SetUInt64Value(PLAYER_FARSIGHT, dynObj->GetGUID());
3438}
3439
3440void Spell::EffectSummonWild(uint32 i)
3441{
3442    uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3443    if(!creature_entry)
3444        return;
3445
3446    uint32 level = m_caster->getLevel();
3447
3448    // level of creature summoned using engineering item based at engineering skill level
3449    if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3450    {
3451        ItemPrototype const *proto = m_CastItem->GetProto();
3452        if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3453        {
3454            uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3455            if(skill202)
3456            {
3457                level = skill202/5;
3458            }
3459        }
3460    }
3461
3462    // select center of summon position
3463    float center_x = m_targets.m_destX;
3464    float center_y = m_targets.m_destY;
3465    float center_z = m_targets.m_destZ;
3466
3467    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3468
3469    int32 amount = damage > 0 ? damage : 1;
3470
3471    for(int32 count = 0; count < amount; ++count)
3472    {
3473        float px, py, pz;
3474        // If dest location if present
3475        if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3476        {
3477            // Summon 1 unit in dest location
3478            if (count == 0)
3479            {
3480                px = m_targets.m_destX;
3481                py = m_targets.m_destY;
3482                pz = m_targets.m_destZ;
3483            }
3484            // Summon in random point all other units if location present
3485            else
3486                m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3487        }
3488        // Summon if dest location not present near caster
3489        else
3490            m_caster->GetClosePoint(px,py,pz,3.0f);
3491
3492        int32 duration = GetSpellDuration(m_spellInfo);
3493
3494        TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3495
3496        m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3497    }
3498}
3499
3500void Spell::EffectSummonGuardian(uint32 i)
3501{
3502    uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3503    if(!pet_entry)
3504        return;
3505
3506    // Jewelery statue case (totem like)
3507    if(m_spellInfo->SpellIconID==2056)
3508    {
3509        EffectSummonTotem(i);
3510        return;
3511    }
3512
3513    // set timer for unsummon
3514    int32 duration = GetSpellDuration(m_spellInfo);
3515
3516    // Search old Guardian only for players (if casted spell not have duration or cooldown)
3517    // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3518    //        so this code hack in fact
3519    if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3520        if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3521            return;                                         // find old guardian, ignore summon
3522
3523    // in another case summon new
3524    uint32 level = m_caster->getLevel();
3525
3526    // level of pet summoned using engineering item based at engineering skill level
3527    if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3528    {
3529        ItemPrototype const *proto = m_CastItem->GetProto();
3530        if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3531        {
3532            uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3533            if(skill202)
3534            {
3535                level = skill202/5;
3536            }
3537        }
3538    }
3539
3540    // select center of summon position
3541    float center_x = m_targets.m_destX;
3542    float center_y = m_targets.m_destY;
3543    float center_z = m_targets.m_destZ;
3544
3545    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3546
3547    int32 amount = damage > 0 ? damage : 1;
3548
3549    for(int32 count = 0; count < amount; ++count)
3550    {
3551        Pet* spawnCreature = new Pet(GUARDIAN_PET);
3552
3553        Map *map = m_caster->GetMap();
3554        uint32 pet_number = objmgr.GeneratePetNumber();
3555        if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number))
3556        {
3557            sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3558            delete spawnCreature;
3559            return;
3560        }
3561
3562        float px, py, pz;
3563        // If dest location if present
3564        if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3565        {
3566            // Summon 1 unit in dest location
3567            if (count == 0)
3568            {
3569                px = m_targets.m_destX;
3570                py = m_targets.m_destY;
3571                pz = m_targets.m_destZ;
3572            }
3573            // Summon in random point all other units if location present
3574            else
3575                m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3576        }
3577        // Summon if dest location not present near caster
3578        else
3579            m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3580
3581        spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3582
3583        if(!spawnCreature->IsPositionValid())
3584        {
3585            sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3586            delete spawnCreature;
3587            return;
3588        }
3589
3590        if(duration > 0)
3591            spawnCreature->SetDuration(duration);
3592
3593        spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
3594        spawnCreature->setPowerType(POWER_MANA);
3595        spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3596        spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3597        spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3598        spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3599        spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3600        spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
3601        spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3602
3603        spawnCreature->InitStatsForLevel(level);
3604        spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3605
3606        spawnCreature->AIM_Initialize();
3607
3608        if(m_caster->GetTypeId()==TYPEID_PLAYER)
3609            ((Player*)m_caster)->AddGuardian(spawnCreature);
3610
3611        map->Add((Creature*)spawnCreature);
3612    }
3613}
3614
3615void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3616{
3617    if(!unitTarget)
3618        return;
3619
3620    if(unitTarget->isInFlight())
3621        return;
3622
3623    uint32 mapid = m_caster->GetMapId();
3624    float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3625
3626    float fx,fy,fz;
3627    m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3628
3629    if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3630        ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, -m_caster->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
3631    else
3632        MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
3633}
3634
3635void Spell::EffectLearnSkill(uint32 i)
3636{
3637    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3638        return;
3639
3640    if(damage < 0)
3641        return;
3642
3643    uint32 skillid =  m_spellInfo->EffectMiscValue[i];
3644    uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3645    ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3646}
3647
3648void Spell::EffectAddHonor(uint32 /*i*/)
3649{
3650    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3651        return;
3652
3653    sLog.outDebug("SpellEffect::AddHonor called for spell_id %u , that rewards %d honor points to player: %u", m_spellInfo->Id, this->damage, ((Player*)unitTarget)->GetGUIDLow());
3654
3655    // TODO: find formula for honor reward based on player's level!
3656
3657    // now fixed only for level 70 players:
3658    if (((Player*)unitTarget)->getLevel() == 70)
3659        ((Player*)unitTarget)->RewardHonor(NULL, 1, this->damage);
3660}
3661
3662void Spell::EffectTradeSkill(uint32 /*i*/)
3663{
3664    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3665        return;
3666    // uint32 skillid =  m_spellInfo->EffectMiscValue[i];
3667    // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3668    // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3669}
3670
3671void Spell::EffectEnchantItemPerm(uint32 i)
3672{
3673    if(m_caster->GetTypeId() != TYPEID_PLAYER)
3674        return;
3675    if (!itemTarget)
3676        return;
3677
3678    Player* p_caster = (Player*)m_caster;
3679
3680    p_caster->UpdateCraftSkill(m_spellInfo->Id);
3681
3682    if (m_spellInfo->EffectMiscValue[i])
3683    {
3684        uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3685
3686        SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3687        if(!pEnchant)
3688            return;
3689
3690        // item can be in trade slot and have owner diff. from caster
3691        Player* item_owner = itemTarget->GetOwner();
3692        if(!item_owner)
3693            return;
3694
3695        if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3696            sLog.outCommand("GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3697                p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3698                itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3699                item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3700
3701        // remove old enchanting before applying new if equipped
3702        item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3703
3704        itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3705
3706        // add new enchanting if equipped
3707        item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3708    }
3709}
3710
3711void Spell::EffectEnchantItemTmp(uint32 i)
3712{
3713    if(m_caster->GetTypeId() != TYPEID_PLAYER)
3714        return;
3715
3716    Player* p_caster = (Player*)m_caster;
3717
3718    if(!itemTarget)
3719        return;
3720
3721    uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3722
3723    // Shaman Rockbiter Weapon
3724    if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3725    {
3726        int32 enchnting_damage = m_currentBasePoints[1]+1;
3727
3728        // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3729        // with already applied percent bonus from Elemental Weapons talent
3730        // Note: damage calculated (correctly) with rounding int32(float(v)) but
3731        // RW enchantments applied damage int32(float(v)+0.5), this create  0..1 difference sometime
3732        switch(enchnting_damage)
3733        {
3734            // Rank 1
3735            case  2: enchant_id =   29; break;              //  0% [ 7% ==  2, 14% == 2, 20% == 2]
3736            // Rank 2
3737            case  4: enchant_id =    6; break;              //  0% [ 7% ==  4, 14% == 4]
3738            case  5: enchant_id = 3025; break;              // 20%
3739            // Rank 3
3740            case  6: enchant_id =    1; break;              //  0% [ 7% ==  6, 14% == 6]
3741            case  7: enchant_id = 3027; break;              // 20%
3742            // Rank 4
3743            case  9: enchant_id = 3032; break;              //  0% [ 7% ==  6]
3744            case 10: enchant_id =  503; break;              // 14%
3745            case 11: enchant_id = 3031; break;              // 20%
3746            // Rank 5
3747            case 15: enchant_id = 3035; break;              // 0%
3748            case 16: enchant_id = 1663; break;              // 7%
3749            case 17: enchant_id = 3033; break;              // 14%
3750            case 18: enchant_id = 3034; break;              // 20%
3751            // Rank 6
3752            case 28: enchant_id = 3038; break;              // 0%
3753            case 29: enchant_id =  683; break;              // 7%
3754            case 31: enchant_id = 3036; break;              // 14%
3755            case 33: enchant_id = 3037; break;              // 20%
3756            // Rank 7
3757            case 40: enchant_id = 3041; break;              // 0%
3758            case 42: enchant_id = 1664; break;              // 7%
3759            case 45: enchant_id = 3039; break;              // 14%
3760            case 48: enchant_id = 3040; break;              // 20%
3761            // Rank 8
3762            case 49: enchant_id = 3044; break;              // 0%
3763            case 52: enchant_id = 2632; break;              // 7%
3764            case 55: enchant_id = 3042; break;              // 14%
3765            case 58: enchant_id = 3043; break;              // 20%
3766            // Rank 9
3767            case 62: enchant_id = 2633; break;              // 0%
3768            case 66: enchant_id = 3018; break;              // 7%
3769            case 70: enchant_id = 3019; break;              // 14%
3770            case 74: enchant_id = 3020; break;              // 20%
3771            default:
3772                sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3773                return;
3774        }
3775    }
3776
3777    if (!enchant_id)
3778    {
3779        sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3780        return;
3781    }
3782
3783    SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3784    if(!pEnchant)
3785    {
3786        sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3787        return;
3788    }
3789
3790    // select enchantment duration
3791    uint32 duration;
3792
3793    // rogue family enchantments exception by duration
3794    if(m_spellInfo->Id==38615)
3795        duration = 1800;                                    // 30 mins
3796    // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3797    else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3798        duration = 3600;                                    // 1 hour
3799    // shaman family enchantments
3800    else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3801        duration = 1800;                                    // 30 mins
3802    // other cases with this SpellVisual already selected
3803    else if(m_spellInfo->SpellVisual==215)
3804        duration = 1800;                                    // 30 mins
3805    // some fishing pole bonuses
3806    else if(m_spellInfo->SpellVisual==563)
3807        duration = 600;                                     // 10 mins
3808    // shaman rockbiter enchantments
3809    else if(m_spellInfo->SpellVisual==0)
3810        duration = 1800;                                    // 30 mins
3811    else if(m_spellInfo->Id==29702)
3812        duration = 300;                                     // 5 mins
3813    else if(m_spellInfo->Id==37360)
3814        duration = 300;                                     // 5 mins
3815    // default case
3816    else
3817        duration = 3600;                                    // 1 hour
3818
3819    // item can be in trade slot and have owner diff. from caster
3820    Player* item_owner = itemTarget->GetOwner();
3821    if(!item_owner)
3822        return;
3823
3824    if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3825        sLog.outCommand("GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3826            p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3827            itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3828            item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3829
3830    // remove old enchanting before applying new if equipped
3831    item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
3832
3833    itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
3834
3835    // add new enchanting if equipped
3836    item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
3837}
3838
3839void Spell::EffectTameCreature(uint32 /*i*/)
3840{
3841    if(m_caster->GetPetGUID())
3842        return;
3843
3844    if(!unitTarget)
3845        return;
3846
3847    if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3848        return;
3849
3850    Creature* creatureTarget = (Creature*)unitTarget;
3851
3852    if(creatureTarget->isPet())
3853        return;
3854
3855    if(m_caster->getClass() == CLASS_HUNTER)
3856    {
3857        // cast finish successfully
3858        //SendChannelUpdate(0);
3859        finish();
3860
3861        Pet* pet = new Pet(HUNTER_PET);
3862
3863        if(!pet->CreateBaseAtCreature(creatureTarget))
3864        {
3865            delete pet;
3866            return;
3867        }
3868
3869        creatureTarget->setDeathState(JUST_DIED);
3870        creatureTarget->RemoveCorpse();
3871        creatureTarget->SetHealth(0);                       // just for nice GM-mode view
3872
3873        pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
3874        pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
3875        pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3876        pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3877
3878        if(!pet->InitStatsForLevel(creatureTarget->getLevel()))
3879        {
3880            sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted.");
3881            delete pet;
3882            return;
3883        }
3884
3885        // prepare visual effect for levelup
3886        pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
3887
3888        pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true);
3889                                                            // this enables pet details window (Shift+P)
3890        pet->AIM_Initialize();
3891        pet->InitPetCreateSpells();
3892        pet->SetHealth(pet->GetMaxHealth());
3893
3894        MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
3895
3896        // visual effect for levelup
3897        pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
3898
3899        if(m_caster->GetTypeId() == TYPEID_PLAYER)
3900        {
3901            m_caster->SetPet(pet);
3902            pet->SavePetToDB(PET_SAVE_AS_CURRENT);
3903            ((Player*)m_caster)->PetSpellInitialize();
3904        }
3905    }
3906}
3907
3908void Spell::EffectSummonPet(uint32 i)
3909{
3910    uint32 petentry = m_spellInfo->EffectMiscValue[i];
3911
3912    Pet *OldSummon = m_caster->GetPet();
3913
3914    // if pet requested type already exist
3915    if( OldSummon )
3916    {
3917        if(petentry == 0 || OldSummon->GetEntry() == petentry)
3918        {
3919            // pet in corpse state can't be summoned
3920            if( OldSummon->isDead() )
3921                return;
3922
3923            MapManager::Instance().GetMap(OldSummon->GetMapId(), OldSummon)->Remove((Creature*)OldSummon,false);
3924            OldSummon->SetMapId(m_caster->GetMapId());
3925
3926            float px, py, pz;
3927            m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
3928
3929            OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
3930            MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->Add((Creature*)OldSummon);
3931
3932            if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
3933            {
3934                ((Player*)m_caster)->PetSpellInitialize();
3935            }
3936            return;
3937        }
3938
3939        if(m_caster->GetTypeId() == TYPEID_PLAYER)
3940            ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
3941        else
3942            return;
3943    }
3944
3945    Pet* NewSummon = new Pet;
3946
3947    // petentry==0 for hunter "call pet" (current pet summoned if any)
3948    if(NewSummon->LoadPetFromDB(m_caster,petentry))
3949    {
3950        if(NewSummon->getPetType()==SUMMON_PET)
3951        {
3952            // Remove Demonic Sacrifice auras (known pet)
3953            Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
3954            for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
3955            {
3956                if((*itr)->GetModifier()->m_miscvalue==2228)
3957                {
3958                    m_caster->RemoveAurasDueToSpell((*itr)->GetId());
3959                    itr = auraClassScripts.begin();
3960                }
3961                else
3962                    ++itr;
3963            }
3964        }
3965
3966        return;
3967    }
3968
3969    // not error in case fail hunter call pet
3970    if(!petentry)
3971    {
3972        delete NewSummon;
3973        return;
3974    }
3975
3976    CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
3977
3978    if(!cInfo)
3979    {
3980        sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
3981        delete NewSummon;
3982        return;
3983    }
3984
3985    Map *map = m_caster->GetMap();
3986    uint32 pet_number = objmgr.GeneratePetNumber();
3987    if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number))
3988    {
3989        delete NewSummon;
3990        return;
3991    }
3992
3993    float px, py, pz;
3994    m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
3995
3996    NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
3997
3998    if(!NewSummon->IsPositionValid())
3999    {
4000        sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4001        delete NewSummon;
4002        return;
4003    }
4004
4005    uint32 petlevel = m_caster->getLevel();
4006    NewSummon->setPetType(SUMMON_PET);
4007
4008    uint32 faction = m_caster->getFaction();
4009    if(m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->isTotem())
4010    {
4011        Unit* owner = ((Totem*)m_caster)->GetOwner();
4012        if(owner)
4013            faction = owner->getFaction();
4014        NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4015    }
4016
4017    NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
4018    NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
4019    NewSummon->SetUInt32Value(UNIT_NPC_FLAGS , 0);
4020    NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4021    NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
4022    NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
4023    NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,time(NULL));
4024    NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
4025    NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
4026    NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4027
4028    NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4029    // this enables pet details window (Shift+P)
4030
4031    // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4032    NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4033
4034    NewSummon->InitStatsForLevel( petlevel);
4035    NewSummon->InitPetCreateSpells();
4036
4037    if(NewSummon->getPetType()==SUMMON_PET)
4038    {
4039        // Remove Demonic Sacrifice auras (new pet)
4040        Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4041        for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4042        {
4043            if((*itr)->GetModifier()->m_miscvalue==2228)
4044            {
4045                m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4046                itr = auraClassScripts.begin();
4047            }
4048            else
4049                ++itr;
4050        }
4051
4052        // generate new name for summon pet
4053        std::string new_name=objmgr.GeneratePetName(petentry);
4054        if(!new_name.empty())
4055            NewSummon->SetName(new_name);
4056    }
4057    else if(NewSummon->getPetType()==HUNTER_PET)
4058        NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4059
4060    NewSummon->AIM_Initialize();
4061    NewSummon->SetHealth(NewSummon->GetMaxHealth());
4062    NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4063
4064    map->Add((Creature*)NewSummon);
4065
4066    m_caster->SetPet(NewSummon);
4067    sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4068
4069    if(m_caster->GetTypeId() == TYPEID_PLAYER)
4070    {
4071        NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4072        ((Player*)m_caster)->PetSpellInitialize();
4073    }
4074}
4075
4076void Spell::EffectLearnPetSpell(uint32 i)
4077{
4078    if(m_caster->GetTypeId() != TYPEID_PLAYER)
4079        return;
4080
4081    Player *_player = (Player*)m_caster;
4082
4083    Pet *pet = _player->GetPet();
4084    if(!pet)
4085        return;
4086    if(!pet->isAlive())
4087        return;
4088
4089    SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4090    if(!learn_spellproto)
4091        return;
4092
4093    pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id));
4094    pet->learnSpell(learn_spellproto->Id);
4095
4096    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4097    _player->PetSpellInitialize();
4098}
4099
4100void Spell::EffectTaunt(uint32 /*i*/)
4101{
4102    // this effect use before aura Taunt apply for prevent taunt already attacking target
4103    // for spell as marked "non effective at already attacking target"
4104    if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4105    {
4106        if(unitTarget->getVictim()==m_caster)
4107        {
4108            SendCastResult(SPELL_FAILED_DONT_REPORT);
4109            return;
4110        }
4111    }
4112
4113    // Also use this effect to set the taunter's threat to the taunted creature's highest value
4114    if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4115        unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4116}
4117
4118void Spell::EffectWeaponDmg(uint32 i)
4119{
4120    if(!unitTarget)
4121        return;
4122    if(!unitTarget->isAlive())
4123        return;
4124
4125    // multiple weapon dmg effect workaround
4126    // execute only the last weapon damage
4127    // and handle all effects at once
4128    for (int j = 0; j < 3; j++)
4129    {
4130        switch(m_spellInfo->Effect[j])
4131        {
4132            case SPELL_EFFECT_WEAPON_DAMAGE:
4133            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4134            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4135            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4136                if (j < i)                                  // we must calculate only at last weapon effect
4137                    return;
4138            break;
4139        }
4140    }
4141
4142    // some spell specific modifiers
4143    bool customBonusDamagePercentMod = false;
4144    float bonusDamagePercentMod  = 1.0f;                    // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4145    float weaponDamagePercentMod = 1.0f;                    // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4146    float totalDamagePercentMod  = 1.0f;                    // applied to final bonus+weapon damage
4147    bool normalized = false;
4148
4149    int32 spell_bonus = 0;                                  // bonus specific for spell
4150    switch(m_spellInfo->SpellFamilyName)
4151    {
4152        case SPELLFAMILY_WARRIOR:
4153        {
4154            // Whirlwind, single only spell with 2 weapon white damage apply if have
4155            if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4156            {
4157                if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4158                    spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4159            }
4160            // Devastate bonus and sunder armor refresh
4161            else if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508)
4162            {
4163                customBonusDamagePercentMod = true;
4164                bonusDamagePercentMod = 0.0f;               // only applied if auras found
4165
4166                Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE);
4167                for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr)
4168                {
4169                    SpellEntry const *proto = (*itr)->GetSpellProto();
4170                    if(proto->SpellVisual == 406 && proto->SpellIconID == 565)
4171                    {
4172                        int32 duration = GetSpellDuration(proto);
4173                        (*itr)->SetAuraDuration(duration);
4174                        (*itr)->UpdateAuraDuration();
4175                        bonusDamagePercentMod += 1.0f;      // +100%
4176                    }
4177                }
4178            }
4179            break;
4180        }
4181        case SPELLFAMILY_ROGUE:
4182        {
4183            // Ambush
4184            if(m_spellInfo->SpellFamilyFlags & 0x00000200LL)
4185            {
4186                customBonusDamagePercentMod = true;
4187                bonusDamagePercentMod = 2.5f;               // 250%
4188            }
4189            // Mutilate (for each hand)
4190            else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4191            {
4192                bool found = false;
4193                // fast check
4194                if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4195                    found = true;
4196                // full aura scan
4197                else
4198                {
4199                    Unit::AuraMap const& auras = unitTarget->GetAuras();
4200                    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4201                    {
4202                        if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4203                        {
4204                            found = true;
4205                            break;
4206                        }
4207                    }
4208                }
4209
4210                if(found)
4211                    totalDamagePercentMod *= 1.5f;          // 150% if poisoned
4212            }
4213            break;
4214        }
4215        case SPELLFAMILY_PALADIN:
4216        {
4217            // Seal of Command - receive benefit from Spell Damage and Healing
4218            if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4219            {
4220                spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4221                spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4222            }
4223            break;
4224        }
4225        case SPELLFAMILY_SHAMAN:
4226        {
4227            // Skyshatter Harness item set bonus
4228            // Stormstrike
4229            if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4230            {
4231                Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4232                for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4233                {
4234                    // Stormstrike AP Buff
4235                    if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4236                    {
4237                        m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4238                        break;
4239                    }
4240                }
4241            }
4242        }
4243    }
4244
4245    int32 fixed_bonus = 0;
4246    for (int j = 0; j < 3; j++)
4247    {
4248        switch(m_spellInfo->Effect[j])
4249        {
4250            case SPELL_EFFECT_WEAPON_DAMAGE:
4251            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4252                fixed_bonus += CalculateDamage(j,unitTarget);
4253                break;
4254            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4255                fixed_bonus += CalculateDamage(j,unitTarget);
4256                normalized = true;
4257                break;
4258            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4259                weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4260
4261                // applied only to prev.effects fixed damage
4262                if(customBonusDamagePercentMod)
4263                    fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod);
4264                else
4265                    fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4266                break;
4267            default:
4268                break;                                      // not weapon damage effect, just skip
4269        }
4270    }
4271
4272    // non-weapon damage
4273    int32 bonus = spell_bonus + fixed_bonus;
4274
4275    // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4276    if(bonus)
4277    {
4278        UnitMods unitMod;
4279        switch(m_attackType)
4280        {
4281            default:
4282            case BASE_ATTACK:   unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4283            case OFF_ATTACK:    unitMod = UNIT_MOD_DAMAGE_OFFHAND;  break;
4284            case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED;   break;
4285        }
4286
4287        float weapon_total_pct  = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4288        bonus = int32(bonus*weapon_total_pct);
4289    }
4290
4291    // + weapon damage with applied weapon% dmg to base weapon damage in call
4292    bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4293
4294    // total damage
4295    bonus = int32(bonus*totalDamagePercentMod);
4296
4297    // prevent negative damage
4298    uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4299
4300    const uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS;
4301
4302    uint32 hitInfo = 0;
4303    VictimState victimState = VICTIMSTATE_NORMAL;
4304    uint32 blocked_dmg = 0;
4305    uint32 absorbed_dmg = 0;
4306    uint32 resisted_dmg = 0;
4307    CleanDamage cleanDamage =  CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
4308
4309    m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell);
4310
4311    if ((hitInfo & nohitMask) && m_attackType != RANGED_ATTACK)  // not send ranged miss/etc
4312        m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchoolMask, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg);
4313
4314    bool criticalhit = (hitInfo & HITINFO_CRITICALHIT);
4315    m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchoolMask, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit);
4316
4317    if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg))
4318    {
4319        eff_damage -= (absorbed_dmg + resisted_dmg + blocked_dmg);
4320    }
4321    else
4322    {
4323        cleanDamage.damage += eff_damage;
4324        eff_damage = 0;
4325    }
4326
4327    // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation
4328    m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true);
4329
4330    // Hemorrhage
4331    if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4332    {
4333        if(m_caster->GetTypeId()==TYPEID_PLAYER)
4334            ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4335    }
4336    // Mangle (Cat): CP
4337    if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4338    {
4339        if(m_caster->GetTypeId()==TYPEID_PLAYER)
4340            ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4341    }
4342
4343
4344    // take ammo
4345    if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4346    {
4347        Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4348
4349        // wands don't have ammo
4350        if(!pItem  || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4351            return;
4352
4353        if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4354        {
4355            if(pItem->GetMaxStackCount()==1)
4356            {
4357                // decrease durability for non-stackable throw weapon
4358                ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4359            }
4360            else
4361            {
4362                // decrease items amount for stackable throw weapon
4363                uint32 count = 1;
4364                ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4365            }
4366        }
4367        else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4368            ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4369    }
4370}
4371
4372void Spell::EffectThreat(uint32 /*i*/)
4373{
4374    if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4375        return;
4376
4377    if(!unitTarget->CanHaveThreatList())
4378        return;
4379
4380    unitTarget->AddThreat(m_caster, float(damage));
4381}
4382
4383void Spell::EffectHealMaxHealth(uint32 /*i*/)
4384{
4385    if(!unitTarget)
4386        return;
4387    if(!unitTarget->isAlive())
4388        return;
4389
4390    uint32 heal = m_caster->GetMaxHealth();
4391
4392    int32 gain = unitTarget->ModifyHealth(heal);
4393    unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
4394
4395    m_caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, heal);
4396}
4397
4398void Spell::EffectInterruptCast(uint32 /*i*/)
4399{
4400    if(!unitTarget)
4401        return;
4402    if(!unitTarget->isAlive())
4403        return;
4404
4405    // TODO: not all spells that used this effect apply cooldown at school spells
4406    // also exist case: apply cooldown to interrupted cast only and to all spells
4407    for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4408    {
4409        if (unitTarget->m_currentSpells[i])
4410        {
4411            // check if we can interrupt spell
4412            if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4413            {
4414                unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4415                unitTarget->InterruptSpell(i,false);
4416            }
4417        }
4418    }
4419}
4420
4421void Spell::EffectSummonObjectWild(uint32 i)
4422{
4423    uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4424
4425    GameObject* pGameObj = new GameObject;
4426
4427    WorldObject* target = focusObject;
4428    if( !target )
4429        target = m_caster;
4430
4431    float x,y,z;
4432    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4433    {
4434        x = m_targets.m_destX;
4435        y = m_targets.m_destY;
4436        z = m_targets.m_destZ;
4437    }
4438    else
4439        m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4440
4441    Map *map = target->GetMap();
4442
4443    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4444        x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4445    {
4446        delete pGameObj;
4447        return;
4448    }
4449
4450    int32 duration = GetSpellDuration(m_spellInfo);
4451    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4452    pGameObj->SetSpellId(m_spellInfo->Id);
4453
4454    if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP)   // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4455        m_caster->AddGameObject(pGameObj);
4456    map->Add(pGameObj);
4457
4458    if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)  //WS
4459    {
4460        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4461        {
4462            Player *pl = (Player*)m_caster;
4463            BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4464            if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4465            {
4466                 uint32 team = ALLIANCE;
4467
4468                 if(pl->GetTeam() == team)
4469                     team = HORDE;
4470
4471                ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4472            }
4473        }
4474    }
4475
4476    if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)  //EY
4477    {
4478        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4479        {
4480            BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4481            if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4482            {
4483                ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4484            }
4485        }
4486    }
4487
4488    if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4489    {
4490        GameObject* linkedGO = new GameObject;
4491        if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4492            x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4493        {
4494            linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4495            linkedGO->SetSpellId(m_spellInfo->Id);
4496
4497            m_caster->AddGameObject(linkedGO);
4498            map->Add(linkedGO);
4499        }
4500        else
4501        {
4502            delete linkedGO;
4503            linkedGO = NULL;
4504            return;
4505        }
4506    }
4507}
4508
4509void Spell::EffectScriptEffect(uint32 effIndex)
4510{
4511    // TODO: we must implement hunter pet summon at login there (spell 6962)
4512
4513    // by spell id
4514    switch(m_spellInfo->Id)
4515    {
4516        // Bending Shinbone
4517        case 8856:
4518        {
4519            if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4520                return;
4521
4522            uint32 spell_id = 0;
4523            switch(urand(1,5))
4524            {
4525                case 1:  spell_id = 8854; break;
4526                default: spell_id = 8855; break;
4527            }
4528
4529            m_caster->CastSpell(m_caster,spell_id,true,NULL);
4530            return;
4531        }
4532
4533        // Healthstone creating spells
4534        case  6201:
4535        case  6202:
4536        case  5699:
4537        case 11729:
4538        case 11730:
4539        case 27230:
4540        {
4541            uint32 itemtype;
4542            uint32 rank = 0;
4543            Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4544            for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4545            {
4546                if((*i)->GetId() == 18692)
4547                {
4548                    rank = 1;
4549                    break;
4550                }
4551                else if((*i)->GetId() == 18693)
4552                {
4553                    rank = 2;
4554                    break;
4555                }
4556            }
4557
4558            static uint32 const itypes[6][3] = {
4559                { 5512,19004,19005},                        // Minor Healthstone
4560                { 5511,19006,19007},                        // Lesser Healthstone
4561                { 5509,19008,19009},                        // Healthstone
4562                { 5510,19010,19011},                        // Greater Healthstone
4563                { 9421,19012,19013},                        // Major Healthstone
4564                {22103,22104,22105}                         // Master Healthstone
4565            };
4566
4567            switch(m_spellInfo->Id)
4568            {
4569                case  6201: itemtype=itypes[0][rank];break; // Minor Healthstone
4570                case  6202: itemtype=itypes[1][rank];break; // Lesser Healthstone
4571                case  5699: itemtype=itypes[2][rank];break; // Healthstone
4572                case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone
4573                case 11730: itemtype=itypes[4][rank];break; // Major Healthstone
4574                case 27230: itemtype=itypes[5][rank];break; // Master Healthstone
4575                default:
4576                    return;
4577            }
4578            DoCreateItem( effIndex, itemtype );
4579            return;
4580        }
4581        // Brittle Armor - need remove one 24575 Brittle Armor aura
4582        case 24590:
4583            unitTarget->RemoveSingleAuraFromStack(24575, 0);
4584            unitTarget->RemoveSingleAuraFromStack(24575, 1);
4585            return;
4586        // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4587        case 26465:
4588            unitTarget->RemoveSingleAuraFromStack(26464, 0);
4589            return;
4590        // Orb teleport spells
4591        case 25140:
4592        case 25143:
4593        case 25650:
4594        case 25652:
4595        case 29128:
4596        case 29129:
4597        case 35376:
4598        case 35727:
4599        {
4600            if(!unitTarget)
4601                return;
4602
4603            uint32 spellid;
4604            switch(m_spellInfo->Id)
4605            {
4606                case 25140: spellid =  32571; break;
4607                case 25143: spellid =  32572; break;
4608                case 25650: spellid =  30140; break;
4609                case 25652: spellid =  30141; break;
4610                case 29128: spellid =  32568; break;
4611                case 29129: spellid =  32569; break;
4612                case 35376: spellid =  25649; break;
4613                case 35727: spellid =  35730; break;
4614                default:
4615                    return;
4616            }
4617
4618            unitTarget->CastSpell(unitTarget,spellid,false);
4619            return;
4620        }
4621
4622        // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4623        case 22539:
4624        case 22972:
4625        case 22975:
4626        case 22976:
4627        case 22977:
4628        case 22978:
4629        case 22979:
4630        case 22980:
4631        case 22981:
4632        case 22982:
4633        case 22983:
4634        case 22984:
4635        case 22985:
4636        {
4637            if(!unitTarget || !unitTarget->isAlive())
4638                return;
4639
4640            // Onyxia Scale Cloak
4641            if(unitTarget->GetDummyAura(22683))
4642                return;
4643
4644            // Shadow Flame
4645            m_caster->CastSpell(unitTarget, 22682, true);
4646            return;
4647        }
4648        break;
4649
4650        // Summon Black Qiraji Battle Tank
4651        case 26656:
4652        {
4653            if(!unitTarget)
4654                return;
4655
4656            // Prevent stacking of mounts
4657            unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4658
4659            // Two separate mounts depending on area id (allows use both in and out of specific instance)
4660            if (unitTarget->GetAreaId() == 3428)
4661                unitTarget->CastSpell(unitTarget, 25863, false);
4662            else
4663                unitTarget->CastSpell(unitTarget, 26655, false);
4664            break;
4665        }
4666        // Piccolo of the Flaming Fire
4667        case 17512:
4668        {
4669            if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4670                return;
4671            unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4672            break;
4673        }
4674
4675        // Netherbloom
4676        case 28702:
4677        {
4678            if(!unitTarget)
4679                return;
4680            // 25% chance of casting a random buff
4681            if(roll_chance_i(75))
4682                return;
4683
4684            // triggered spells are 28703 to 28707
4685            // Note: some sources say, that there was the possibility of
4686            //       receiving a debuff. However, this seems to be removed by a patch.
4687            const uint32 spellid = 28703;
4688
4689            // don't overwrite an existing aura
4690            for(uint8 i=0; i<5; i++)
4691                if(unitTarget->HasAura(spellid+i, 0))
4692                    return;
4693            unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
4694            break;
4695        }
4696
4697        // Nightmare Vine
4698        case 28720:
4699        {
4700            if(!unitTarget)
4701                return;
4702            // 25% chance of casting Nightmare Pollen
4703            if(roll_chance_i(75))
4704                return;
4705            unitTarget->CastSpell(unitTarget, 28721, true);
4706            break;
4707        }
4708
4709        // Mirren's Drinking Hat
4710        case 29830:
4711        {
4712            uint32 item = 0;
4713            switch ( urand(1,6) )
4714            {
4715                case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager
4716                case 4: case 5:         item = 23585; break;// Stouthammer Lite
4717                case 6:                 item = 23586; break;// Aerie Peak Pale Ale
4718            }
4719            if (item)
4720                DoCreateItem(effIndex,item);
4721            break;
4722        }
4723        // Improved Sprint
4724        case 30918:
4725        {
4726            // Removes snares and roots.
4727            uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4728            Unit::AuraMap& Auras = unitTarget->GetAuras();
4729            for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4730            {
4731                next = iter;
4732                ++next;
4733                Aura *aur = iter->second;
4734                if (!aur->IsPositive())             //only remove negative spells
4735                {
4736                    // check for mechanic mask
4737                    if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4738                    {
4739                        unitTarget->RemoveAurasDueToSpell(aur->GetId());
4740                        if(Auras.empty())
4741                            break;
4742                        else
4743                            next = Auras.begin();
4744                    }
4745                }
4746            }
4747            break;
4748        }
4749
4750        // Goblin Weather Machine
4751        case 46203:
4752        {
4753            if(!unitTarget)
4754                return;
4755
4756            uint32 spellId;
4757            switch(rand()%4)
4758            {
4759                case 0:
4760                    spellId=46740;
4761                    break;
4762                case 1:
4763                    spellId=46739;
4764                    break;
4765                case 2:
4766                    spellId=46738;
4767                    break;
4768                case 3:
4769                    spellId=46736;
4770                    break;
4771            }
4772            unitTarget->CastSpell(unitTarget, spellId, true);
4773            break;
4774        }
4775
4776    }
4777
4778    if(!unitTarget || !unitTarget->isAlive()) // can we remove this check?
4779    {
4780        sLog.outError("Spell %u in EffectScriptEffect does not have unitTarget", m_spellInfo->Id);
4781        return;
4782    }
4783
4784    switch(m_spellInfo->Id)
4785    {
4786        // Dreaming Glory
4787        case 28698: unitTarget->CastSpell(unitTarget, 28694, true); break;
4788        // Needle Spine
4789        case 39835: unitTarget->CastSpell(unitTarget, 39968, true); break;
4790        // Draw Soul
4791        case 40904: unitTarget->CastSpell(m_caster, 40903, true); break;
4792        // Flame Crash
4793        case 41126: unitTarget->CastSpell(unitTarget, 41131, true); break;
4794        // Force Cast - Portal Effect: Sunwell Isle
4795        case 44876: unitTarget->CastSpell(unitTarget, 44870, true); break;
4796        //5,000 Gold
4797        case 46642:
4798        {
4799            if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4800                ((Player*)unitTarget)->ModifyMoney(50000000);
4801            break;
4802        }
4803    }
4804
4805    if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
4806    {
4807        switch(m_spellInfo->SpellFamilyFlags)
4808        {
4809            // Judgement
4810            case 0x800000:
4811            {
4812                uint32 spellId2 = 0;
4813
4814                // all seals have aura dummy
4815                Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4816                for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
4817                {
4818                    SpellEntry const *spellInfo = (*itr)->GetSpellProto();
4819
4820                    // search seal (all seals have judgement's aura dummy spell id in 2 effect
4821                    if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 )
4822                        continue;
4823
4824                    // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
4825                    spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1;
4826
4827                    if(spellId2 <= 1)
4828                        continue;
4829
4830                    // found, remove seal
4831                    m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4832
4833                    // Sanctified Judgement
4834                    Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4835                    for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i)
4836                    {
4837                        if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL)
4838                        {
4839                            int32 chance = (*i)->GetModifier()->m_amount;
4840                            if ( roll_chance_i(chance) )
4841                            {
4842                                int32 mana = spellInfo->manaCost;
4843                                if ( Player* modOwner = m_caster->GetSpellModOwner() )
4844                                    modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana);
4845                                mana = int32(mana* 0.8f);
4846                                m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i);
4847                            }
4848                            break;
4849                        }
4850                    }
4851
4852                    break;
4853                }
4854
4855                m_caster->CastSpell(unitTarget,spellId2,true);
4856                return;
4857            }
4858        }
4859    }
4860
4861    // normal DB scripted effect
4862    sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
4863    sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
4864}
4865
4866void Spell::EffectSanctuary(uint32 /*i*/)
4867{
4868    if(!unitTarget)
4869        return;
4870    //unitTarget->CombatStop();
4871
4872    unitTarget->CombatStop();
4873    unitTarget->getHostilRefManager().deleteReferences();   // stop all fighting
4874    // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4875    if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
4876    {
4877        ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4878    }
4879}
4880
4881void Spell::EffectAddComboPoints(uint32 /*i*/)
4882{
4883    if(!unitTarget)
4884        return;
4885
4886    if(m_caster->GetTypeId() != TYPEID_PLAYER)
4887        return;
4888
4889    if(damage <= 0)
4890        return;
4891
4892    ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
4893}
4894
4895void Spell::EffectDuel(uint32 i)
4896{
4897    if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
4898        return;
4899
4900    Player *caster = (Player*)m_caster;
4901    Player *target = (Player*)unitTarget;
4902
4903    // caster or target already have requested duel
4904    if( caster->duel || target->duel || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
4905        return;
4906
4907    // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
4908    // Don't have to check the target's map since you cannot challenge someone across maps
4909    if( caster->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530)
4910    {
4911        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
4912        return;
4913    }
4914
4915    AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
4916    if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
4917    {
4918        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
4919        return;
4920    }
4921
4922    AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
4923    if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
4924    {
4925        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
4926        return;
4927    }
4928
4929    //CREATE DUEL FLAG OBJECT
4930    GameObject* pGameObj = new GameObject;
4931
4932    uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4933
4934    Map *map = m_caster->GetMap();
4935    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4936        m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
4937        m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
4938        m_caster->GetPositionZ(),
4939        m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1))
4940    {
4941        delete pGameObj;
4942        return;
4943    }
4944
4945    pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
4946    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
4947    int32 duration = GetSpellDuration(m_spellInfo);
4948    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4949    pGameObj->SetSpellId(m_spellInfo->Id);
4950
4951    m_caster->AddGameObject(pGameObj);
4952    map->Add(pGameObj);
4953    //END
4954
4955    // Send request
4956    WorldPacket data(SMSG_DUEL_REQUESTED, 16);
4957    data << pGameObj->GetGUID();
4958    data << caster->GetGUID();
4959    caster->GetSession()->SendPacket(&data);
4960    target->GetSession()->SendPacket(&data);
4961
4962    // create duel-info
4963    DuelInfo *duel   = new DuelInfo;
4964    duel->initiator  = caster;
4965    duel->opponent   = target;
4966    duel->startTime  = 0;
4967    duel->startTimer = 0;
4968    caster->duel     = duel;
4969
4970    DuelInfo *duel2   = new DuelInfo;
4971    duel2->initiator  = caster;
4972    duel2->opponent   = caster;
4973    duel2->startTime  = 0;
4974    duel2->startTimer = 0;
4975    target->duel      = duel2;
4976
4977    caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
4978    target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
4979}
4980
4981void Spell::EffectStuck(uint32 /*i*/)
4982{
4983    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4984        return;
4985
4986    if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
4987        return;
4988
4989    Player* pTarget = (Player*)unitTarget;
4990
4991    sLog.outDebug("Spell Effect: Stuck");
4992    sLog.outDetail("Player %s (guid %u) used auto-unstuck future at map %u (%f, %f, %f)", pTarget->GetName(), pTarget->GetGUIDLow(), m_caster->GetMapId(), m_caster->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ());
4993
4994    if(pTarget->isInFlight())
4995        return;
4996
4997    // homebind location is loaded always
4998    pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
4999
5000    // Stuck spell trigger Hearthstone cooldown
5001    SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5002    if(!spellInfo)
5003        return;
5004    Spell spell(pTarget,spellInfo,true,0);
5005    spell.SendSpellCooldown();
5006}
5007
5008void Spell::EffectSummonPlayer(uint32 /*i*/)
5009{
5010    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5011        return;
5012
5013    // Evil Twin (ignore player summon, but hide this for summoner)
5014    if(unitTarget->GetDummyAura(23445))
5015        return;
5016
5017    float x,y,z;
5018    m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5019
5020    ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5021
5022    WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5023    data << uint64(m_caster->GetGUID());                    // summoner guid
5024    data << uint32(m_caster->GetZoneId());                  // summoner zone
5025    data << uint32(MAX_PLAYER_SUMMON_DELAY*1000);           // auto decline after msecs
5026    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5027}
5028
5029static ScriptInfo generateActivateCommand()
5030{
5031    ScriptInfo si;
5032    si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5033    return si;
5034}
5035
5036void Spell::EffectActivateObject(uint32 effect_idx)
5037{
5038    if(!gameObjTarget)
5039        return;
5040
5041    static ScriptInfo activateCommand = generateActivateCommand();
5042
5043    int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5044
5045    sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5046}
5047
5048void Spell::EffectSummonTotem(uint32 i)
5049{
5050    uint8 slot = 0;
5051    switch(m_spellInfo->EffectMiscValueB[i])
5052    {
5053        case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5054        case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5055        case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5056        case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5057        // Battle standard case
5058        case SUMMON_TYPE_TOTEM:       slot = 254; break;
5059        // jewelery statue case, like totem without slot
5060        case SUMMON_TYPE_GUARDIAN:    slot = 255; break;
5061        default: return;
5062    }
5063
5064    if(slot < MAX_TOTEM)
5065    {
5066        uint64 guid = m_caster->m_TotemSlot[slot];
5067        if(guid != 0)
5068        {
5069            Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5070            if(OldTotem && OldTotem->isTotem())
5071                ((Totem*)OldTotem)->UnSummon();
5072        }
5073    }
5074
5075    uint32 team = 0;
5076    if (m_caster->GetTypeId()==TYPEID_PLAYER)
5077        team = ((Player*)m_caster)->GetTeam();
5078
5079    Totem* pTotem = new Totem;
5080
5081    if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team ))
5082    {
5083        delete pTotem;
5084        return;
5085    }
5086
5087    float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5088
5089    float x,y,z;
5090    m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5091
5092    // totem must be at same Z in case swimming caster and etc.
5093    if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5094        z = m_caster->GetPositionZ();
5095
5096    pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5097
5098    if(slot < MAX_TOTEM)
5099        m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5100
5101    pTotem->SetOwner(m_caster->GetGUID());
5102    pTotem->SetTypeBySummonSpell(m_spellInfo);              // must be after Create call where m_spells initilized
5103
5104    int32 duration=GetSpellDuration(m_spellInfo);
5105    if(Player* modOwner = m_caster->GetSpellModOwner())
5106        modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5107    pTotem->SetDuration(duration);
5108
5109    if (damage)                                             // if not spell info, DB values used
5110    {
5111        pTotem->SetMaxHealth(damage);
5112        pTotem->SetHealth(damage);
5113    }
5114
5115    pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5116    pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5117
5118    pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true);
5119    pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true);
5120
5121    pTotem->Summon(m_caster);
5122
5123    if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5124    {
5125        WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5126        data << uint8(slot);
5127        data << uint64(pTotem->GetGUID());
5128        data << uint32(duration);
5129        data << uint32(m_spellInfo->Id);
5130        ((Player*)m_caster)->SendDirectMessage(&data);
5131    }
5132}
5133
5134void Spell::EffectEnchantHeldItem(uint32 i)
5135{
5136    // this is only item spell effect applied to main-hand weapon of target player (players in area)
5137    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5138        return;
5139
5140    Player* item_owner = (Player*)unitTarget;
5141    Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5142
5143    if(!item )
5144        return;
5145
5146    // must be equipped
5147    if(!item ->IsEquipped())
5148        return;
5149
5150    if (m_spellInfo->EffectMiscValue[i])
5151    {
5152        uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5153        int32 duration = GetSpellDuration(m_spellInfo);          //Try duration index first ..
5154        if(!duration)
5155            duration = m_currentBasePoints[i]+1;            //Base points after ..
5156        if(!duration)
5157            duration = 10;                                  //10 seconds for enchants which don't have listed duration
5158
5159        SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5160        if(!pEnchant)
5161            return;
5162
5163        // Always go to temp enchantment slot
5164        EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5165
5166        // Enchantment will not be applied if a different one already exists
5167        if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5168            return;
5169
5170        // Apply the temporary enchantment
5171        item->SetEnchantment(slot, enchant_id, duration*1000, 0);
5172        item_owner->ApplyEnchantment(item,slot,true);
5173    }
5174}
5175
5176void Spell::EffectDisEnchant(uint32 /*i*/)
5177{
5178    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5179        return;
5180
5181    Player* p_caster = (Player*)m_caster;
5182    if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5183        return;
5184
5185    p_caster->UpdateCraftSkill(m_spellInfo->Id);
5186
5187    ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5188
5189    // item will be removed at disenchanting end
5190}
5191
5192void Spell::EffectInebriate(uint32 /*i*/)
5193{
5194    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5195        return;
5196
5197    Player *player = (Player*)unitTarget;
5198    uint16 currentDrunk = player->GetDrunkValue();
5199    uint16 drunkMod = damage * 256;
5200    if (currentDrunk + drunkMod > 0xFFFF)
5201        currentDrunk = 0xFFFF;
5202    else
5203        currentDrunk += drunkMod;
5204    player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5205}
5206
5207void Spell::EffectFeedPet(uint32 i)
5208{
5209    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5210        return;
5211
5212    Player *_player = (Player*)m_caster;
5213
5214    if(!itemTarget)
5215        return;
5216
5217    Pet *pet = _player->GetPet();
5218    if(!pet)
5219        return;
5220
5221    if(!pet->isAlive())
5222        return;
5223
5224    int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel);
5225    if(benefit <= 0)
5226        return;
5227
5228    uint32 count = 1;
5229    _player->DestroyItemCount(itemTarget,count,true);
5230    // TODO: fix crash when a spell has two effects, both pointed at the same item target
5231
5232    m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5233}
5234
5235void Spell::EffectDismissPet(uint32 /*i*/)
5236{
5237    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5238        return;
5239
5240    Pet* pet = m_caster->GetPet();
5241
5242    // not let dismiss dead pet
5243    if(!pet||!pet->isAlive())
5244        return;
5245
5246    ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5247}
5248
5249void Spell::EffectSummonObject(uint32 i)
5250{
5251    uint32 go_id = m_spellInfo->EffectMiscValue[i];
5252
5253    uint8 slot = 0;
5254    switch(m_spellInfo->Effect[i])
5255    {
5256        case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5257        case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5258        case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5259        case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5260        default: return;
5261    }
5262
5263    uint64 guid = m_caster->m_ObjectSlot[slot];
5264    if(guid != 0)
5265    {
5266        GameObject* obj = NULL;
5267        if( m_caster )
5268            obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5269
5270        if(obj) obj->Delete();
5271        m_caster->m_ObjectSlot[slot] = 0;
5272    }
5273
5274    GameObject* pGameObj = new GameObject;
5275
5276    float rot2 = sin(m_caster->GetOrientation()/2);
5277    float rot3 = cos(m_caster->GetOrientation()/2);
5278
5279    float x,y,z;
5280    // If dest location if present
5281    if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5282    {
5283        x = m_targets.m_destX;
5284        y = m_targets.m_destY;
5285        z = m_targets.m_destZ;
5286    }
5287    // Summon in random point all other units if location present
5288    else
5289        m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5290
5291    Map *map = m_caster->GetMap();
5292    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
5293    {
5294        delete pGameObj;
5295        return;
5296    }
5297
5298    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5299    int32 duration = GetSpellDuration(m_spellInfo);
5300    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5301    pGameObj->SetSpellId(m_spellInfo->Id);
5302    m_caster->AddGameObject(pGameObj);
5303
5304    map->Add(pGameObj);
5305    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5306    data << pGameObj->GetGUID();
5307    m_caster->SendMessageToSet(&data,true);
5308
5309    m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5310}
5311
5312void Spell::EffectResurrect(uint32 i)
5313{
5314    if(!unitTarget)
5315        return;
5316    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5317        return;
5318
5319    if(unitTarget->isAlive())
5320        return;
5321    if(!unitTarget->IsInWorld())
5322        return;
5323
5324    switch (m_spellInfo->Id)
5325    {
5326        // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5327        case 8342:
5328            if (roll_chance_i(67))
5329            {
5330                m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5331                return;
5332            }
5333            break;
5334        // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5335        case 22999:
5336            if (roll_chance_i(50))
5337            {
5338                m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5339                return;
5340            }
5341            break;
5342        default:
5343            break;
5344    }
5345
5346    Player* pTarget = ((Player*)unitTarget);
5347
5348    if(pTarget->isRessurectRequested())       // already have one active request
5349        return;
5350
5351    uint32 health = pTarget->GetMaxHealth() * damage / 100;
5352    uint32 mana   = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5353
5354    pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5355    SendResurrectRequest(pTarget);
5356}
5357
5358void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5359{
5360    if(!unitTarget || !unitTarget->isAlive())
5361        return;
5362
5363    if( unitTarget->m_extraAttacks )
5364        return;
5365
5366    unitTarget->m_extraAttacks = damage;
5367}
5368
5369void Spell::EffectParry(uint32 /*i*/)
5370{
5371    if (unitTarget->GetTypeId() == TYPEID_PLAYER)
5372    {
5373        ((Player*)unitTarget)->SetCanParry(true);
5374    }
5375}
5376
5377void Spell::EffectBlock(uint32 /*i*/)
5378{
5379    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
5380        return;
5381
5382    ((Player*)unitTarget)->SetCanBlock(true);
5383}
5384
5385void Spell::EffectMomentMove(uint32 i)
5386{
5387    if(unitTarget->isInFlight())
5388        return;
5389
5390    if( m_spellInfo->rangeIndex== 1)                        //self range
5391    {
5392        uint32 mapid = m_caster->GetMapId();
5393        float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5394
5395        // before caster
5396        float fx,fy,fz;
5397        unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5398        float ox,oy,oz;
5399        unitTarget->GetPosition(ox,oy,oz);
5400
5401        float fx2,fy2,fz2;                                  // getObjectHitPos overwrite last args in any result case
5402        if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5403        {
5404            fx = fx2;
5405            fy = fy2;
5406            fz = fz2;
5407            unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5408        }
5409
5410        if(unitTarget->GetTypeId() == TYPEID_PLAYER)
5411            ((Player*)unitTarget)->TeleportTo(mapid, fx, fy, fz, unitTarget->GetOrientation(), TELE_TO_NOT_LEAVE_COMBAT | TELE_TO_NOT_UNSUMMON_PET | (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5412        else
5413            MapManager::Instance().GetMap(mapid, unitTarget)->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
5414    }
5415}
5416
5417void Spell::EffectReputation(uint32 i)
5418{
5419    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5420        return;
5421
5422    Player *_player = (Player*)unitTarget;
5423
5424    int32  rep_change = m_currentBasePoints[i]+1;           // field store reputation change -1
5425
5426    uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5427
5428    FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5429
5430    if(!factionEntry)
5431        return;
5432
5433    _player->ModifyFactionReputation(factionEntry,rep_change);
5434}
5435
5436void Spell::EffectQuestComplete(uint32 i)
5437{
5438    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5439        return;
5440
5441    Player *_player = (Player*)m_caster;
5442
5443    uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5444    _player->AreaExploredOrEventHappens(quest_id);
5445}
5446
5447void Spell::EffectSelfResurrect(uint32 i)
5448{
5449    if(!unitTarget || unitTarget->isAlive())
5450        return;
5451    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5452        return;
5453    if(!unitTarget->IsInWorld())
5454        return;
5455
5456    uint32 health = 0;
5457    uint32 mana = 0;
5458
5459    // flat case
5460    if(damage < 0)
5461    {
5462        health = uint32(-damage);
5463        mana = m_spellInfo->EffectMiscValue[i];
5464    }
5465    // percent case
5466    else
5467    {
5468        health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5469        if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5470            mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5471    }
5472
5473    Player *plr = ((Player*)unitTarget);
5474    plr->ResurrectPlayer(0.0f);
5475
5476    plr->SetHealth( health );
5477    plr->SetPower(POWER_MANA, mana );
5478    plr->SetPower(POWER_RAGE, 0 );
5479    plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5480
5481    plr->SpawnCorpseBones();
5482
5483    plr->SaveToDB();
5484}
5485
5486void Spell::EffectSkinning(uint32 /*i*/)
5487{
5488    if(unitTarget->GetTypeId() != TYPEID_UNIT )
5489        return;
5490    if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5491        return;
5492
5493    Creature* creature = (Creature*) unitTarget;
5494    int32 targetLevel = creature->getLevel();
5495
5496    uint32 skill;
5497    if(creature->GetCreatureInfo()->flag1 & 256)
5498        skill = SKILL_HERBALISM;                            // special case
5499    else if(creature->GetCreatureInfo()->flag1 & 512)
5500        skill = SKILL_MINING;                               // special case
5501    else
5502        skill = SKILL_SKINNING;                             // normal case
5503
5504    ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5505    creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5506
5507    int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5508
5509    int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5510
5511    // Double chances for elites
5512    ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5513}
5514
5515void Spell::EffectCharge(uint32 /*i*/)
5516{
5517    if(!unitTarget || !m_caster)
5518        return;
5519
5520    float x, y, z;
5521    unitTarget->GetContactPoint(m_caster, x, y, z);
5522    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5523        ((Creature *)unitTarget)->StopMoving();
5524
5525    // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5526    m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5527
5528    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5529        MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5530
5531    // not all charge effects used in negative spells
5532    if ( !IsPositiveSpell(m_spellInfo->Id))
5533        m_caster->Attack(unitTarget,true);
5534}
5535
5536void Spell::EffectSummonCritter(uint32 i)
5537{
5538    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5539        return;
5540    Player* player = (Player*)m_caster;
5541
5542    uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5543    if(!pet_entry)
5544        return;
5545
5546    Pet* old_critter = player->GetMiniPet();
5547
5548    // for same pet just despawn
5549    if(old_critter && old_critter->GetEntry() == pet_entry)
5550    {
5551        player->RemoveMiniPet();
5552        return;
5553    }
5554
5555    // despawn old pet before summon new
5556    if(old_critter)
5557        player->RemoveMiniPet();
5558
5559    // summon new pet
5560    Pet* critter = new Pet(MINI_PET);
5561
5562    Map *map = m_caster->GetMap();
5563    uint32 pet_number = objmgr.GeneratePetNumber();
5564    if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),
5565        map, pet_entry, pet_number))
5566    {
5567        sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5568        delete critter;
5569        return;
5570    }
5571
5572    float x,y,z;
5573    // If dest location if present
5574    if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5575    {
5576         x = m_targets.m_destX;
5577         y = m_targets.m_destY;
5578         z = m_targets.m_destZ;
5579     }
5580     // Summon if dest location not present near caster
5581     else
5582         m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5583
5584    critter->Relocate(x,y,z,m_caster->GetOrientation());
5585
5586    if(!critter->IsPositionValid())
5587    {
5588        sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5589        delete critter;
5590        return;
5591    }
5592
5593    critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
5594    critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID());
5595    critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5596    critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5597
5598    critter->AIM_Initialize();
5599    critter->InitPetCreateSpells();                         // e.g. disgusting oozeling has a create spell as critter...
5600    critter->SetMaxHealth(1);
5601    critter->SetHealth(1);
5602    critter->SetLevel(1);
5603
5604    // set timer for unsummon
5605    int32 duration = GetSpellDuration(m_spellInfo);
5606    if(duration > 0)
5607        critter->SetDuration(duration);
5608
5609    std::string name = player->GetName();
5610    name.append(petTypeSuffix[critter->getPetType()]);
5611    critter->SetName( name );
5612    player->SetMiniPet(critter);
5613
5614    map->Add((Creature*)critter);
5615}
5616
5617void Spell::EffectKnockBack(uint32 i)
5618{
5619    if(!unitTarget || !m_caster)
5620        return;
5621
5622    // Effect only works on players
5623    if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5624        return;
5625
5626    float vsin = sin(m_caster->GetAngle(unitTarget));
5627    float vcos = cos(m_caster->GetAngle(unitTarget));
5628
5629    WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5630    data.append(unitTarget->GetPackGUID());
5631    data << uint32(0);                                      // Sequence
5632    data << float(vcos);                                    // x direction
5633    data << float(vsin);                                    // y direction
5634    data << float(m_spellInfo->EffectMiscValue[i])/10;      // Horizontal speed
5635    data << float(damage/-10);                              // Z Movement speed (vertical)
5636
5637    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5638}
5639
5640void Spell::EffectSendTaxi(uint32 i)
5641{
5642    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5643        return;
5644
5645    TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5646    if(!entry)
5647        return;
5648
5649    std::vector<uint32> nodes;
5650
5651    nodes.resize(2);
5652    nodes[0] = entry->from;
5653    nodes[1] = entry->to;
5654
5655    uint32 mountid = 0;
5656    switch(m_spellInfo->Id)
5657    {
5658        case 31606:       //Stormcrow Amulet
5659            mountid = 17447;
5660            break;
5661        case 45071:      //Quest - Sunwell Daily - Dead Scar Bombing Run
5662        case 45113:      //Quest - Sunwell Daily - Ship Bombing Run
5663        case 45353:      //Quest - Sunwell Daily - Ship Bombing Run Return
5664            mountid = 22840;
5665            break;
5666        case 34905:      //Stealth Flight
5667            mountid = 6851;
5668            break;
5669    }
5670
5671    ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
5672
5673}
5674
5675void Spell::EffectPlayerPull(uint32 i)
5676{
5677    if(!unitTarget || !m_caster)
5678        return;
5679
5680    // Effect only works on players
5681    if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5682        return;
5683
5684    float vsin = sin(unitTarget->GetAngle(m_caster));
5685    float vcos = cos(unitTarget->GetAngle(m_caster));
5686
5687    WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5688    data.append(unitTarget->GetPackGUID());
5689    data << uint32(0);                                      // Sequence
5690    data << float(vcos);                                    // x direction
5691    data << float(vsin);                                    // y direction
5692                                                            // Horizontal speed
5693    data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
5694    data << float(m_spellInfo->EffectMiscValue[i])/-10;     // Z Movement speed
5695
5696    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5697}
5698
5699void Spell::EffectDispelMechanic(uint32 i)
5700{
5701    if(!unitTarget)
5702        return;
5703
5704    uint32 mechanic = m_spellInfo->EffectMiscValue[i];
5705
5706    Unit::AuraMap& Auras = unitTarget->GetAuras();
5707    for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
5708    {
5709        next = iter;
5710        ++next;
5711        SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
5712        if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
5713        {
5714            unitTarget->RemoveAurasDueToSpell(spell->Id);
5715            if(Auras.empty())
5716                break;
5717            else
5718                next = Auras.begin();
5719        }
5720    }
5721    return;
5722}
5723
5724void Spell::EffectSummonDeadPet(uint32 /*i*/)
5725{
5726    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5727        return;
5728    Player *_player = (Player*)m_caster;
5729    Pet *pet = _player->GetPet();
5730    if(!pet)
5731        return;
5732    if(pet->isAlive())
5733        return;
5734    if(damage < 0)
5735        return;
5736    pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
5737    pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5738    pet->setDeathState( ALIVE );
5739    pet->clearUnitState(UNIT_STAT_ALL_STATE);
5740    pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
5741
5742    pet->AIM_Initialize();
5743
5744    _player->PetSpellInitialize();
5745    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
5746}
5747
5748void Spell::EffectDestroyAllTotems(uint32 /*i*/)
5749{
5750    float mana = 0;
5751    for(int slot = 0;  slot < MAX_TOTEM; ++slot)
5752    {
5753        if(!m_caster->m_TotemSlot[slot])
5754            continue;
5755
5756        Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
5757        if(totem && totem->isTotem())
5758        {
5759            uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
5760            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
5761            if(spellInfo)
5762                mana += spellInfo->manaCost * damage / 100;
5763            ((Totem*)totem)->UnSummon();
5764        }
5765    }
5766
5767    int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
5768    m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
5769}
5770
5771void Spell::EffectDurabilityDamage(uint32 i)
5772{
5773    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5774        return;
5775
5776    int32 slot = m_spellInfo->EffectMiscValue[i];
5777
5778    // FIXME: some spells effects have value -1/-2
5779    // Possibly its mean -1 all player equipped items and -2 all items
5780    if(slot < 0)
5781    {
5782        ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
5783        return;
5784    }
5785
5786    // invalid slot value
5787    if(slot >= INVENTORY_SLOT_BAG_END)
5788        return;
5789
5790    if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5791        ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
5792}
5793
5794void Spell::EffectDurabilityDamagePCT(uint32 i)
5795{
5796    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5797        return;
5798
5799    int32 slot = m_spellInfo->EffectMiscValue[i];
5800
5801    // FIXME: some spells effects have value -1/-2
5802    // Possibly its mean -1 all player equipped items and -2 all items
5803    if(slot < 0)
5804    {
5805        ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
5806        return;
5807    }
5808
5809    // invalid slot value
5810    if(slot >= INVENTORY_SLOT_BAG_END)
5811        return;
5812
5813    if(damage <= 0)
5814        return;
5815
5816    if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5817        ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
5818}
5819
5820void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
5821{
5822    if(!unitTarget)
5823        return;
5824
5825    unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
5826}
5827
5828void Spell::EffectTransmitted(uint32 effIndex)
5829{
5830    uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
5831
5832    GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
5833
5834    if (!goinfo)
5835    {
5836        sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
5837        return;
5838    }
5839
5840    float fx,fy,fz;
5841
5842    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5843    {
5844        fx = m_targets.m_destX;
5845        fy = m_targets.m_destY;
5846        fz = m_targets.m_destZ;
5847    }
5848    //FIXME: this can be better check for most objects but still hack
5849    else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
5850    {
5851        float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
5852        m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5853    }
5854    else
5855    {
5856        float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5857        float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5858        float dis = rand_norm() * (max_dis - min_dis) + min_dis;
5859
5860        m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5861    }
5862
5863    Map *cMap = m_caster->GetMap();
5864
5865    if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
5866    {
5867        if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
5868        { // but this is not proper, we really need to ignore not materialized objects
5869            SendCastResult(SPELL_FAILED_NOT_HERE);
5870            SendChannelUpdate(0);
5871            return;
5872        }
5873
5874        // replace by water level in this case
5875        fz = cMap->GetWaterLevel(fx,fy);
5876    }
5877    // if gameobject is summoning object, it should be spawned right on caster's position
5878    else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
5879    {
5880        m_caster->GetPosition(fx,fy,fz);
5881    }
5882
5883    GameObject* pGameObj = new GameObject;
5884
5885    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
5886        fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
5887    {
5888        delete pGameObj;
5889        return;
5890    }
5891
5892    int32 duration = GetSpellDuration(m_spellInfo);
5893
5894    switch(goinfo->type)
5895    {
5896        case GAMEOBJECT_TYPE_FISHINGNODE:
5897        {
5898            m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
5899                                                            // Orientation3
5900            pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 );
5901                                                            // Orientation4
5902            pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 );
5903            m_caster->AddGameObject(pGameObj);              // will removed at spell cancel
5904
5905            // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
5906            // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
5907            int32 lastSec;
5908            switch(urand(0, 3))
5909            {
5910                case 0: lastSec =  3; break;
5911                case 1: lastSec =  7; break;
5912                case 2: lastSec = 13; break;
5913                case 3: lastSec = 17; break;
5914            }
5915
5916            duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000;
5917            break;
5918        }
5919        case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
5920        {
5921            if(m_caster->GetTypeId()==TYPEID_PLAYER)
5922            {
5923                pGameObj->AddUniqueUse((Player*)m_caster);
5924                m_caster->AddGameObject(pGameObj);          // will removed at spell cancel
5925            }
5926            break;
5927        }
5928        case GAMEOBJECT_TYPE_FISHINGHOLE:
5929        case GAMEOBJECT_TYPE_CHEST:
5930        default:
5931        {
5932            break;
5933        }
5934    }
5935
5936    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5937
5938    pGameObj->SetOwnerGUID(m_caster->GetGUID() );
5939
5940    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
5941    pGameObj->SetSpellId(m_spellInfo->Id);
5942
5943    DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
5944    //m_caster->AddGameObject(pGameObj);
5945    //m_ObjToDel.push_back(pGameObj);
5946
5947    cMap->Add(pGameObj);
5948
5949    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5950    data << uint64(pGameObj->GetGUID());
5951    m_caster->SendMessageToSet(&data,true);
5952
5953    if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
5954    {
5955        GameObject* linkedGO = new GameObject;
5956        if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
5957            fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
5958        {
5959            linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5960            linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
5961            linkedGO->SetSpellId(m_spellInfo->Id);
5962            linkedGO->SetOwnerGUID(m_caster->GetGUID() );
5963
5964            MapManager::Instance().GetMap(linkedGO->GetMapId(), linkedGO)->Add(linkedGO);
5965        }
5966        else
5967        {
5968            delete linkedGO;
5969            linkedGO = NULL;
5970            return;
5971        }
5972    }
5973}
5974
5975void Spell::EffectProspecting(uint32 /*i*/)
5976{
5977    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5978        return;
5979
5980    Player* p_caster = (Player*)m_caster;
5981    if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
5982        return;
5983
5984    if(itemTarget->GetCount() < 5)
5985        return;
5986
5987    if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
5988    {
5989        uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
5990        uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
5991        p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
5992    }
5993
5994    ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
5995}
5996
5997void Spell::EffectSkill(uint32 /*i*/)
5998{
5999    sLog.outDebug("WORLD: SkillEFFECT");
6000}
6001
6002void Spell::EffectSummonDemon(uint32 i)
6003{
6004    float px = m_targets.m_destX;
6005    float py = m_targets.m_destY;
6006    float pz = m_targets.m_destZ;
6007
6008    Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000);
6009    if (!Charmed)
6010        return;
6011
6012    // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6013    Charmed->SetLevel(m_caster->getLevel());
6014
6015    // TODO: Add damage/mana/hp according to level
6016
6017    if (m_spellInfo->EffectMiscValue[i] == 89)              // Inferno summon
6018    {
6019        // Enslave demon effect, without mana cost and cooldown
6020        m_caster->CastSpell(Charmed, 20882, true);          // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6021
6022        // Inferno effect
6023        Charmed->CastSpell(Charmed, 22703, true, 0);
6024    }
6025}
6026
6027/* There is currently no need for this effect. We handle it in BattleGround.cpp
6028   If we would handle the resurrection here, the spiritguide would instantly disappear as the
6029   player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6030   This is why we use a half sec delay between the visual effect and the resurrection itself */
6031void Spell::EffectSpiritHeal(uint32 /*i*/)
6032{
6033    /*
6034    if(!unitTarget || unitTarget->isAlive())
6035        return;
6036    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6037        return;
6038    if(!unitTarget->IsInWorld())
6039        return;
6040
6041    //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6042    //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6043    ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6044    ((Player*)unitTarget)->SpawnCorpseBones();
6045    */
6046}
6047
6048// remove insignia spell effect
6049void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6050{
6051    sLog.outDebug("Effect: SkinPlayerCorpse");
6052    if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6053        return;
6054
6055    ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6056}
6057
6058void Spell::EffectStealBeneficialBuff(uint32 i)
6059{
6060    sLog.outDebug("Effect: StealBeneficialBuff");
6061
6062    if(!unitTarget || unitTarget==m_caster)                 // can't steal from self
6063        return;
6064
6065    std::vector <Aura *> steal_list;
6066    // Create dispel mask by dispel type
6067    uint32 dispelMask  = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6068    Unit::AuraMap const& auras = unitTarget->GetAuras();
6069    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6070    {
6071        Aura *aur = (*itr).second;
6072        if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6073        {
6074            // Need check for passive? this
6075            if (aur->IsPositive() && !aur->IsPassive())
6076                steal_list.push_back(aur);
6077        }
6078    }
6079    // Ok if exist some buffs for dispel try dispel it
6080    if (!steal_list.empty())
6081    {
6082        std::list < std::pair<uint32,uint64> > success_list;
6083        int32 list_size = steal_list.size();
6084        // Dispell N = damage buffs (or while exist buffs for dispel)
6085        for (int32 count=0; count < damage && list_size > 0; ++count)
6086        {
6087            // Random select buff for dispel
6088            Aura *aur = steal_list[urand(0, list_size-1)];
6089            // Not use chance for steal
6090            // TODO possible need do it
6091            success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6092
6093            // Remove buff from list for prevent doubles
6094            for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6095            {
6096                Aura *stealed = *j;
6097                if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6098                {
6099                    j = steal_list.erase(j);
6100                    --list_size;
6101                }
6102                else
6103                    ++j;
6104            }
6105        }
6106        // Really try steal and send log
6107        if (!success_list.empty())
6108        {
6109            int32 count = success_list.size();
6110            WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6111            data.append(unitTarget->GetPackGUID());  // Victim GUID
6112            data.append(m_caster->GetPackGUID());    // Caster GUID
6113            data << uint32(m_spellInfo->Id);         // Dispell spell id
6114            data << uint8(0);                        // not used
6115            data << uint32(count);                   // count
6116            for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6117            {
6118                SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6119                data << uint32(spellInfo->Id);       // Spell Id
6120                data << uint8(0);                    // 0 - steals !=0 transfers
6121                unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6122            }
6123            m_caster->SendMessageToSet(&data, true);
6124        }
6125    }
6126}
6127
6128void Spell::EffectKillCredit(uint32 i)
6129{
6130    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6131        return;
6132
6133    ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0);
6134}
6135
6136void Spell::EffectQuestFail(uint32 i)
6137{
6138    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6139        return;
6140
6141    ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6142}
Note: See TracBrowser for help on using the browser.