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

Revision 106, 237.0 kB (checked in by yumileroy, 17 years ago)

[svn] Fix a crash caused by gruul script.
Change in EffectSummonWild? and DoZoneInCombat?.

Original author: megamage
Date: 2008-10-24 17:37:40-05:00

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