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

Revision 110, 236.5 kB (checked in by yumileroy, 17 years ago)

[svn] Add SpellExtraInfoMap?. Currently support:
Limited-number-of-players spell; shared damage spell; target-in-line cone spell (e.g. dark glare).
Change angle of cone spells from 120 degree to 60 degree.

Original author: megamage
Date: 2008-10-25 15:46:52-05:00

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