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

Revision 105, 236.9 kB (checked in by yumileroy, 17 years ago)

[svn] Fix cloak of shadow, can remove fairy fire now.
Add yells to High King Maulgar. Patch provided by riddick.
Script for Prince Malchezaar Doors. Patch provided by BroodWyrm?.
Bug fix for Selin Fireheart. Patch provided by BroodWyrm?.
Arcane Charges only while on flightpath. Patch provided by SLG.

Original author: megamage
Date: 2008-10-23 22:04:14-05:00

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