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

Revision 214, 240.0 kB (checked in by yumileroy, 17 years ago)

[svn] Fix a bug that tame beast may crash server.

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