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

Revision 57, 236.8 kB (checked in by yumileroy, 17 years ago)

[svn] Update some Black Temple boss scripts.
Implement some Black Temple boss spells.
Update maiden of virtue and void reaver scripts. Patch provided by Blaymoira.

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