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

Revision 53, 237.4 kB (checked in by yumileroy, 17 years ago)

[svn] Merge branch r50 with trunk.

Original author: megamage
Date: 2008-10-17 21:44:37-05:00

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