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

Revision 9, 241.1 kB (checked in by yumileroy, 17 years ago)

[svn] -enabled instantiated battlegrounds
-enabled arena matches
-rewritten battleground queuing to support joining as group
-removed queue announcements

Original author: w12x
Date: 2008-10-05 08:48:32-05:00

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