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

Revision 180, 239.9 kB (checked in by yumileroy, 17 years ago)

[svn] Fix hunter's trap (let original caster summon dynamic object).
Fix black temple boss 1's hurl spine.

Original author: megamage
Date: 2008-11-06 12:24: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.GetSpellExtraAttr(m_spellInfo->Id, SPELL_EXTRA_ATTR_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: triggering unknown spell id %effect_idx", m_spellInfo->Id,triggered_spell_id);
1954        return;
1955    }
1956
1957    if (m_CastItem)
1958        DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1959
1960    Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID );
1961
1962    SpellCastTargets targets;
1963    targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ);
1964    spell->m_CastItem = m_CastItem;
1965    spell->prepare(&targets, NULL);
1966}
1967
1968void Spell::EffectTeleportUnits(uint32 i)
1969{
1970    if(!unitTarget || unitTarget->isInFlight())
1971        return;
1972
1973    // If not exist data for dest location - return
1974    if(!m_targets.HasDest())
1975    {
1976        sLog.outError( "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id );
1977        return;
1978    }
1979    // Init dest coordinates
1980    int32 mapid = m_targets.m_mapId;
1981    if(mapid < 0) mapid = (int32)unitTarget->GetMapId();
1982    float x = m_targets.m_destX;
1983    float y = m_targets.m_destY;
1984    float z = m_targets.m_destZ;
1985    float orientation = unitTarget->GetOrientation();
1986    sLog.outDebug("Spell::EffectTeleportUnits - teleport unit to %u %f %f %f\n", mapid, x, y, z);
1987    // Teleport
1988    if(unitTarget->GetTypeId() == TYPEID_PLAYER)
1989        ((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));
1990    else
1991    {
1992        MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)unitTarget, x, y, z, orientation);
1993        WorldPacket data;
1994        unitTarget->BuildTeleportAckMsg(&data, x, y, z, orientation);
1995        unitTarget->SendMessageToSet(&data, false);
1996    }
1997
1998    // post effects for TARGET_TABLE_X_Y_Z_COORDINATES
1999    switch ( m_spellInfo->Id )
2000    {
2001        // Dimensional Ripper - Everlook
2002        case 23442:
2003        {
2004            int32 r = irand(0, 119);
2005            if ( r >= 70 )                                  // 7/12 success
2006            {
2007                if ( r < 100 )                              // 4/12 evil twin
2008                    m_caster->CastSpell(m_caster,23445,true);
2009                else                                        // 1/12 fire
2010                    m_caster->CastSpell(m_caster,23449,true);
2011            }
2012            return;
2013        }
2014        // Ultrasafe Transporter: Toshley's Station
2015        case 36941:
2016        {
2017            if ( roll_chance_i(50) )                        // 50% success
2018            {
2019                int32 rand_eff = urand(1,7);
2020                switch ( rand_eff )
2021                {
2022                    case 1:
2023                        // soul split - evil
2024                        m_caster->CastSpell(m_caster,36900,true);
2025                        break;
2026                    case 2:
2027                        // soul split - good
2028                        m_caster->CastSpell(m_caster,36901,true);
2029                        break;
2030                    case 3:
2031                        // Increase the size
2032                        m_caster->CastSpell(m_caster,36895,true);
2033                        break;
2034                    case 4:
2035                        // Decrease the size
2036                        m_caster->CastSpell(m_caster,36893,true);
2037                        break;
2038                    case 5:
2039                    // Transform
2040                    {
2041                        if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2042                            m_caster->CastSpell(m_caster,36897,true);
2043                        else
2044                            m_caster->CastSpell(m_caster,36899,true);
2045                        break;
2046                    }
2047                    case 6:
2048                        // chicken
2049                        m_caster->CastSpell(m_caster,36940,true);
2050                        break;
2051                    case 7:
2052                        // evil twin
2053                        m_caster->CastSpell(m_caster,23445,true);
2054                        break;
2055                }
2056            }
2057            return;
2058        }
2059        // Dimensional Ripper - Area 52
2060        case 36890:
2061        {
2062            if ( roll_chance_i(50) )                        // 50% success
2063            {
2064                int32 rand_eff = urand(1,4);
2065                switch ( rand_eff )
2066                {
2067                    case 1:
2068                        // soul split - evil
2069                        m_caster->CastSpell(m_caster,36900,true);
2070                        break;
2071                    case 2:
2072                        // soul split - good
2073                        m_caster->CastSpell(m_caster,36901,true);
2074                        break;
2075                    case 3:
2076                        // Increase the size
2077                        m_caster->CastSpell(m_caster,36895,true);
2078                        break;
2079                    case 4:
2080                    // Transform
2081                    {
2082                        if (((Player*)m_caster)->GetTeam() == ALLIANCE )
2083                            m_caster->CastSpell(m_caster,36897,true);
2084                        else
2085                            m_caster->CastSpell(m_caster,36899,true);
2086                        break;
2087                    }
2088                }
2089            }
2090            return;
2091        }
2092    }
2093}
2094
2095void Spell::EffectApplyAura(uint32 i)
2096{
2097    if(!unitTarget)
2098        return;
2099
2100    SpellImmuneList const& list = unitTarget->m_spellImmune[IMMUNITY_STATE];
2101    for(SpellImmuneList::const_iterator itr = list.begin(); itr != list.end(); ++itr)
2102        if(itr->type == m_spellInfo->EffectApplyAuraName[i])
2103            return;
2104
2105    // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load)
2106    if( !unitTarget->isAlive() && m_spellInfo->Id != 20584 && m_spellInfo->Id != 8326 &&
2107        (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) )
2108        return;
2109
2110    Unit* caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2111    if(!caster)
2112        return;
2113
2114    sLog.outDebug("Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[i]);
2115
2116    Aura* Aur = CreateAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, caster, m_CastItem);
2117
2118    // Now Reduce spell duration using data received at spell hit
2119    int32 duration = Aur->GetAuraMaxDuration();
2120    unitTarget->ApplyDiminishingToDuration(m_diminishGroup,duration,caster,m_diminishLevel);
2121    Aur->setDiminishGroup(m_diminishGroup);
2122
2123    // if Aura removed and deleted, do not continue.
2124    if(duration== 0 && !(Aur->IsPermanent()))
2125    {
2126        delete Aur;
2127        return;
2128    }
2129
2130    if(duration != Aur->GetAuraMaxDuration())
2131    {
2132        Aur->SetAuraMaxDuration(duration);
2133        Aur->SetAuraDuration(duration);
2134    }
2135
2136    bool added = unitTarget->AddAura(Aur);
2137
2138    // Aura not added and deleted in AddAura call;
2139    if (!added)
2140        return;
2141
2142    // found crash at character loading, broken pointer to Aur...
2143    // Aur was deleted in AddAura()...
2144    if(!Aur)
2145        return;
2146
2147    // TODO Make a way so it works for every related spell!
2148    if(unitTarget->GetTypeId()==TYPEID_PLAYER)              // Negative buff should only be applied on players
2149    {
2150        uint32 spellId = 0;
2151        if(m_spellInfo->CasterAuraStateNot==AURA_STATE_WEAKENED_SOUL || m_spellInfo->TargetAuraStateNot==AURA_STATE_WEAKENED_SOUL)
2152            spellId = 6788;                                 // Weakened Soul
2153        else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_FORBEARANCE || m_spellInfo->TargetAuraStateNot==AURA_STATE_FORBEARANCE)
2154            spellId = 25771;                                // Forbearance
2155        else if(m_spellInfo->CasterAuraStateNot==AURA_STATE_HYPOTHERMIA)
2156            spellId = 41425;                                // Hypothermia
2157        else if (m_spellInfo->Mechanic == MECHANIC_BANDAGE) // Bandages
2158            spellId = 11196;                                // Recently Bandaged
2159        else if( (m_spellInfo->AttributesEx & 0x20) && (m_spellInfo->AttributesEx2 & 0x20000) )
2160            spellId = 23230;                                // Blood Fury - Healing Reduction
2161
2162        SpellEntry const *AdditionalSpellInfo = sSpellStore.LookupEntry(spellId);
2163        if (AdditionalSpellInfo)
2164        {
2165            // applied at target by target
2166            Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, 0, &m_currentBasePoints[0], unitTarget,unitTarget, 0);
2167            unitTarget->AddAura(AdditionalAura);
2168            sLog.outDebug("Spell: Additional Aura is: %u", AdditionalSpellInfo->EffectApplyAuraName[0]);
2169        }
2170    }
2171
2172    // Prayer of Mending (jump animation), we need formal caster instead original for correct animation
2173    if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST && (m_spellInfo->SpellFamilyFlags & 0x00002000000000LL))
2174        m_caster->CastSpell(unitTarget,41637,true,NULL,Aur);
2175}
2176
2177void Spell::EffectUnlearnSpecialization( uint32 i )
2178{
2179    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2180        return;
2181
2182    Player *_player = (Player*)unitTarget;
2183    uint32 spellToUnlearn = m_spellInfo->EffectTriggerSpell[i];
2184
2185    _player->removeSpell(spellToUnlearn);
2186
2187    sLog.outDebug( "Spell: Player %u have unlearned spell %u from NpcGUID: %u", _player->GetGUIDLow(), spellToUnlearn, m_caster->GetGUIDLow() );
2188}
2189
2190void Spell::EffectPowerDrain(uint32 i)
2191{
2192    if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2193        return;
2194
2195    Powers drain_power = Powers(m_spellInfo->EffectMiscValue[i]);
2196
2197    if(!unitTarget)
2198        return;
2199    if(!unitTarget->isAlive())
2200        return;
2201    if(unitTarget->getPowerType() != drain_power)
2202        return;
2203    if(damage < 0)
2204        return;
2205
2206    uint32 curPower = unitTarget->GetPower(drain_power);
2207
2208    //add spell damage bonus
2209    damage=m_caster->SpellDamageBonus(unitTarget,m_spellInfo,uint32(damage),SPELL_DIRECT_DAMAGE);
2210
2211    // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2212    uint32 power = damage;
2213    if ( drain_power == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2214        power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2215
2216    int32 new_damage;
2217    if(curPower < power)
2218        new_damage = curPower;
2219    else
2220        new_damage = power;
2221
2222    unitTarget->ModifyPower(drain_power,-new_damage);
2223
2224    if(drain_power == POWER_MANA)
2225    {
2226        float manaMultiplier = m_spellInfo->EffectMultipleValue[i];
2227        if(manaMultiplier==0)
2228            manaMultiplier = 1;
2229
2230        if(Player *modOwner = m_caster->GetSpellModOwner())
2231            modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, manaMultiplier);
2232
2233        int32 gain = int32(new_damage*manaMultiplier);
2234
2235        m_caster->ModifyPower(POWER_MANA,gain);
2236        //send log
2237        m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id,gain,POWER_MANA,false);
2238    }
2239}
2240
2241void Spell::EffectSendEvent(uint32 EffectIndex)
2242{
2243    if (m_caster->GetTypeId() == TYPEID_PLAYER && ((Player*)m_caster)->InBattleGround())
2244    {
2245        BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
2246        if(bg && bg->GetStatus() == STATUS_IN_PROGRESS)
2247        {
2248            switch(m_spellInfo->Id)
2249            {
2250                case 23333:                                 // Pickup Horde Flag
2251                    /*do not uncomment .
2252                    if(bg->GetTypeID()==BATTLEGROUND_WS)
2253                        bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2254                    sLog.outDebug("Send Event Horde Flag Picked Up");
2255                    break;
2256                    /* not used :
2257                    case 23334:                                 // Drop Horde Flag
2258                        if(bg->GetTypeID()==BATTLEGROUND_WS)
2259                            bg->EventPlayerDroppedFlag((Player*)m_caster);
2260                        sLog.outDebug("Drop Horde Flag");
2261                        break;
2262                    */
2263                case 23335:                                 // Pickup Alliance Flag
2264                    /*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
2265                    if(bg->GetTypeID()==BATTLEGROUND_WS)
2266                        bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2267                    sLog.outDebug("Send Event Alliance Flag Picked Up");
2268                    break;
2269                    /* not used :
2270                    case 23336:                                 // Drop Alliance Flag
2271                        if(bg->GetTypeID()==BATTLEGROUND_WS)
2272                            bg->EventPlayerDroppedFlag((Player*)m_caster);
2273                        sLog.outDebug("Drop Alliance Flag");
2274                        break;
2275                    case 23385:                                 // Alliance Flag Returns
2276                        if(bg->GetTypeID()==BATTLEGROUND_WS)
2277                            bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2278                        sLog.outDebug("Alliance Flag Returned");
2279                        break;
2280                    case 23386:                                   // Horde Flag Returns
2281                        if(bg->GetTypeID()==BATTLEGROUND_WS)
2282                            bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2283                        sLog.outDebug("Horde Flag Returned");
2284                        break;*/
2285                case 34976:
2286                    /*
2287                    if(bg->GetTypeID()==BATTLEGROUND_EY)
2288                        bg->EventPlayerClickedOnFlag((Player*)m_caster, this->gameObjTarget);
2289                    */
2290                    break;
2291                default:
2292                    sLog.outDebug("Unknown spellid %u in BG event", m_spellInfo->Id);
2293                    break;
2294            }
2295        }
2296    }
2297    sLog.outDebug("Spell ScriptStart %u for spellid %u in EffectSendEvent ", m_spellInfo->EffectMiscValue[EffectIndex], m_spellInfo->Id);
2298    sWorld.ScriptsStart(sEventScripts, m_spellInfo->EffectMiscValue[EffectIndex], m_caster, focusObject);
2299}
2300
2301void Spell::EffectPowerBurn(uint32 i)
2302{
2303    if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2304        return;
2305
2306    Powers powertype = Powers(m_spellInfo->EffectMiscValue[i]);
2307
2308    if(!unitTarget)
2309        return;
2310    if(!unitTarget->isAlive())
2311        return;
2312    if(unitTarget->getPowerType()!=powertype)
2313        return;
2314    if(damage < 0)
2315        return;
2316
2317    int32 curPower = int32(unitTarget->GetPower(powertype));
2318
2319    // resilience reduce mana draining effect at spell crit damage reduction (added in 2.4)
2320    uint32 power = damage;
2321    if ( powertype == POWER_MANA && unitTarget->GetTypeId() == TYPEID_PLAYER )
2322        power -= ((Player*)unitTarget)->GetSpellCritDamageReduction(power);
2323
2324    int32 new_damage = (curPower < power) ? curPower : power;
2325
2326    unitTarget->ModifyPower(powertype,-new_damage);
2327    float multiplier = m_spellInfo->EffectMultipleValue[i];
2328
2329    if(Player *modOwner = m_caster->GetSpellModOwner())
2330        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2331
2332    new_damage = int32(new_damage*multiplier);
2333    m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2334}
2335
2336void Spell::EffectHeal( uint32 /*i*/ )
2337{
2338    if( unitTarget && unitTarget->isAlive() && damage >= 0)
2339    {
2340        // Try to get original caster
2341        Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2342
2343        // Skip if m_originalCaster not available
2344        if (!caster)
2345            return;
2346
2347        int32 addhealth = damage;
2348
2349        // Vessel of the Naaru (Vial of the Sunwell trinket)
2350        if (m_spellInfo->Id == 45064)
2351        {
2352            // Amount of heal - depends from stacked Holy Energy
2353            int damageAmount = 0;
2354            Unit::AuraList const& mDummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
2355            for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
2356                if((*i)->GetId() == 45062)
2357                    damageAmount+=(*i)->GetModifier()->m_amount;
2358            if (damageAmount)
2359                m_caster->RemoveAurasDueToSpell(45062);
2360
2361            addhealth += damageAmount;
2362        }
2363        // Swiftmend - consumes Regrowth or Rejuvenation
2364        else if (m_spellInfo->TargetAuraState == AURA_STATE_SWIFTMEND && unitTarget->HasAuraState(AURA_STATE_SWIFTMEND))
2365        {
2366            Unit::AuraList const& RejorRegr = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_HEAL);
2367            // find most short by duration
2368            Aura *targetAura = NULL;
2369            for(Unit::AuraList::const_iterator i = RejorRegr.begin(); i != RejorRegr.end(); ++i)
2370            {
2371                if((*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_DRUID
2372                    && ((*i)->GetSpellProto()->SpellFamilyFlags == 0x40 || (*i)->GetSpellProto()->SpellFamilyFlags == 0x10) )
2373                {
2374                    if(!targetAura || (*i)->GetAuraDuration() < targetAura->GetAuraDuration())
2375                        targetAura = *i;
2376                }
2377            }
2378
2379            if(!targetAura)
2380            {
2381                sLog.outError("Target(GUID:" I64FMTD ") has aurastate AURA_STATE_SWIFTMEND but no matching aura.", unitTarget->GetGUID());
2382                return;
2383            }
2384            int idx = 0;
2385            while(idx < 3)
2386            {
2387                if(targetAura->GetSpellProto()->EffectApplyAuraName[idx] == SPELL_AURA_PERIODIC_HEAL)
2388                    break;
2389                idx++;
2390            }
2391
2392            int32 tickheal = caster->SpellHealingBonus(targetAura->GetSpellProto(), targetAura->GetModifier()->m_amount, DOT, unitTarget);
2393            int32 tickcount = GetSpellDuration(targetAura->GetSpellProto()) / targetAura->GetSpellProto()->EffectAmplitude[idx];
2394            unitTarget->RemoveAurasDueToSpell(targetAura->GetId());
2395
2396            addhealth += tickheal * tickcount;
2397        }
2398        else
2399            addhealth = caster->SpellHealingBonus(m_spellInfo, addhealth,HEAL, unitTarget);
2400
2401        bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask, m_attackType);
2402        if (crit)
2403            addhealth = caster->SpellCriticalBonus(m_spellInfo, addhealth, unitTarget);
2404        caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, crit);
2405
2406        int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2407        unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2408
2409        if(caster->GetTypeId()==TYPEID_PLAYER)
2410            if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2411                bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2412
2413        // ignore item heals
2414        if(m_CastItem)
2415            return;
2416
2417        uint32 procHealer = PROC_FLAG_HEAL;
2418        if (crit)
2419            procHealer |= PROC_FLAG_CRIT_HEAL;
2420
2421        m_caster->ProcDamageAndSpell(unitTarget,procHealer,PROC_FLAG_HEALED,addhealth,SPELL_SCHOOL_MASK_NONE,m_spellInfo,m_IsTriggeredSpell);
2422    }
2423}
2424
2425void Spell::EffectHealPct( uint32 /*i*/ )
2426{
2427    if( unitTarget && unitTarget->isAlive() && damage >= 0)
2428    {
2429        // Try to get original caster
2430        Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2431
2432        // Skip if m_originalCaster not available
2433        if (!caster)
2434            return;
2435
2436        uint32 addhealth = unitTarget->GetMaxHealth() * damage / 100;
2437        caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2438
2439        int32 gain = unitTarget->ModifyHealth( int32(addhealth) );
2440        unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
2441
2442        if(caster->GetTypeId()==TYPEID_PLAYER)
2443            if(BattleGround *bg = ((Player*)caster)->GetBattleGround())
2444                bg->UpdatePlayerScore(((Player*)caster), SCORE_HEALING_DONE, gain);
2445    }
2446}
2447
2448void Spell::EffectHealMechanical( uint32 /*i*/ )
2449{
2450    // Mechanic creature type should be correctly checked by targetCreatureType field
2451    if( unitTarget && unitTarget->isAlive() && damage >= 0)
2452    {
2453        // Try to get original caster
2454        Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2455
2456        // Skip if m_originalCaster not available
2457        if (!caster)
2458            return;
2459
2460        uint32 addhealth = caster->SpellHealingBonus(m_spellInfo, uint32(damage), HEAL, unitTarget);
2461        caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, false);
2462        unitTarget->ModifyHealth( int32(damage) );
2463    }
2464}
2465
2466void Spell::EffectHealthLeech(uint32 i)
2467{
2468    if(!unitTarget)
2469        return;
2470    if(!unitTarget->isAlive())
2471        return;
2472
2473    if(damage < 0)
2474        return;
2475
2476    sLog.outDebug("HealthLeech :%i", damage);
2477
2478    float multiplier = m_spellInfo->EffectMultipleValue[i];
2479
2480    if(Player *modOwner = m_caster->GetSpellModOwner())
2481        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_MULTIPLE_VALUE, multiplier);
2482
2483    int32 new_damage = int32(damage*multiplier);
2484    uint32 curHealth = unitTarget->GetHealth();
2485    new_damage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, new_damage, m_IsTriggeredSpell, true);
2486    if(curHealth < new_damage)
2487        new_damage = curHealth;
2488
2489    if(m_caster->isAlive())
2490    {
2491        new_damage = m_caster->SpellHealingBonus(m_spellInfo, new_damage, HEAL, m_caster);
2492
2493        m_caster->ModifyHealth(new_damage);
2494
2495        if(m_caster->GetTypeId() == TYPEID_PLAYER)
2496            m_caster->SendHealSpellLog(m_caster, m_spellInfo->Id, uint32(new_damage));
2497    }
2498}
2499
2500void Spell::DoCreateItem(uint32 i, uint32 itemtype)
2501{
2502    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
2503        return;
2504
2505    Player* player = (Player*)unitTarget;
2506
2507    uint32 newitemid = itemtype;
2508    ItemPrototype const *pProto = objmgr.GetItemPrototype( newitemid );
2509    if(!pProto)
2510    {
2511        player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2512        return;
2513    }
2514
2515    uint32 num_to_add;
2516
2517    // TODO: maybe all this can be replaced by using correct calculated `damage` value
2518    if(pProto->Class != ITEM_CLASS_CONSUMABLE || m_spellInfo->SpellFamilyName != SPELLFAMILY_MAGE)
2519    {
2520        int32 basePoints = m_currentBasePoints[i];
2521        int32 randomPoints = m_spellInfo->EffectDieSides[i];
2522        if (randomPoints)
2523            num_to_add = basePoints + irand(1, randomPoints);
2524        else
2525            num_to_add = basePoints + 1;
2526    }
2527    else if (pProto->MaxCount == 1)
2528        num_to_add = 1;
2529    else if(player->getLevel() >= m_spellInfo->spellLevel)
2530    {
2531        int32 basePoints = m_currentBasePoints[i];
2532        float pointPerLevel = m_spellInfo->EffectRealPointsPerLevel[i];
2533        num_to_add = basePoints + 1 + uint32((player->getLevel() - m_spellInfo->spellLevel)*pointPerLevel);
2534    }
2535    else
2536        num_to_add = 2;
2537
2538    if (num_to_add < 1)
2539        num_to_add = 1;
2540    if (num_to_add > pProto->Stackable)
2541        num_to_add = pProto->Stackable;
2542
2543    // init items_count to 1, since 1 item will be created regardless of specialization
2544    int items_count=1;
2545    // the chance to create additional items
2546    float additionalCreateChance=0.0f;
2547    // the maximum number of created additional items
2548    uint8 additionalMaxNum=0;
2549    // get the chance and maximum number for creating extra items
2550    if ( canCreateExtraItems(player, m_spellInfo->Id, additionalCreateChance, additionalMaxNum) )
2551    {
2552        // roll with this chance till we roll not to create or we create the max num
2553        while ( roll_chance_f(additionalCreateChance) && items_count<=additionalMaxNum )
2554            ++items_count;
2555    }
2556
2557    // really will be created more items
2558    num_to_add *= items_count;
2559
2560    // can the player store the new item?
2561    ItemPosCountVec dest;
2562    uint32 no_space = 0;
2563    uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, num_to_add, &no_space );
2564    if( msg != EQUIP_ERR_OK )
2565    {
2566        // convert to possible store amount
2567        if( msg == EQUIP_ERR_INVENTORY_FULL || msg == EQUIP_ERR_CANT_CARRY_MORE_OF_THIS )
2568            num_to_add -= no_space;
2569        else
2570        {
2571            // if not created by another reason from full inventory or unique items amount limitation
2572            player->SendEquipError( msg, NULL, NULL );
2573            return;
2574        }
2575    }
2576
2577    if(num_to_add)
2578    {
2579        // create the new item and store it
2580        Item* pItem = player->StoreNewItem( dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
2581
2582        // was it successful? return error if not
2583        if(!pItem)
2584        {
2585            player->SendEquipError( EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL );
2586            return;
2587        }
2588
2589        // set the "Crafted by ..." property of the item
2590        if( pItem->GetProto()->Class != ITEM_CLASS_CONSUMABLE && pItem->GetProto()->Class != ITEM_CLASS_QUEST)
2591            pItem->SetUInt32Value(ITEM_FIELD_CREATOR,player->GetGUIDLow());
2592
2593        // send info to the client
2594        if(pItem)
2595            player->SendNewItem(pItem, num_to_add, true, true);
2596
2597        // we succeeded in creating at least one item, so a levelup is possible
2598        player->UpdateCraftSkill(m_spellInfo->Id);
2599    }
2600
2601    // for battleground marks send by mail if not add all expected
2602    if(no_space > 0 )
2603    {
2604        BattleGroundTypeId bgType;
2605        switch(m_spellInfo->Id)
2606        {
2607            case SPELL_AV_MARK_WINNER:
2608            case SPELL_AV_MARK_LOSER:
2609                bgType = BATTLEGROUND_AV;
2610                break;
2611            case SPELL_WS_MARK_WINNER:
2612            case SPELL_WS_MARK_LOSER:
2613                bgType = BATTLEGROUND_WS;
2614                break;
2615            case SPELL_AB_MARK_WINNER:
2616            case SPELL_AB_MARK_LOSER:
2617                bgType = BATTLEGROUND_AB;
2618                break;
2619            default:
2620                return;
2621        }
2622
2623        if(BattleGround* bg = sBattleGroundMgr.GetBattleGroundTemplate(bgType))
2624            bg->SendRewardMarkByMail(player,newitemid,no_space);
2625    }
2626}
2627
2628void Spell::EffectCreateItem(uint32 i)
2629{
2630    DoCreateItem(i,m_spellInfo->EffectItemType[i]);
2631}
2632
2633void Spell::EffectPersistentAA(uint32 i)
2634{
2635    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2636    Unit *caster = m_originalCasterGUID ? m_originalCaster : m_caster;
2637
2638    if(Player* modOwner = caster->GetSpellModOwner())
2639        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius);
2640
2641    int32 duration = GetSpellDuration(m_spellInfo);
2642    DynamicObject* dynObj = new DynamicObject;
2643    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))
2644    {
2645        delete dynObj;
2646        return;
2647    }
2648    dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
2649    dynObj->SetUInt32Value(GAMEOBJECT_DISPLAYID, 368003);
2650    dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x01eeeeee);
2651    caster->AddDynObject(dynObj);
2652    MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj);
2653}
2654
2655void Spell::EffectEnergize(uint32 i)
2656{
2657    if(!unitTarget)
2658        return;
2659    if(!unitTarget->isAlive())
2660        return;
2661
2662    if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2663        return;
2664
2665    // Some level depends spells
2666    int multipler  = 0;
2667    int level_diff = 0;
2668    switch (m_spellInfo->Id)
2669    {
2670        // Restore Energy
2671        case 9512:
2672            level_diff = m_caster->getLevel() - 40;
2673            multipler  = 2;
2674            break;
2675        // Blood Fury
2676        case 24571:
2677            level_diff = m_caster->getLevel() - 60;
2678            multipler  = 10;
2679            break;
2680        // Burst of Energy
2681        case 24532:
2682            level_diff = m_caster->getLevel() - 60;
2683            multipler  = 4;
2684            break;
2685        default:
2686            break;
2687    }
2688
2689    if (level_diff > 0)
2690        damage -= multipler * level_diff;
2691
2692    if(damage < 0)
2693        return;
2694
2695    Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2696
2697    if(unitTarget->GetMaxPower(power) == 0)
2698        return;
2699
2700    unitTarget->ModifyPower(power,damage);
2701    m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2702
2703    // Mad Alchemist's Potion
2704    if (m_spellInfo->Id == 45051)
2705    {
2706        // find elixirs on target
2707        uint32 elixir_mask = 0;
2708        Unit::AuraMap& Auras = unitTarget->GetAuras();
2709        for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
2710        {
2711            uint32 spell_id = itr->second->GetId();
2712            if(uint32 mask = spellmgr.GetSpellElixirMask(spell_id))
2713                elixir_mask |= mask;
2714        }
2715
2716        // get available elixir mask any not active type from battle/guardian (and flask if no any)
2717        elixir_mask = (elixir_mask & ELIXIR_FLASK_MASK) ^ ELIXIR_FLASK_MASK;
2718
2719        // get all available elixirs by mask and spell level
2720        std::vector<uint32> elixirs;
2721        SpellElixirMap const& m_spellElixirs = spellmgr.GetSpellElixirMap();
2722        for(SpellElixirMap::const_iterator itr = m_spellElixirs.begin(); itr != m_spellElixirs.end(); ++itr)
2723        {
2724            if (itr->second & elixir_mask)
2725            {
2726                if (itr->second & (ELIXIR_UNSTABLE_MASK | ELIXIR_SHATTRATH_MASK))
2727                    continue;
2728
2729                SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
2730                if (spellInfo && (spellInfo->spellLevel < m_spellInfo->spellLevel || spellInfo->spellLevel > unitTarget->getLevel()))
2731                    continue;
2732
2733                elixirs.push_back(itr->first);
2734            }
2735        }
2736
2737        if (!elixirs.empty())
2738        {
2739            // cast random elixir on target
2740            uint32 rand_spell = urand(0,elixirs.size()-1);
2741            m_caster->CastSpell(unitTarget,elixirs[rand_spell],true,m_CastItem);
2742        }
2743    }
2744}
2745
2746void Spell::EffectEnergisePct(uint32 i)
2747{
2748    if(!unitTarget)
2749        return;
2750    if(!unitTarget->isAlive())
2751        return;
2752
2753    if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
2754        return;
2755
2756    Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
2757
2758    uint32 maxPower = unitTarget->GetMaxPower(power);
2759    if(maxPower == 0)
2760        return;
2761
2762    uint32 gain = damage * maxPower / 100;
2763    unitTarget->ModifyPower(power, gain);
2764    m_caster->SendEnergizeSpellLog(unitTarget, m_spellInfo->Id, damage, power);
2765}
2766
2767void Spell::SendLoot(uint64 guid, LootType loottype)
2768{
2769    Player* player = (Player*)m_caster;
2770    if (!player)
2771        return;
2772
2773    if (gameObjTarget)
2774    {
2775        switch (gameObjTarget->GetGoType())
2776        {
2777            case GAMEOBJECT_TYPE_DOOR:
2778            case GAMEOBJECT_TYPE_BUTTON:
2779                gameObjTarget->UseDoorOrButton();
2780                sWorld.ScriptsStart(sGameObjectScripts, gameObjTarget->GetDBTableGUIDLow(), player, gameObjTarget);
2781                return;
2782
2783            case GAMEOBJECT_TYPE_QUESTGIVER:
2784                // start or end quest
2785                player->PrepareQuestMenu(guid);
2786                player->SendPreparedQuest(guid);
2787                return;
2788
2789            case GAMEOBJECT_TYPE_SPELL_FOCUS:
2790                // triggering linked GO
2791                if(uint32 trapEntry = gameObjTarget->GetGOInfo()->spellFocus.linkedTrapId)
2792                    gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2793                return;
2794
2795            case GAMEOBJECT_TYPE_GOOBER:
2796                // goober_scripts can be triggered if the player don't have the quest
2797                if (gameObjTarget->GetGOInfo()->goober.eventId)
2798                {
2799                    sLog.outDebug("Goober ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->goober.eventId,gameObjTarget->GetDBTableGUIDLow());
2800                    sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->goober.eventId, player, gameObjTarget);
2801                }
2802
2803                // cast goober spell
2804                if (gameObjTarget->GetGOInfo()->goober.questId)
2805                    ///Quest require to be active for GO using
2806                    if(player->GetQuestStatus(gameObjTarget->GetGOInfo()->goober.questId) != QUEST_STATUS_INCOMPLETE)
2807                        return;
2808
2809                gameObjTarget->AddUniqueUse(player);
2810                gameObjTarget->SetLootState(GO_JUST_DEACTIVATED);
2811
2812                //TODO? Objective counting called without spell check but with quest objective check
2813                // if send spell id then this line will duplicate to spell casting call (double counting)
2814                // So we or have this line and not required in quest_template have reqSpellIdN
2815                // or must remove this line and required in DB have data in quest_template have reqSpellIdN for all quest using cases.
2816                player->CastedCreatureOrGO(gameObjTarget->GetEntry(), gameObjTarget->GetGUID(), 0);
2817
2818                // triggering linked GO
2819                if(uint32 trapEntry = gameObjTarget->GetGOInfo()->goober.linkedTrapId)
2820                    gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2821
2822                return;
2823
2824            case GAMEOBJECT_TYPE_CHEST:
2825                // TODO: possible must be moved to loot release (in different from linked triggering)
2826                if (gameObjTarget->GetGOInfo()->chest.eventId)
2827                {
2828                    sLog.outDebug("Chest ScriptStart id %u for GO %u", gameObjTarget->GetGOInfo()->chest.eventId,gameObjTarget->GetDBTableGUIDLow());
2829                    sWorld.ScriptsStart(sEventScripts, gameObjTarget->GetGOInfo()->chest.eventId, player, gameObjTarget);
2830                }
2831
2832                // triggering linked GO
2833                if(uint32 trapEntry = gameObjTarget->GetGOInfo()->chest.linkedTrapId)
2834                    gameObjTarget->TriggeringLinkedGameObject(trapEntry,m_caster);
2835
2836                // Don't return, let loots been taken
2837        }
2838    }
2839
2840    // Send loot
2841    player->SendLoot(guid, loottype);
2842}
2843
2844void Spell::EffectOpenLock(uint32 /*i*/)
2845{
2846    if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
2847    {
2848        sLog.outDebug( "WORLD: Open Lock - No Player Caster!");
2849        return;
2850    }
2851
2852    Player* player = (Player*)m_caster;
2853
2854    LootType loottype = LOOT_CORPSE;
2855    uint32 lockId = 0;
2856    uint64 guid = 0;
2857
2858    // Get lockId
2859    if(gameObjTarget)
2860    {
2861        GameObjectInfo const* goInfo = gameObjTarget->GetGOInfo();
2862        // Arathi Basin banner opening !
2863        if( goInfo->type == GAMEOBJECT_TYPE_BUTTON && goInfo->button.noDamageImmune ||
2864            goInfo->type == GAMEOBJECT_TYPE_GOOBER && goInfo->goober.losOK )
2865        {
2866            //isAllowUseBattleGroundObject() already called in CanCast()
2867            // in battleground check
2868            if(BattleGround *bg = player->GetBattleGround())
2869            {
2870                // check if it's correct bg
2871                if(bg && bg->GetTypeID() == BATTLEGROUND_AB)
2872                    bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2873                return;
2874            }
2875        }
2876        else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
2877        {
2878            //isAllowUseBattleGroundObject() already called in CanCast()
2879            // in battleground check
2880            if(BattleGround *bg = player->GetBattleGround())
2881            {
2882                if(bg->GetTypeID() == BATTLEGROUND_EY)
2883                    bg->EventPlayerClickedOnFlag(player, gameObjTarget);
2884                return;
2885            }
2886        }
2887        // handle outdoor pvp object opening, return true if go was registered for handling
2888        // these objects must have been spawned by outdoorpvp!
2889        else if(gameObjTarget->GetGOInfo()->type == GAMEOBJECT_TYPE_GOOBER && sOutdoorPvPMgr.HandleOpenGo(player, gameObjTarget->GetGUID()))
2890            return;
2891        lockId = gameObjTarget->GetLockId();
2892        guid = gameObjTarget->GetGUID();
2893    }
2894    else if(itemTarget)
2895    {
2896        lockId = itemTarget->GetProto()->LockID;
2897        guid = itemTarget->GetGUID();
2898    }
2899    else
2900    {
2901        sLog.outDebug( "WORLD: Open Lock - No GameObject/Item Target!");
2902        return;
2903    }
2904
2905    if(!lockId)                                             // possible case for GO and maybe for items.
2906    {
2907        SendLoot(guid, loottype);
2908        return;
2909    }
2910
2911    // Get LockInfo
2912    LockEntry const *lockInfo = sLockStore.LookupEntry(lockId);
2913
2914    if (!lockInfo)
2915    {
2916        sLog.outError( "Spell::EffectOpenLock: %s [guid = %u] has an unknown lockId: %u!",
2917            (gameObjTarget ? "gameobject" : "item"), GUID_LOPART(guid), lockId);
2918        SendCastResult(SPELL_FAILED_BAD_TARGETS);
2919        return;
2920    }
2921
2922    // check key
2923    for(int i = 0; i < 5; ++i)
2924    {
2925        // type==1 This means lockInfo->key[i] is an item
2926        if(lockInfo->keytype[i]==LOCK_KEY_ITEM && lockInfo->key[i] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[i])
2927        {
2928            SendLoot(guid, loottype);
2929            return;
2930        }
2931    }
2932
2933    uint32 SkillId = 0;
2934    // Check and skill-up skill
2935    if( m_spellInfo->Effect[1] == SPELL_EFFECT_SKILL )
2936        SkillId = m_spellInfo->EffectMiscValue[1];
2937                                                            // pickpocketing spells
2938    else if( m_spellInfo->EffectMiscValue[0] == LOCKTYPE_PICKLOCK )
2939        SkillId = SKILL_LOCKPICKING;
2940
2941    // skill bonus provided by casting spell (mostly item spells)
2942    uint32 spellSkillBonus = uint32(m_currentBasePoints[0]+1);
2943
2944    uint32 reqSkillValue = lockInfo->requiredminingskill;
2945
2946    if(lockInfo->requiredlockskill)                         // required pick lock skill applying
2947    {
2948        if(SkillId != SKILL_LOCKPICKING)                    // wrong skill (cheating?)
2949        {
2950            SendCastResult(SPELL_FAILED_FIZZLE);
2951            return;
2952        }
2953
2954        reqSkillValue = lockInfo->requiredlockskill;
2955    }
2956    else if(SkillId == SKILL_LOCKPICKING)                   // apply picklock skill to wrong target
2957    {
2958        SendCastResult(SPELL_FAILED_BAD_TARGETS);
2959        return;
2960    }
2961
2962    if ( SkillId )
2963    {
2964        loottype = LOOT_SKINNING;
2965        if ( player->GetSkillValue(SkillId) + spellSkillBonus < reqSkillValue )
2966        {
2967            SendCastResult(SPELL_FAILED_LOW_CASTLEVEL);
2968            return;
2969        }
2970
2971        // update skill if really known
2972        uint32 SkillValue = player->GetPureSkillValue(SkillId);
2973        if(SkillValue)                                      // non only item base skill
2974        {
2975            if(gameObjTarget)
2976            {
2977                // Allow one skill-up until respawned
2978                if ( !gameObjTarget->IsInSkillupList( player->GetGUIDLow() ) &&
2979                    player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue) )
2980                    gameObjTarget->AddToSkillupList( player->GetGUIDLow() );
2981            }
2982            else if(itemTarget)
2983            {
2984                // Do one skill-up
2985                uint32 SkillValue = player->GetPureSkillValue(SkillId);
2986                player->UpdateGatherSkill(SkillId, SkillValue, reqSkillValue);
2987            }
2988        }
2989    }
2990
2991    SendLoot(guid, loottype);
2992}
2993
2994void Spell::EffectSummonChangeItem(uint32 i)
2995{
2996    if(m_caster->GetTypeId() != TYPEID_PLAYER)
2997        return;
2998
2999    Player *player = (Player*)m_caster;
3000
3001    // applied only to using item
3002    if(!m_CastItem)
3003        return;
3004
3005    // ... only to item in own inventory/bank/equip_slot
3006    if(m_CastItem->GetOwnerGUID()!=player->GetGUID())
3007        return;
3008
3009    uint32 newitemid = m_spellInfo->EffectItemType[i];
3010    if(!newitemid)
3011        return;
3012
3013    uint16 pos = m_CastItem->GetPos();
3014
3015    Item *pNewItem = Item::CreateItem( newitemid, 1, player);
3016    if( !pNewItem )
3017        return;
3018
3019    for(uint8 i= PERM_ENCHANTMENT_SLOT; i<=TEMP_ENCHANTMENT_SLOT; ++i)
3020    {
3021        if(m_CastItem->GetEnchantmentId(EnchantmentSlot(i)))
3022            pNewItem->SetEnchantment(EnchantmentSlot(i), m_CastItem->GetEnchantmentId(EnchantmentSlot(i)), m_CastItem->GetEnchantmentDuration(EnchantmentSlot(i)), m_CastItem->GetEnchantmentCharges(EnchantmentSlot(i)));
3023    }
3024
3025    if(m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) < m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
3026    {
3027        double loosePercent = 1 - m_CastItem->GetUInt32Value(ITEM_FIELD_DURABILITY) / double(m_CastItem->GetUInt32Value(ITEM_FIELD_MAXDURABILITY));
3028        player->DurabilityLoss(pNewItem, loosePercent);
3029    }
3030
3031    if( player->IsInventoryPos( pos ) )
3032    {
3033        ItemPosCountVec dest;
3034        uint8 msg = player->CanStoreItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3035        if( msg == EQUIP_ERR_OK )
3036        {
3037            player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3038
3039            // prevent crash at access and unexpected charges counting with item update queue corrupt
3040            if(m_CastItem==m_targets.getItemTarget())
3041                m_targets.setItemTarget(NULL);
3042
3043            m_CastItem = NULL;
3044
3045            player->StoreItem( dest, pNewItem, true);
3046            return;
3047        }
3048    }
3049    else if( player->IsBankPos ( pos ) )
3050    {
3051        ItemPosCountVec dest;
3052        uint8 msg = player->CanBankItem( m_CastItem->GetBagSlot(), m_CastItem->GetSlot(), dest, pNewItem, true );
3053        if( msg == EQUIP_ERR_OK )
3054        {
3055            player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3056
3057            // prevent crash at access and unexpected charges counting with item update queue corrupt
3058            if(m_CastItem==m_targets.getItemTarget())
3059                m_targets.setItemTarget(NULL);
3060
3061            m_CastItem = NULL;
3062
3063            player->BankItem( dest, pNewItem, true);
3064            return;
3065        }
3066    }
3067    else if( player->IsEquipmentPos ( pos ) )
3068    {
3069        uint16 dest;
3070        uint8 msg = player->CanEquipItem( m_CastItem->GetSlot(), dest, pNewItem, true );
3071        if( msg == EQUIP_ERR_OK )
3072        {
3073            player->DestroyItem(m_CastItem->GetBagSlot(), m_CastItem->GetSlot(),true);
3074
3075            // prevent crash at access and unexpected charges counting with item update queue corrupt
3076            if(m_CastItem==m_targets.getItemTarget())
3077                m_targets.setItemTarget(NULL);
3078
3079            m_CastItem = NULL;
3080
3081            player->EquipItem( dest, pNewItem, true);
3082            player->AutoUnequipOffhandIfNeed();
3083            return;
3084        }
3085    }
3086
3087    // fail
3088    delete pNewItem;
3089}
3090
3091void Spell::EffectOpenSecretSafe(uint32 i)
3092{
3093    EffectOpenLock(i);                                      //no difference for now
3094}
3095
3096void Spell::EffectProficiency(uint32 /*i*/)
3097{
3098    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
3099        return;
3100    Player *p_target = (Player*)unitTarget;
3101
3102    uint32 subClassMask = m_spellInfo->EquippedItemSubClassMask;
3103    if(m_spellInfo->EquippedItemClass == 2 && !(p_target->GetWeaponProficiency() & subClassMask))
3104    {
3105        p_target->AddWeaponProficiency(subClassMask);
3106        p_target->SendProficiency(uint8(0x02),p_target->GetWeaponProficiency());
3107    }
3108    if(m_spellInfo->EquippedItemClass == 4 && !(p_target->GetArmorProficiency() & subClassMask))
3109    {
3110        p_target->AddArmorProficiency(subClassMask);
3111        p_target->SendProficiency(uint8(0x04),p_target->GetArmorProficiency());
3112    }
3113}
3114
3115void Spell::EffectApplyAreaAura(uint32 i)
3116{
3117    if(!unitTarget)
3118        return;
3119    if(!unitTarget->isAlive())
3120        return;
3121
3122    AreaAura* Aur = new AreaAura(m_spellInfo, i, &m_currentBasePoints[i], unitTarget, m_caster, m_CastItem);
3123    unitTarget->AddAura(Aur);
3124}
3125
3126void Spell::EffectSummonType(uint32 i)
3127{
3128    switch(m_spellInfo->EffectMiscValueB[i])
3129    {
3130        case SUMMON_TYPE_GUARDIAN:
3131            EffectSummonGuardian(i);
3132            break;
3133        case SUMMON_TYPE_POSESSED:
3134        case SUMMON_TYPE_POSESSED2:
3135            EffectSummonPossessed(i);
3136            break;
3137        case SUMMON_TYPE_WILD:
3138            EffectSummonWild(i);
3139            break;
3140        case SUMMON_TYPE_DEMON:
3141            EffectSummonDemon(i);
3142            break;
3143        case SUMMON_TYPE_SUMMON:
3144            EffectSummon(i);
3145            break;
3146        case SUMMON_TYPE_CRITTER:
3147        case SUMMON_TYPE_CRITTER2:
3148        case SUMMON_TYPE_CRITTER3:
3149            EffectSummonCritter(i);
3150            break;
3151        case SUMMON_TYPE_TOTEM_SLOT1:
3152        case SUMMON_TYPE_TOTEM_SLOT2:
3153        case SUMMON_TYPE_TOTEM_SLOT3:
3154        case SUMMON_TYPE_TOTEM_SLOT4:
3155        case SUMMON_TYPE_TOTEM:
3156            EffectSummonTotem(i);
3157            break;
3158        case SUMMON_TYPE_UNKNOWN1:
3159        case SUMMON_TYPE_UNKNOWN2:
3160        case SUMMON_TYPE_UNKNOWN3:
3161        case SUMMON_TYPE_UNKNOWN4:
3162        case SUMMON_TYPE_UNKNOWN5:
3163            break;
3164        default:
3165            sLog.outError("EffectSummonType: Unhandled summon type %u", m_spellInfo->EffectMiscValueB[i]);
3166            break;
3167    }
3168}
3169
3170void Spell::EffectSummon(uint32 i)
3171{
3172    if(m_caster->GetPetGUID())
3173        return;
3174
3175    if(!unitTarget)
3176        return;
3177    uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3178    if(!pet_entry)
3179        return;
3180    uint32 level = m_caster->getLevel();
3181    Pet* spawnCreature = new Pet(SUMMON_PET);
3182    spawnCreature->setActive(m_caster->isActive());
3183
3184    if(spawnCreature->LoadPetFromDB(m_caster,pet_entry))
3185    {
3186        // set timer for unsummon
3187        int32 duration = GetSpellDuration(m_spellInfo);
3188        if(duration > 0)
3189            spawnCreature->SetDuration(duration);
3190
3191        return;
3192    }
3193
3194    Map *map = m_caster->GetMap();
3195    uint32 pet_number = objmgr.GeneratePetNumber();
3196    if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),map,m_spellInfo->EffectMiscValue[i], pet_number))
3197    {
3198        sLog.outErrorDb("Spell::EffectSummon: no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3199        delete spawnCreature;
3200        return;
3201    }
3202
3203    // Summon in dest location
3204    float x,y,z;
3205    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3206    {
3207        x = m_targets.m_destX;
3208        y = m_targets.m_destY;
3209        z = m_targets.m_destZ;
3210    }
3211    else
3212        m_caster->GetClosePoint(x,y,z,spawnCreature->GetObjectSize());
3213
3214    spawnCreature->Relocate(x,y,z,-m_caster->GetOrientation());
3215
3216    if(!spawnCreature->IsPositionValid())
3217    {
3218        sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3219        delete spawnCreature;
3220        return;
3221    }
3222
3223    // set timer for unsummon
3224    int32 duration = GetSpellDuration(m_spellInfo);
3225    if(duration > 0)
3226        spawnCreature->SetDuration(duration);
3227
3228    spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
3229    spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3230    spawnCreature->setPowerType(POWER_MANA);
3231    spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3232    spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3233    spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
3234    spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3235    spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3236    spawnCreature->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
3237    spawnCreature->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
3238    spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
3239    spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3240
3241    spawnCreature->InitStatsForLevel(level);
3242
3243    spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3244
3245    spawnCreature->AIM_Initialize();
3246    spawnCreature->InitPetCreateSpells();
3247    spawnCreature->SetHealth(spawnCreature->GetMaxHealth());
3248    spawnCreature->SetPower(POWER_MANA, spawnCreature->GetMaxPower(POWER_MANA));
3249
3250    std::string name = m_caster->GetName();
3251    name.append(petTypeSuffix[spawnCreature->getPetType()]);
3252    spawnCreature->SetName( name );
3253
3254    map->Add((Creature*)spawnCreature);
3255
3256    if(m_caster->GetTypeId() == TYPEID_PLAYER)
3257    {
3258        m_caster->SetPet(spawnCreature);
3259        spawnCreature->GetCharmInfo()->SetReactState( REACT_DEFENSIVE );
3260        spawnCreature->SavePetToDB(PET_SAVE_AS_CURRENT);
3261        ((Player*)m_caster)->PetSpellInitialize();
3262    }
3263}
3264
3265void Spell::EffectLearnSpell(uint32 i)
3266{
3267    if(!unitTarget)
3268        return;
3269
3270    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3271    {
3272        if(m_caster->GetTypeId() == TYPEID_PLAYER)
3273            EffectLearnPetSpell(i);
3274
3275        return;
3276    }
3277
3278    Player *player = (Player*)unitTarget;
3279
3280    uint32 spellToLearn = (m_spellInfo->Id==SPELL_ID_GENERIC_LEARN) ? damage : m_spellInfo->EffectTriggerSpell[i];
3281    player->learnSpell(spellToLearn);
3282
3283    sLog.outDebug( "Spell: Player %u have learned spell %u from NpcGUID=%u", player->GetGUIDLow(), spellToLearn, m_caster->GetGUIDLow() );
3284}
3285
3286void Spell::EffectDispel(uint32 i)
3287{
3288    if(!unitTarget)
3289        return;
3290
3291    // Fill possible dispell list
3292    std::vector <Aura *> dispel_list;
3293
3294    // Create dispel mask by dispel type
3295    uint32 dispel_type = m_spellInfo->EffectMiscValue[i];
3296    uint32 dispelMask  = GetDispellMask( DispelType(dispel_type) );
3297    Unit::AuraMap const& auras = unitTarget->GetAuras();
3298    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
3299    {
3300        Aura *aur = (*itr).second;
3301        if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
3302        {
3303            if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
3304            {
3305                bool positive = true;
3306                if (!aur->IsPositive())
3307                    positive = false;
3308                else
3309                    positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
3310
3311                // do not remove positive auras if friendly target
3312                //               negative auras if non-friendly target
3313                if(positive == unitTarget->IsFriendlyTo(m_caster))
3314                    continue;
3315            }
3316            // Add aura to dispel list
3317            dispel_list.push_back(aur);
3318        }
3319    }
3320    // Ok if exist some buffs for dispel try dispel it
3321    if (!dispel_list.empty())
3322    {
3323        std::list < std::pair<uint32,uint64> > success_list;// (spell_id,casterGuid)
3324        std::list < uint32 > fail_list;                     // spell_id
3325        int32 list_size = dispel_list.size();
3326        // Dispell N = damage buffs (or while exist buffs for dispel)
3327        for (int32 count=0; count < damage && list_size > 0; ++count)
3328        {
3329            // Random select buff for dispel
3330            Aura *aur = dispel_list[urand(0, list_size-1)];
3331
3332            SpellEntry const* spellInfo = aur->GetSpellProto();
3333            // Base dispel chance
3334            // TODO: possible chance depend from spell level??
3335            int32 miss_chance = 0;
3336            // Apply dispel mod from aura caster
3337            if (Unit *caster = aur->GetCaster())
3338            {
3339                if ( Player* modOwner = caster->GetSpellModOwner() )
3340                    modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
3341            }
3342            // Try dispel
3343            if (roll_chance_i(miss_chance))
3344                fail_list.push_back(aur->GetId());
3345            else
3346                success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
3347            // Remove buff from list for prevent doubles
3348            for (std::vector<Aura *>::iterator j = dispel_list.begin(); j != dispel_list.end(); )
3349            {
3350                Aura *dispeled = *j;
3351                if (dispeled->GetId() == aur->GetId() && dispeled->GetCasterGUID() == aur->GetCasterGUID())
3352                {
3353                    j = dispel_list.erase(j);
3354                    --list_size;
3355                }
3356                else
3357                    ++j;
3358            }
3359        }
3360        // Send success log and really remove auras
3361        if (!success_list.empty())
3362        {
3363            int32 count = success_list.size();
3364            WorldPacket data(SMSG_SPELLDISPELLOG, 8+8+4+1+4+count*5);
3365            data.append(unitTarget->GetPackGUID());         // Victim GUID
3366            data.append(m_caster->GetPackGUID());           // Caster GUID
3367            data << uint32(m_spellInfo->Id);                // Dispell spell id
3368            data << uint8(0);                               // not used
3369            data << uint32(count);                          // count
3370            for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
3371            {
3372                SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
3373                data << uint32(spellInfo->Id);              // Spell Id
3374                data << uint8(0);                           // 0 - dispeled !=0 cleansed
3375                unitTarget->RemoveAurasDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
3376            }
3377            m_caster->SendMessageToSet(&data, true);
3378
3379            // On succes dispel
3380            // Devour Magic
3381            if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->Category == 12)
3382            {
3383                uint32 heal_spell = 0;
3384                switch (m_spellInfo->Id)
3385                {
3386                    case 19505: heal_spell = 19658; break;
3387                    case 19731: heal_spell = 19732; break;
3388                    case 19734: heal_spell = 19733; break;
3389                    case 19736: heal_spell = 19735; break;
3390                    case 27276: heal_spell = 27278; break;
3391                    case 27277: heal_spell = 27279; break;
3392                    default:
3393                        sLog.outDebug("Spell for Devour Magic %d not handled in Spell::EffectDispel", m_spellInfo->Id);
3394                        break;
3395                }
3396                if (heal_spell)
3397                    m_caster->CastSpell(m_caster, heal_spell, true);
3398            }
3399        }
3400        // Send fail log to client
3401        if (!fail_list.empty())
3402        {
3403            // Failed to dispell
3404            WorldPacket data(SMSG_DISPEL_FAILED, 8+8+4+4*fail_list.size());
3405            data << uint64(m_caster->GetGUID());            // Caster GUID
3406            data << uint64(unitTarget->GetGUID());          // Victim GUID
3407            data << uint32(m_spellInfo->Id);                // Dispell spell id
3408            for (std::list< uint32 >::iterator j = fail_list.begin(); j != fail_list.end(); ++j)
3409                data << uint32(*j);                         // Spell Id
3410            m_caster->SendMessageToSet(&data, true);
3411        }
3412    }
3413}
3414
3415void Spell::EffectDualWield(uint32 /*i*/)
3416{
3417    unitTarget->SetCanDualWield(true);
3418    if(unitTarget->GetTypeId() == TYPEID_UNIT)
3419        ((Creature*)unitTarget)->UpdateDamagePhysical(OFF_ATTACK);
3420}
3421
3422void Spell::EffectPull(uint32 /*i*/)
3423{
3424    // TODO: create a proper pull towards distract spell center for distract
3425    sLog.outDebug("WORLD: Spell Effect DUMMY");
3426}
3427
3428void Spell::EffectDistract(uint32 /*i*/)
3429{
3430    // Check for possible target
3431    if (!unitTarget || unitTarget->isInCombat())
3432        return;
3433
3434    // target must be OK to do this
3435    if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3436        return;
3437
3438    float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3439
3440    if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3441    {
3442        // For players just turn them
3443        WorldPacket data;
3444        ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3445        ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3446        ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3447    }
3448    else
3449    {
3450        // Set creature Distracted, Stop it, And turn it
3451        unitTarget->SetOrientation(angle);
3452        unitTarget->StopMoving();
3453        unitTarget->GetMotionMaster()->MoveDistract(damage*1000);
3454    }
3455}
3456
3457void Spell::EffectPickPocket(uint32 /*i*/)
3458{
3459    if( m_caster->GetTypeId() != TYPEID_PLAYER )
3460        return;
3461
3462    // victim must be creature and attackable
3463    if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3464        return;
3465
3466    // victim have to be alive and humanoid or undead
3467    if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3468    {
3469        int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3470
3471        if (chance > irand(0, 19))
3472        {
3473            // Stealing successful
3474            //sLog.outDebug("Sending loot from pickpocket");
3475            ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3476        }
3477        else
3478        {
3479            // Reveal action + get attack
3480            m_caster->RemoveInterruptableAura(AURA_INTERRUPT_FLAG_STEALTH);
3481            if (((Creature*)unitTarget)->AI())
3482                ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3483        }
3484    }
3485}
3486
3487void Spell::EffectAddFarsight(uint32 i)
3488{
3489    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3490    int32 duration = GetSpellDuration(m_spellInfo);
3491    DynamicObject* dynObj = new DynamicObject;
3492    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))
3493    {
3494        delete dynObj;
3495        return;
3496    }
3497    dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3498    dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3499    m_caster->AddDynObject(dynObj);
3500    MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj);
3501    m_caster->SetUInt64Value(PLAYER_FARSIGHT, dynObj->GetGUID());
3502}
3503
3504void Spell::EffectSummonWild(uint32 i)
3505{
3506    uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3507    if(!creature_entry)
3508        return;
3509
3510    uint32 level = m_caster->getLevel();
3511
3512    // level of creature summoned using engineering item based at engineering skill level
3513    if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3514    {
3515        ItemPrototype const *proto = m_CastItem->GetProto();
3516        if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3517        {
3518            uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3519            if(skill202)
3520            {
3521                level = skill202/5;
3522            }
3523        }
3524    }
3525
3526    // select center of summon position
3527    float center_x = m_targets.m_destX;
3528    float center_y = m_targets.m_destY;
3529    float center_z = m_targets.m_destZ;
3530
3531    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3532
3533    int32 amount = damage > 0 ? damage : 1;
3534
3535    for(int32 count = 0; count < amount; ++count)
3536    {
3537        float px, py, pz;
3538        // If dest location if present
3539        if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3540        {
3541            // Summon 1 unit in dest location
3542            if (count == 0)
3543            {
3544                px = m_targets.m_destX;
3545                py = m_targets.m_destY;
3546                pz = m_targets.m_destZ;
3547            }
3548            // Summon in random point all other units if location present
3549            else
3550                m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3551        }
3552        // Summon if dest location not present near caster
3553        else
3554            m_caster->GetClosePoint(px,py,pz,3.0f);
3555
3556        int32 duration = GetSpellDuration(m_spellInfo);
3557
3558        TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
3559
3560        if(m_originalCaster)
3561            m_originalCaster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3562        else
3563            m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3564    }
3565}
3566
3567void Spell::EffectSummonGuardian(uint32 i)
3568{
3569    uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3570    if(!pet_entry)
3571        return;
3572
3573    // Jewelery statue case (totem like)
3574    if(m_spellInfo->SpellIconID==2056)
3575    {
3576        EffectSummonTotem(i);
3577        return;
3578    }
3579
3580    // trigger
3581    if(m_spellInfo->Id == 40276)
3582    {
3583        EffectSummonWild(i);
3584        return;
3585    }
3586
3587    // set timer for unsummon
3588    int32 duration = GetSpellDuration(m_spellInfo);
3589
3590    // Search old Guardian only for players (if casted spell not have duration or cooldown)
3591    // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3592    //        so this code hack in fact
3593    if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3594        if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3595            return;                                         // find old guardian, ignore summon
3596
3597    // in another case summon new
3598    uint32 level = m_caster->getLevel();
3599
3600    // level of pet summoned using engineering item based at engineering skill level
3601    if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3602    {
3603        ItemPrototype const *proto = m_CastItem->GetProto();
3604        if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3605        {
3606            uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3607            if(skill202)
3608            {
3609                level = skill202/5;
3610            }
3611        }
3612    }
3613
3614    // select center of summon position
3615    float center_x = m_targets.m_destX;
3616    float center_y = m_targets.m_destY;
3617    float center_z = m_targets.m_destZ;
3618
3619    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3620
3621    int32 amount = damage > 0 ? damage : 1;
3622
3623    for(int32 count = 0; count < amount; ++count)
3624    {
3625        Pet* spawnCreature = new Pet(GUARDIAN_PET);
3626        spawnCreature->setActive(m_caster->isActive());
3627
3628        Map *map = m_caster->GetMap();
3629        uint32 pet_number = objmgr.GeneratePetNumber();
3630        if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number))
3631        {
3632            sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3633            delete spawnCreature;
3634            return;
3635        }
3636
3637        float px, py, pz;
3638        // If dest location if present
3639        if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3640        {
3641            // Summon 1 unit in dest location
3642            if (count == 0)
3643            {
3644                px = m_targets.m_destX;
3645                py = m_targets.m_destY;
3646                pz = m_targets.m_destZ;
3647            }
3648            // Summon in random point all other units if location present
3649            else
3650                m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3651        }
3652        // Summon if dest location not present near caster
3653        else
3654            m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3655
3656        spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3657
3658        if(!spawnCreature->IsPositionValid())
3659        {
3660            sLog.outError("ERROR: Pet (guidlow %d, entry %d) not created base at creature. Suggested coordinates isn't valid (X: %d Y: ^%d)", spawnCreature->GetGUIDLow(), spawnCreature->GetEntry(), spawnCreature->GetPositionX(), spawnCreature->GetPositionY());
3661            delete spawnCreature;
3662            return;
3663        }
3664
3665        if(duration > 0)
3666            spawnCreature->SetDuration(duration);
3667
3668        spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
3669        spawnCreature->setPowerType(POWER_MANA);
3670        spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3671        spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3672        spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3673        spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3674        spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3675        spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
3676        spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3677
3678        spawnCreature->InitStatsForLevel(level);
3679        spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3680
3681        spawnCreature->AIM_Initialize();
3682
3683        if(m_caster->GetTypeId()==TYPEID_PLAYER)
3684            ((Player*)m_caster)->AddGuardian(spawnCreature);
3685
3686        map->Add((Creature*)spawnCreature);
3687    }
3688}
3689
3690void Spell::EffectSummonPossessed(uint32 i)
3691{
3692    uint32 creatureEntry = m_spellInfo->EffectMiscValue[i];
3693    if(!creatureEntry)
3694        return;
3695
3696    if(m_caster->GetTypeId() != TYPEID_PLAYER)
3697        return;
3698
3699    uint32 level = m_caster->getLevel();
3700
3701    float px, py, pz;
3702    m_caster->GetClosePoint(px, py, pz, DEFAULT_WORLD_OBJECT_SIZE);
3703
3704    int32 duration = GetSpellDuration(m_spellInfo);
3705
3706    TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_OR_DEAD_DESPAWN;
3707
3708    Creature* c = m_caster->SummonCreature(creatureEntry, px, py, pz, m_caster->GetOrientation(), summonType, duration);
3709    ((Player*)m_caster)->Possess(c);
3710}
3711
3712void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3713{
3714    if(!unitTarget)
3715        return;
3716
3717    if(unitTarget->isInFlight())
3718        return;
3719
3720    uint32 mapid = m_caster->GetMapId();
3721    float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3722
3723    float fx,fy,fz;
3724    m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3725
3726    if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3727        ((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));
3728    else
3729        MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
3730}
3731
3732void Spell::EffectLearnSkill(uint32 i)
3733{
3734    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3735        return;
3736
3737    if(damage < 0)
3738        return;
3739
3740    uint32 skillid =  m_spellInfo->EffectMiscValue[i];
3741    uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3742    ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3743}
3744
3745void Spell::EffectAddHonor(uint32 /*i*/)
3746{
3747    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3748        return;
3749
3750    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());
3751
3752    // TODO: find formula for honor reward based on player's level!
3753
3754    // now fixed only for level 70 players:
3755    if (((Player*)unitTarget)->getLevel() == 70)
3756        ((Player*)unitTarget)->RewardHonor(NULL, 1, this->damage);
3757}
3758
3759void Spell::EffectTradeSkill(uint32 /*i*/)
3760{
3761    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3762        return;
3763    // uint32 skillid =  m_spellInfo->EffectMiscValue[i];
3764    // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3765    // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3766}
3767
3768void Spell::EffectEnchantItemPerm(uint32 i)
3769{
3770    if(m_caster->GetTypeId() != TYPEID_PLAYER)
3771        return;
3772    if (!itemTarget)
3773        return;
3774
3775    Player* p_caster = (Player*)m_caster;
3776
3777    p_caster->UpdateCraftSkill(m_spellInfo->Id);
3778
3779    if (m_spellInfo->EffectMiscValue[i])
3780    {
3781        uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3782
3783        SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3784        if(!pEnchant)
3785            return;
3786
3787        // item can be in trade slot and have owner diff. from caster
3788        Player* item_owner = itemTarget->GetOwner();
3789        if(!item_owner)
3790            return;
3791
3792        if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3793            sLog.outCommand("GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3794                p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3795                itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3796                item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3797
3798        // remove old enchanting before applying new if equipped
3799        item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3800
3801        itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3802
3803        // add new enchanting if equipped
3804        item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3805    }
3806}
3807
3808void Spell::EffectEnchantItemTmp(uint32 i)
3809{
3810    if(m_caster->GetTypeId() != TYPEID_PLAYER)
3811        return;
3812
3813    Player* p_caster = (Player*)m_caster;
3814
3815    if(!itemTarget)
3816        return;
3817
3818    uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3819
3820    // Shaman Rockbiter Weapon
3821    if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3822    {
3823        int32 enchnting_damage = m_currentBasePoints[1]+1;
3824
3825        // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3826        // with already applied percent bonus from Elemental Weapons talent
3827        // Note: damage calculated (correctly) with rounding int32(float(v)) but
3828        // RW enchantments applied damage int32(float(v)+0.5), this create  0..1 difference sometime
3829        switch(enchnting_damage)
3830        {
3831            // Rank 1
3832            case  2: enchant_id =   29; break;              //  0% [ 7% ==  2, 14% == 2, 20% == 2]
3833            // Rank 2
3834            case  4: enchant_id =    6; break;              //  0% [ 7% ==  4, 14% == 4]
3835            case  5: enchant_id = 3025; break;              // 20%
3836            // Rank 3
3837            case  6: enchant_id =    1; break;              //  0% [ 7% ==  6, 14% == 6]
3838            case  7: enchant_id = 3027; break;              // 20%
3839            // Rank 4
3840            case  9: enchant_id = 3032; break;              //  0% [ 7% ==  6]
3841            case 10: enchant_id =  503; break;              // 14%
3842            case 11: enchant_id = 3031; break;              // 20%
3843            // Rank 5
3844            case 15: enchant_id = 3035; break;              // 0%
3845            case 16: enchant_id = 1663; break;              // 7%
3846            case 17: enchant_id = 3033; break;              // 14%
3847            case 18: enchant_id = 3034; break;              // 20%
3848            // Rank 6
3849            case 28: enchant_id = 3038; break;              // 0%
3850            case 29: enchant_id =  683; break;              // 7%
3851            case 31: enchant_id = 3036; break;              // 14%
3852            case 33: enchant_id = 3037; break;              // 20%
3853            // Rank 7
3854            case 40: enchant_id = 3041; break;              // 0%
3855            case 42: enchant_id = 1664; break;              // 7%
3856            case 45: enchant_id = 3039; break;              // 14%
3857            case 48: enchant_id = 3040; break;              // 20%
3858            // Rank 8
3859            case 49: enchant_id = 3044; break;              // 0%
3860            case 52: enchant_id = 2632; break;              // 7%
3861            case 55: enchant_id = 3042; break;              // 14%
3862            case 58: enchant_id = 3043; break;              // 20%
3863            // Rank 9
3864            case 62: enchant_id = 2633; break;              // 0%
3865            case 66: enchant_id = 3018; break;              // 7%
3866            case 70: enchant_id = 3019; break;              // 14%
3867            case 74: enchant_id = 3020; break;              // 20%
3868            default:
3869                sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3870                return;
3871        }
3872    }
3873
3874    if (!enchant_id)
3875    {
3876        sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3877        return;
3878    }
3879
3880    SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3881    if(!pEnchant)
3882    {
3883        sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3884        return;
3885    }
3886
3887    // select enchantment duration
3888    uint32 duration;
3889
3890    // rogue family enchantments exception by duration
3891    if(m_spellInfo->Id==38615)
3892        duration = 1800;                                    // 30 mins
3893    // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3894    else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3895        duration = 3600;                                    // 1 hour
3896    // shaman family enchantments
3897    else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3898        duration = 1800;                                    // 30 mins
3899    // other cases with this SpellVisual already selected
3900    else if(m_spellInfo->SpellVisual==215)
3901        duration = 1800;                                    // 30 mins
3902    // some fishing pole bonuses
3903    else if(m_spellInfo->SpellVisual==563)
3904        duration = 600;                                     // 10 mins
3905    // shaman rockbiter enchantments
3906    else if(m_spellInfo->SpellVisual==0)
3907        duration = 1800;                                    // 30 mins
3908    else if(m_spellInfo->Id==29702)
3909        duration = 300;                                     // 5 mins
3910    else if(m_spellInfo->Id==37360)
3911        duration = 300;                                     // 5 mins
3912    // default case
3913    else
3914        duration = 3600;                                    // 1 hour
3915
3916    // item can be in trade slot and have owner diff. from caster
3917    Player* item_owner = itemTarget->GetOwner();
3918    if(!item_owner)
3919        return;
3920
3921    if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3922        sLog.outCommand("GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3923            p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3924            itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3925            item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3926
3927    // remove old enchanting before applying new if equipped
3928    item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
3929
3930    itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
3931
3932    // add new enchanting if equipped
3933    item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
3934}
3935
3936void Spell::EffectTameCreature(uint32 /*i*/)
3937{
3938    if(m_caster->GetPetGUID())
3939        return;
3940
3941    if(!unitTarget)
3942        return;
3943
3944    if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3945        return;
3946
3947    Creature* creatureTarget = (Creature*)unitTarget;
3948
3949    if(creatureTarget->isPet())
3950        return;
3951
3952    if(m_caster->getClass() != CLASS_HUNTER)
3953        return;
3954
3955    // cast finish successfully
3956    //SendChannelUpdate(0);
3957    finish();
3958
3959    Pet* pet = m_caster->CreateTamedPetFrom(creatureTarget,m_spellInfo->Id);
3960
3961    // kill original creature
3962    creatureTarget->setDeathState(JUST_DIED);
3963    creatureTarget->RemoveCorpse();
3964    creatureTarget->SetHealth(0);                       // just for nice GM-mode view
3965
3966    // prepare visual effect for levelup
3967    pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
3968
3969    // add to world
3970    MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
3971
3972    // visual effect for levelup
3973    pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
3974
3975    // caster have pet now
3976    m_caster->SetPet(pet);
3977
3978    if(m_caster->GetTypeId() == TYPEID_PLAYER)
3979    {
3980        pet->SavePetToDB(PET_SAVE_AS_CURRENT);
3981        ((Player*)m_caster)->PetSpellInitialize();
3982    }
3983}
3984
3985void Spell::EffectSummonPet(uint32 i)
3986{
3987    uint32 petentry = m_spellInfo->EffectMiscValue[i];
3988
3989    Pet *OldSummon = m_caster->GetPet();
3990
3991    // if pet requested type already exist
3992    if( OldSummon )
3993    {
3994        if(petentry == 0 || OldSummon->GetEntry() == petentry)
3995        {
3996            // pet in corpse state can't be summoned
3997            if( OldSummon->isDead() )
3998                return;
3999
4000            MapManager::Instance().GetMap(OldSummon->GetMapId(), OldSummon)->Remove((Creature*)OldSummon,false);
4001            OldSummon->SetMapId(m_caster->GetMapId());
4002
4003            float px, py, pz;
4004            m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4005
4006            OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4007            MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->Add((Creature*)OldSummon);
4008
4009            if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4010            {
4011                ((Player*)m_caster)->PetSpellInitialize();
4012            }
4013            return;
4014        }
4015
4016        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4017            ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4018        else
4019            return;
4020    }
4021
4022    Pet* NewSummon = new Pet;
4023    NewSummon->setActive(m_caster->isActive());
4024
4025    // petentry==0 for hunter "call pet" (current pet summoned if any)
4026    if(NewSummon->LoadPetFromDB(m_caster,petentry))
4027    {
4028        if(NewSummon->getPetType()==SUMMON_PET)
4029        {
4030            // Remove Demonic Sacrifice auras (known pet)
4031            Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4032            for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4033            {
4034                if((*itr)->GetModifier()->m_miscvalue==2228)
4035                {
4036                    m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4037                    itr = auraClassScripts.begin();
4038                }
4039                else
4040                    ++itr;
4041            }
4042        }
4043
4044        return;
4045    }
4046
4047    // not error in case fail hunter call pet
4048    if(!petentry)
4049    {
4050        delete NewSummon;
4051        return;
4052    }
4053
4054    CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4055
4056    if(!cInfo)
4057    {
4058        sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4059        delete NewSummon;
4060        return;
4061    }
4062
4063    Map *map = m_caster->GetMap();
4064    uint32 pet_number = objmgr.GeneratePetNumber();
4065    if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number))
4066    {
4067        delete NewSummon;
4068        return;
4069    }
4070
4071    float px, py, pz;
4072    m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4073
4074    NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4075
4076    if(!NewSummon->IsPositionValid())
4077    {
4078        sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", NewSummon->GetGUIDLow(), NewSummon->GetEntry(), NewSummon->GetPositionX(), NewSummon->GetPositionY());
4079        delete NewSummon;
4080        return;
4081    }
4082
4083    uint32 petlevel = m_caster->getLevel();
4084    NewSummon->setPetType(SUMMON_PET);
4085
4086    uint32 faction = m_caster->getFaction();
4087    if(m_caster->GetTypeId() == TYPEID_UNIT)
4088    {
4089                if ( ((Creature*)m_caster)->isTotem() )
4090                        NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4091                else
4092                        NewSummon->GetCharmInfo()->SetReactState(REACT_DEFENSIVE);
4093    }
4094
4095    NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
4096    NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
4097    NewSummon->SetUInt32Value(UNIT_NPC_FLAGS , 0);
4098    NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4099    NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
4100    NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
4101    NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,time(NULL));
4102    NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
4103    NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
4104    NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4105
4106    NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4107    // this enables pet details window (Shift+P)
4108
4109    // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4110    NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4111
4112    NewSummon->InitStatsForLevel( petlevel);
4113    NewSummon->InitPetCreateSpells();
4114
4115    if(NewSummon->getPetType()==SUMMON_PET)
4116    {
4117        // Remove Demonic Sacrifice auras (new pet)
4118        Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4119        for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4120        {
4121            if((*itr)->GetModifier()->m_miscvalue==2228)
4122            {
4123                m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4124                itr = auraClassScripts.begin();
4125            }
4126            else
4127                ++itr;
4128        }
4129
4130        // generate new name for summon pet
4131        std::string new_name=objmgr.GeneratePetName(petentry);
4132        if(!new_name.empty())
4133            NewSummon->SetName(new_name);
4134    }
4135    else if(NewSummon->getPetType()==HUNTER_PET)
4136        NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4137
4138    NewSummon->AIM_Initialize();
4139    NewSummon->SetHealth(NewSummon->GetMaxHealth());
4140    NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4141
4142    map->Add((Creature*)NewSummon);
4143
4144    m_caster->SetPet(NewSummon);
4145    sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4146
4147    if(m_caster->GetTypeId() == TYPEID_PLAYER)
4148    {
4149        NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4150        ((Player*)m_caster)->PetSpellInitialize();
4151    }
4152}
4153
4154void Spell::EffectLearnPetSpell(uint32 i)
4155{
4156    if(m_caster->GetTypeId() != TYPEID_PLAYER)
4157        return;
4158
4159    Player *_player = (Player*)m_caster;
4160
4161    Pet *pet = _player->GetPet();
4162    if(!pet)
4163        return;
4164    if(!pet->isAlive())
4165        return;
4166
4167    SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4168    if(!learn_spellproto)
4169        return;
4170
4171    pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id));
4172    pet->learnSpell(learn_spellproto->Id);
4173
4174    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4175    _player->PetSpellInitialize();
4176}
4177
4178void Spell::EffectTaunt(uint32 /*i*/)
4179{
4180    // this effect use before aura Taunt apply for prevent taunt already attacking target
4181    // for spell as marked "non effective at already attacking target"
4182    if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4183    {
4184        if(unitTarget->getVictim()==m_caster)
4185        {
4186            SendCastResult(SPELL_FAILED_DONT_REPORT);
4187            return;
4188        }
4189    }
4190
4191    // Also use this effect to set the taunter's threat to the taunted creature's highest value
4192    if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4193        unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4194}
4195
4196void Spell::EffectWeaponDmg(uint32 i)
4197{
4198    if(!unitTarget)
4199        return;
4200    if(!unitTarget->isAlive())
4201        return;
4202
4203    // multiple weapon dmg effect workaround
4204    // execute only the last weapon damage
4205    // and handle all effects at once
4206    for (int j = 0; j < 3; j++)
4207    {
4208        switch(m_spellInfo->Effect[j])
4209        {
4210            case SPELL_EFFECT_WEAPON_DAMAGE:
4211            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4212            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4213            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4214                if (j < i)                                  // we must calculate only at last weapon effect
4215                    return;
4216            break;
4217        }
4218    }
4219
4220    // some spell specific modifiers
4221    bool customBonusDamagePercentMod = false;
4222    float bonusDamagePercentMod  = 1.0f;                    // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4223    float weaponDamagePercentMod = 1.0f;                    // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4224    float totalDamagePercentMod  = 1.0f;                    // applied to final bonus+weapon damage
4225    bool normalized = false;
4226
4227    int32 spell_bonus = 0;                                  // bonus specific for spell
4228    switch(m_spellInfo->SpellFamilyName)
4229    {
4230        case SPELLFAMILY_WARRIOR:
4231        {
4232            // Whirlwind, single only spell with 2 weapon white damage apply if have
4233            if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4234            {
4235                if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4236                    spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4237            }
4238            // Devastate bonus and sunder armor refresh
4239            else if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508)
4240            {
4241                customBonusDamagePercentMod = true;
4242                bonusDamagePercentMod = 0.0f;               // only applied if auras found
4243
4244                Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE);
4245                for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr)
4246                {
4247                    SpellEntry const *proto = (*itr)->GetSpellProto();
4248                    if(proto->SpellVisual == 406 && proto->SpellIconID == 565)
4249                    {
4250                        int32 duration = GetSpellDuration(proto);
4251                        (*itr)->SetAuraDuration(duration);
4252                        (*itr)->UpdateAuraDuration();
4253                        bonusDamagePercentMod += 1.0f;      // +100%
4254                    }
4255                }
4256            }
4257            break;
4258        }
4259        case SPELLFAMILY_ROGUE:
4260        {
4261            // Ambush
4262            if(m_spellInfo->SpellFamilyFlags & 0x00000200LL)
4263            {
4264                customBonusDamagePercentMod = true;
4265                bonusDamagePercentMod = 2.5f;               // 250%
4266            }
4267            // Mutilate (for each hand)
4268            else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4269            {
4270                bool found = false;
4271                // fast check
4272                if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4273                    found = true;
4274                // full aura scan
4275                else
4276                {
4277                    Unit::AuraMap const& auras = unitTarget->GetAuras();
4278                    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4279                    {
4280                        if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4281                        {
4282                            found = true;
4283                            break;
4284                        }
4285                    }
4286                }
4287
4288                if(found)
4289                    totalDamagePercentMod *= 1.5f;          // 150% if poisoned
4290            }
4291            break;
4292        }
4293        case SPELLFAMILY_PALADIN:
4294        {
4295            // Seal of Command - receive benefit from Spell Damage and Healing
4296            if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4297            {
4298                spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4299                spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4300            }
4301            break;
4302        }
4303        case SPELLFAMILY_SHAMAN:
4304        {
4305            // Skyshatter Harness item set bonus
4306            // Stormstrike
4307            if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4308            {
4309                Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4310                for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4311                {
4312                    // Stormstrike AP Buff
4313                    if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4314                    {
4315                        m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4316                        break;
4317                    }
4318                }
4319            }
4320        }
4321    }
4322
4323    int32 fixed_bonus = 0;
4324    for (int j = 0; j < 3; j++)
4325    {
4326        switch(m_spellInfo->Effect[j])
4327        {
4328            case SPELL_EFFECT_WEAPON_DAMAGE:
4329            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4330                fixed_bonus += CalculateDamage(j,unitTarget);
4331                break;
4332            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4333                fixed_bonus += CalculateDamage(j,unitTarget);
4334                normalized = true;
4335                break;
4336            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4337                weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4338
4339                // applied only to prev.effects fixed damage
4340                if(customBonusDamagePercentMod)
4341                    fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod);
4342                else
4343                    fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4344                break;
4345            default:
4346                break;                                      // not weapon damage effect, just skip
4347        }
4348    }
4349
4350    // non-weapon damage
4351    int32 bonus = spell_bonus + fixed_bonus;
4352
4353    // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4354    if(bonus)
4355    {
4356        UnitMods unitMod;
4357        switch(m_attackType)
4358        {
4359            default:
4360            case BASE_ATTACK:   unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4361            case OFF_ATTACK:    unitMod = UNIT_MOD_DAMAGE_OFFHAND;  break;
4362            case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED;   break;
4363        }
4364
4365        float weapon_total_pct  = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4366        bonus = int32(bonus*weapon_total_pct);
4367    }
4368
4369    // + weapon damage with applied weapon% dmg to base weapon damage in call
4370    bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4371
4372    // total damage
4373    bonus = int32(bonus*totalDamagePercentMod);
4374
4375    // prevent negative damage
4376    uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4377
4378    const uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS;
4379
4380    uint32 hitInfo = 0;
4381    VictimState victimState = VICTIMSTATE_NORMAL;
4382    uint32 blocked_dmg = 0;
4383    uint32 absorbed_dmg = 0;
4384    uint32 resisted_dmg = 0;
4385    CleanDamage cleanDamage =  CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
4386
4387    m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell);
4388
4389    if ((hitInfo & nohitMask) && m_attackType != RANGED_ATTACK)  // not send ranged miss/etc
4390        m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchoolMask, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg);
4391
4392    bool criticalhit = (hitInfo & HITINFO_CRITICALHIT);
4393    m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchoolMask, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit);
4394
4395    if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg))
4396    {
4397        eff_damage -= (absorbed_dmg + resisted_dmg + blocked_dmg);
4398    }
4399    else
4400    {
4401        cleanDamage.damage += eff_damage;
4402        eff_damage = 0;
4403    }
4404
4405    // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation
4406    m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true);
4407
4408    // Hemorrhage
4409    if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4410    {
4411        if(m_caster->GetTypeId()==TYPEID_PLAYER)
4412            ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4413    }
4414    // Mangle (Cat): CP
4415    if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4416    {
4417        if(m_caster->GetTypeId()==TYPEID_PLAYER)
4418            ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4419    }
4420
4421
4422    // take ammo
4423    if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4424    {
4425        Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4426
4427        // wands don't have ammo
4428        if(!pItem  || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4429            return;
4430
4431        if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4432        {
4433            if(pItem->GetMaxStackCount()==1)
4434            {
4435                // decrease durability for non-stackable throw weapon
4436                ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4437            }
4438            else
4439            {
4440                // decrease items amount for stackable throw weapon
4441                uint32 count = 1;
4442                ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4443            }
4444        }
4445        else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4446            ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4447    }
4448}
4449
4450void Spell::EffectThreat(uint32 /*i*/)
4451{
4452    if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4453        return;
4454
4455    if(!unitTarget->CanHaveThreatList())
4456        return;
4457
4458    unitTarget->AddThreat(m_caster, float(damage));
4459}
4460
4461void Spell::EffectHealMaxHealth(uint32 /*i*/)
4462{
4463    if(!unitTarget)
4464        return;
4465    if(!unitTarget->isAlive())
4466        return;
4467
4468    uint32 heal = m_caster->GetMaxHealth();
4469
4470    int32 gain = unitTarget->ModifyHealth(heal);
4471    unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
4472
4473    m_caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, heal);
4474}
4475
4476void Spell::EffectInterruptCast(uint32 /*i*/)
4477{
4478    if(!unitTarget)
4479        return;
4480    if(!unitTarget->isAlive())
4481        return;
4482
4483    // TODO: not all spells that used this effect apply cooldown at school spells
4484    // also exist case: apply cooldown to interrupted cast only and to all spells
4485    for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4486    {
4487        if (unitTarget->m_currentSpells[i])
4488        {
4489            // check if we can interrupt spell
4490            if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4491            {
4492                unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4493                unitTarget->InterruptSpell(i,false);
4494            }
4495        }
4496    }
4497}
4498
4499void Spell::EffectSummonObjectWild(uint32 i)
4500{
4501    uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4502
4503    GameObject* pGameObj = new GameObject;
4504
4505    WorldObject* target = focusObject;
4506    if( !target )
4507        target = m_caster;
4508
4509    float x,y,z;
4510    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4511    {
4512        x = m_targets.m_destX;
4513        y = m_targets.m_destY;
4514        z = m_targets.m_destZ;
4515    }
4516    else
4517        m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4518
4519    Map *map = target->GetMap();
4520
4521    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4522        x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4523    {
4524        delete pGameObj;
4525        return;
4526    }
4527
4528    int32 duration = GetSpellDuration(m_spellInfo);
4529    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4530    pGameObj->SetSpellId(m_spellInfo->Id);
4531
4532    if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP)   // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4533        m_caster->AddGameObject(pGameObj);
4534    map->Add(pGameObj);
4535
4536    if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)  //WS
4537    {
4538        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4539        {
4540            Player *pl = (Player*)m_caster;
4541            BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4542            if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4543            {
4544                 uint32 team = ALLIANCE;
4545
4546                 if(pl->GetTeam() == team)
4547                     team = HORDE;
4548
4549                ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4550            }
4551        }
4552    }
4553
4554    if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)  //EY
4555    {
4556        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4557        {
4558            BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4559            if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4560            {
4561                ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4562            }
4563        }
4564    }
4565
4566    if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4567    {
4568        GameObject* linkedGO = new GameObject;
4569        if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4570            x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4571        {
4572            linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4573            linkedGO->SetSpellId(m_spellInfo->Id);
4574
4575            m_caster->AddGameObject(linkedGO);
4576            map->Add(linkedGO);
4577        }
4578        else
4579        {
4580            delete linkedGO;
4581            linkedGO = NULL;
4582            return;
4583        }
4584    }
4585}
4586
4587void Spell::EffectScriptEffect(uint32 effIndex)
4588{
4589    // TODO: we must implement hunter pet summon at login there (spell 6962)
4590
4591    // by spell id
4592    switch(m_spellInfo->Id)
4593    {
4594        // Bending Shinbone
4595        case 8856:
4596        {
4597            if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4598                return;
4599
4600            uint32 spell_id = 0;
4601            switch(urand(1,5))
4602            {
4603                case 1:  spell_id = 8854; break;
4604                default: spell_id = 8855; break;
4605            }
4606
4607            m_caster->CastSpell(m_caster,spell_id,true,NULL);
4608            return;
4609        }
4610
4611        // Healthstone creating spells
4612        case  6201:
4613        case  6202:
4614        case  5699:
4615        case 11729:
4616        case 11730:
4617        case 27230:
4618        {
4619            uint32 itemtype;
4620            uint32 rank = 0;
4621            Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4622            for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4623            {
4624                if((*i)->GetId() == 18692)
4625                {
4626                    rank = 1;
4627                    break;
4628                }
4629                else if((*i)->GetId() == 18693)
4630                {
4631                    rank = 2;
4632                    break;
4633                }
4634            }
4635
4636            static uint32 const itypes[6][3] = {
4637                { 5512,19004,19005},                        // Minor Healthstone
4638                { 5511,19006,19007},                        // Lesser Healthstone
4639                { 5509,19008,19009},                        // Healthstone
4640                { 5510,19010,19011},                        // Greater Healthstone
4641                { 9421,19012,19013},                        // Major Healthstone
4642                {22103,22104,22105}                         // Master Healthstone
4643            };
4644
4645            switch(m_spellInfo->Id)
4646            {
4647                case  6201: itemtype=itypes[0][rank];break; // Minor Healthstone
4648                case  6202: itemtype=itypes[1][rank];break; // Lesser Healthstone
4649                case  5699: itemtype=itypes[2][rank];break; // Healthstone
4650                case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone
4651                case 11730: itemtype=itypes[4][rank];break; // Major Healthstone
4652                case 27230: itemtype=itypes[5][rank];break; // Master Healthstone
4653                default:
4654                    return;
4655            }
4656            DoCreateItem( effIndex, itemtype );
4657            return;
4658        }
4659        // Brittle Armor - need remove one 24575 Brittle Armor aura
4660        case 24590:
4661            unitTarget->RemoveSingleAuraFromStack(24575, 0);
4662            unitTarget->RemoveSingleAuraFromStack(24575, 1);
4663            return;
4664        // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4665        case 26465:
4666            unitTarget->RemoveSingleAuraFromStack(26464, 0);
4667            return;
4668        // Orb teleport spells
4669        case 25140:
4670        case 25143:
4671        case 25650:
4672        case 25652:
4673        case 29128:
4674        case 29129:
4675        case 35376:
4676        case 35727:
4677        {
4678            if(!unitTarget)
4679                return;
4680
4681            uint32 spellid;
4682            switch(m_spellInfo->Id)
4683            {
4684                case 25140: spellid =  32571; break;
4685                case 25143: spellid =  32572; break;
4686                case 25650: spellid =  30140; break;
4687                case 25652: spellid =  30141; break;
4688                case 29128: spellid =  32568; break;
4689                case 29129: spellid =  32569; break;
4690                case 35376: spellid =  25649; break;
4691                case 35727: spellid =  35730; break;
4692                default:
4693                    return;
4694            }
4695
4696            unitTarget->CastSpell(unitTarget,spellid,false);
4697            return;
4698        }
4699
4700        // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4701        case 22539:
4702        case 22972:
4703        case 22975:
4704        case 22976:
4705        case 22977:
4706        case 22978:
4707        case 22979:
4708        case 22980:
4709        case 22981:
4710        case 22982:
4711        case 22983:
4712        case 22984:
4713        case 22985:
4714        {
4715            if(!unitTarget || !unitTarget->isAlive())
4716                return;
4717
4718            // Onyxia Scale Cloak
4719            if(unitTarget->GetDummyAura(22683))
4720                return;
4721
4722            // Shadow Flame
4723            m_caster->CastSpell(unitTarget, 22682, true);
4724            return;
4725        }
4726        break;
4727
4728        // Summon Black Qiraji Battle Tank
4729        case 26656:
4730        {
4731            if(!unitTarget)
4732                return;
4733
4734            // Prevent stacking of mounts
4735            unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4736
4737            // Two separate mounts depending on area id (allows use both in and out of specific instance)
4738            if (unitTarget->GetAreaId() == 3428)
4739                unitTarget->CastSpell(unitTarget, 25863, false);
4740            else
4741                unitTarget->CastSpell(unitTarget, 26655, false);
4742            break;
4743        }
4744        // Piccolo of the Flaming Fire
4745        case 17512:
4746        {
4747            if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4748                return;
4749            unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4750            break;
4751        }
4752
4753        // Netherbloom
4754        case 28702:
4755        {
4756            if(!unitTarget)
4757                return;
4758            // 25% chance of casting a random buff
4759            if(roll_chance_i(75))
4760                return;
4761
4762            // triggered spells are 28703 to 28707
4763            // Note: some sources say, that there was the possibility of
4764            //       receiving a debuff. However, this seems to be removed by a patch.
4765            const uint32 spellid = 28703;
4766
4767            // don't overwrite an existing aura
4768            for(uint8 i=0; i<5; i++)
4769                if(unitTarget->HasAura(spellid+i, 0))
4770                    return;
4771            unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
4772            break;
4773        }
4774
4775        // Nightmare Vine
4776        case 28720:
4777        {
4778            if(!unitTarget)
4779                return;
4780            // 25% chance of casting Nightmare Pollen
4781            if(roll_chance_i(75))
4782                return;
4783            unitTarget->CastSpell(unitTarget, 28721, true);
4784            break;
4785        }
4786
4787        // Mirren's Drinking Hat
4788        case 29830:
4789        {
4790            uint32 item = 0;
4791            switch ( urand(1,6) )
4792            {
4793                case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager
4794                case 4: case 5:         item = 23585; break;// Stouthammer Lite
4795                case 6:                 item = 23586; break;// Aerie Peak Pale Ale
4796            }
4797            if (item)
4798                DoCreateItem(effIndex,item);
4799            break;
4800        }
4801        // Improved Sprint
4802        case 30918:
4803        {
4804            // Removes snares and roots.
4805            uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4806            Unit::AuraMap& Auras = unitTarget->GetAuras();
4807            for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4808            {
4809                next = iter;
4810                ++next;
4811                Aura *aur = iter->second;
4812                if (!aur->IsPositive())             //only remove negative spells
4813                {
4814                    // check for mechanic mask
4815                    if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4816                    {
4817                        unitTarget->RemoveAurasDueToSpell(aur->GetId());
4818                        if(Auras.empty())
4819                            break;
4820                        else
4821                            next = Auras.begin();
4822                    }
4823                }
4824            }
4825            break;
4826        }
4827
4828        // Goblin Weather Machine
4829        case 46203:
4830        {
4831            if(!unitTarget)
4832                return;
4833
4834            uint32 spellId;
4835            switch(rand()%4)
4836            {
4837                case 0:
4838                    spellId=46740;
4839                    break;
4840                case 1:
4841                    spellId=46739;
4842                    break;
4843                case 2:
4844                    spellId=46738;
4845                    break;
4846                case 3:
4847                    spellId=46736;
4848                    break;
4849            }
4850            unitTarget->CastSpell(unitTarget, spellId, true);
4851            break;
4852        }
4853
4854    }
4855
4856    if(!unitTarget || !unitTarget->isAlive()) // can we remove this check?
4857    {
4858        sLog.outError("Spell %u in EffectScriptEffect does not have unitTarget", m_spellInfo->Id);
4859        return;
4860    }
4861
4862    switch(m_spellInfo->Id)
4863    {
4864        // Dreaming Glory
4865        case 28698: unitTarget->CastSpell(unitTarget, 28694, true); break;
4866        // Needle Spine
4867        //case 39835: unitTarget->CastSpell(unitTarget, 39968, true); break;
4868        // Draw Soul
4869        case 40904: unitTarget->CastSpell(m_caster, 40903, true); break;
4870        // Flame Crash
4871        //case 41126: unitTarget->CastSpell(unitTarget, 41131, true); break;
4872        case 41931:
4873        {
4874            int bag=19;
4875            int slot=0;
4876            Item* item = NULL;
4877           
4878            while (bag < 256)
4879            {
4880                item = ((Player*)m_caster)->GetItemByPos(bag,slot);
4881                if (item && item->GetEntry() == 38587) break;
4882                slot++;
4883                if (slot == 39)
4884                {
4885                    slot = 0;
4886                    bag++;
4887                }
4888            }
4889            if (bag < 256)
4890            {
4891                if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true);
4892                else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1);
4893                // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen)
4894                m_caster->CastSpell(m_caster,42518,true);
4895                return;
4896            }
4897        }
4898        // Force Cast - Portal Effect: Sunwell Isle
4899        case 44876: unitTarget->CastSpell(unitTarget, 44870, true); break;
4900        //5,000 Gold
4901        case 46642:
4902        {
4903            if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4904                ((Player*)unitTarget)->ModifyMoney(50000000);
4905            break;
4906        }
4907    }
4908
4909    if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
4910    {
4911        switch(m_spellInfo->SpellFamilyFlags)
4912        {
4913            // Judgement
4914            case 0x800000:
4915            {
4916                uint32 spellId2 = 0;
4917
4918                // all seals have aura dummy
4919                Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4920                for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
4921                {
4922                    SpellEntry const *spellInfo = (*itr)->GetSpellProto();
4923
4924                    // search seal (all seals have judgement's aura dummy spell id in 2 effect
4925                    if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 )
4926                        continue;
4927
4928                    // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
4929                    spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1;
4930
4931                    if(spellId2 <= 1)
4932                        continue;
4933
4934                    // found, remove seal
4935                    m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4936
4937                    // Sanctified Judgement
4938                    Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4939                    for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i)
4940                    {
4941                        if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL)
4942                        {
4943                            int32 chance = (*i)->GetModifier()->m_amount;
4944                            if ( roll_chance_i(chance) )
4945                            {
4946                                int32 mana = spellInfo->manaCost;
4947                                if ( Player* modOwner = m_caster->GetSpellModOwner() )
4948                                    modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana);
4949                                mana = int32(mana* 0.8f);
4950                                m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i);
4951                            }
4952                            break;
4953                        }
4954                    }
4955
4956                    break;
4957                }
4958
4959                m_caster->CastSpell(unitTarget,spellId2,true);
4960                return;
4961            }
4962        }
4963    }
4964
4965    // normal DB scripted effect
4966    sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
4967    sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
4968}
4969
4970void Spell::EffectSanctuary(uint32 /*i*/)
4971{
4972    if(!unitTarget)
4973        return;
4974    //unitTarget->CombatStop();
4975
4976    unitTarget->CombatStop();
4977    unitTarget->getHostilRefManager().deleteReferences();   // stop all fighting
4978    // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4979    if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
4980    {
4981        ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4982    }
4983}
4984
4985void Spell::EffectAddComboPoints(uint32 /*i*/)
4986{
4987    if(!unitTarget)
4988        return;
4989
4990    if(m_caster->GetTypeId() != TYPEID_PLAYER)
4991        return;
4992
4993    if(damage <= 0)
4994        return;
4995
4996    ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
4997}
4998
4999void Spell::EffectDuel(uint32 i)
5000{
5001    if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5002        return;
5003
5004    Player *caster = (Player*)m_caster;
5005    Player *target = (Player*)unitTarget;
5006
5007    // caster or target already have requested duel
5008    if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5009        return;
5010
5011    // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5012    // Don't have to check the target's map since you cannot challenge someone across maps
5013    if( caster->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530)
5014    {
5015        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
5016        return;
5017    }
5018
5019    AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5020    if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5021    {
5022        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
5023        return;
5024    }
5025
5026    AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5027    if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5028    {
5029        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
5030        return;
5031    }
5032
5033    //CREATE DUEL FLAG OBJECT
5034    GameObject* pGameObj = new GameObject;
5035
5036    uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5037
5038    Map *map = m_caster->GetMap();
5039    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
5040        m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5041        m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5042        m_caster->GetPositionZ(),
5043        m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1))
5044    {
5045        delete pGameObj;
5046        return;
5047    }
5048
5049    pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5050    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5051    int32 duration = GetSpellDuration(m_spellInfo);
5052    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5053    pGameObj->SetSpellId(m_spellInfo->Id);
5054
5055    m_caster->AddGameObject(pGameObj);
5056    map->Add(pGameObj);
5057    //END
5058
5059    // Send request
5060    WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5061    data << pGameObj->GetGUID();
5062    data << caster->GetGUID();
5063    caster->GetSession()->SendPacket(&data);
5064    target->GetSession()->SendPacket(&data);
5065
5066    // create duel-info
5067    DuelInfo *duel   = new DuelInfo;
5068    duel->initiator  = caster;
5069    duel->opponent   = target;
5070    duel->startTime  = 0;
5071    duel->startTimer = 0;
5072    caster->duel     = duel;
5073
5074    DuelInfo *duel2   = new DuelInfo;
5075    duel2->initiator  = caster;
5076    duel2->opponent   = caster;
5077    duel2->startTime  = 0;
5078    duel2->startTimer = 0;
5079    target->duel      = duel2;
5080
5081    caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5082    target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5083}
5084
5085void Spell::EffectStuck(uint32 /*i*/)
5086{
5087    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5088        return;
5089
5090    if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5091        return;
5092
5093    Player* pTarget = (Player*)unitTarget;
5094
5095    sLog.outDebug("Spell Effect: Stuck");
5096    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());
5097
5098    if(pTarget->isInFlight())
5099        return;
5100
5101    // homebind location is loaded always
5102    pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5103
5104    // Stuck spell trigger Hearthstone cooldown
5105    SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5106    if(!spellInfo)
5107        return;
5108    Spell spell(pTarget,spellInfo,true,0);
5109    spell.SendSpellCooldown();
5110}
5111
5112void Spell::EffectSummonPlayer(uint32 /*i*/)
5113{
5114    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5115        return;
5116
5117    // Evil Twin (ignore player summon, but hide this for summoner)
5118    if(unitTarget->GetDummyAura(23445))
5119        return;
5120
5121    float x,y,z;
5122    m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5123
5124    ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5125
5126    WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5127    data << uint64(m_caster->GetGUID());                    // summoner guid
5128    data << uint32(m_caster->GetZoneId());                  // summoner zone
5129    data << uint32(MAX_PLAYER_SUMMON_DELAY*1000);           // auto decline after msecs
5130    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5131}
5132
5133static ScriptInfo generateActivateCommand()
5134{
5135    ScriptInfo si;
5136    si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5137    return si;
5138}
5139
5140void Spell::EffectActivateObject(uint32 effect_idx)
5141{
5142    if(!gameObjTarget)
5143        return;
5144
5145    static ScriptInfo activateCommand = generateActivateCommand();
5146
5147    int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5148
5149    sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5150}
5151
5152void Spell::EffectSummonTotem(uint32 i)
5153{
5154    uint8 slot = 0;
5155    switch(m_spellInfo->EffectMiscValueB[i])
5156    {
5157        case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5158        case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5159        case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5160        case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5161        // Battle standard case
5162        case SUMMON_TYPE_TOTEM:       slot = 254; break;
5163        // jewelery statue case, like totem without slot
5164        case SUMMON_TYPE_GUARDIAN:    slot = 255; break;
5165        default: return;
5166    }
5167
5168    if(slot < MAX_TOTEM)
5169    {
5170        uint64 guid = m_caster->m_TotemSlot[slot];
5171        if(guid != 0)
5172        {
5173            Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5174            if(OldTotem && OldTotem->isTotem())
5175                ((Totem*)OldTotem)->UnSummon();
5176        }
5177    }
5178
5179    uint32 team = 0;
5180    if (m_caster->GetTypeId()==TYPEID_PLAYER)
5181        team = ((Player*)m_caster)->GetTeam();
5182
5183    Totem* pTotem = new Totem;
5184
5185    if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team ))
5186    {
5187        delete pTotem;
5188        return;
5189    }
5190
5191    float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5192
5193    float x,y,z;
5194    m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5195
5196    // totem must be at same Z in case swimming caster and etc.
5197    if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5198        z = m_caster->GetPositionZ();
5199
5200    pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5201
5202    if(slot < MAX_TOTEM)
5203        m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5204
5205    pTotem->SetOwner(m_caster->GetGUID());
5206    pTotem->SetTypeBySummonSpell(m_spellInfo);              // must be after Create call where m_spells initilized
5207
5208    int32 duration=GetSpellDuration(m_spellInfo);
5209    if(Player* modOwner = m_caster->GetSpellModOwner())
5210        modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5211    pTotem->SetDuration(duration);
5212
5213    if (damage)                                             // if not spell info, DB values used
5214    {
5215        pTotem->SetMaxHealth(damage);
5216        pTotem->SetHealth(damage);
5217    }
5218
5219    pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5220    pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5221
5222    pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true);
5223    pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true);
5224
5225    pTotem->Summon(m_caster);
5226
5227    if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5228    {
5229        WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5230        data << uint8(slot);
5231        data << uint64(pTotem->GetGUID());
5232        data << uint32(duration);
5233        data << uint32(m_spellInfo->Id);
5234        ((Player*)m_caster)->SendDirectMessage(&data);
5235    }
5236}
5237
5238void Spell::EffectEnchantHeldItem(uint32 i)
5239{
5240    // this is only item spell effect applied to main-hand weapon of target player (players in area)
5241    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5242        return;
5243
5244    Player* item_owner = (Player*)unitTarget;
5245    Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5246
5247    if(!item )
5248        return;
5249
5250    // must be equipped
5251    if(!item ->IsEquipped())
5252        return;
5253
5254    if (m_spellInfo->EffectMiscValue[i])
5255    {
5256        uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5257        int32 duration = GetSpellDuration(m_spellInfo);          //Try duration index first ..
5258        if(!duration)
5259            duration = m_currentBasePoints[i]+1;            //Base points after ..
5260        if(!duration)
5261            duration = 10;                                  //10 seconds for enchants which don't have listed duration
5262
5263        SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5264        if(!pEnchant)
5265            return;
5266
5267        // Always go to temp enchantment slot
5268        EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5269
5270        // Enchantment will not be applied if a different one already exists
5271        if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5272            return;
5273
5274        // Apply the temporary enchantment
5275        item->SetEnchantment(slot, enchant_id, duration*1000, 0);
5276        item_owner->ApplyEnchantment(item,slot,true);
5277    }
5278}
5279
5280void Spell::EffectDisEnchant(uint32 /*i*/)
5281{
5282    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5283        return;
5284
5285    Player* p_caster = (Player*)m_caster;
5286    if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5287        return;
5288
5289    p_caster->UpdateCraftSkill(m_spellInfo->Id);
5290
5291    ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5292
5293    // item will be removed at disenchanting end
5294}
5295
5296void Spell::EffectInebriate(uint32 /*i*/)
5297{
5298    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5299        return;
5300
5301    Player *player = (Player*)unitTarget;
5302    uint16 currentDrunk = player->GetDrunkValue();
5303    uint16 drunkMod = damage * 256;
5304    if (currentDrunk + drunkMod > 0xFFFF)
5305        currentDrunk = 0xFFFF;
5306    else
5307        currentDrunk += drunkMod;
5308    player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5309}
5310
5311void Spell::EffectFeedPet(uint32 i)
5312{
5313    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5314        return;
5315
5316    Player *_player = (Player*)m_caster;
5317
5318    if(!itemTarget)
5319        return;
5320
5321    Pet *pet = _player->GetPet();
5322    if(!pet)
5323        return;
5324
5325    if(!pet->isAlive())
5326        return;
5327
5328    int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel);
5329    if(benefit <= 0)
5330        return;
5331
5332    uint32 count = 1;
5333    _player->DestroyItemCount(itemTarget,count,true);
5334    // TODO: fix crash when a spell has two effects, both pointed at the same item target
5335
5336    m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5337}
5338
5339void Spell::EffectDismissPet(uint32 /*i*/)
5340{
5341    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5342        return;
5343
5344    Pet* pet = m_caster->GetPet();
5345
5346    // not let dismiss dead pet
5347    if(!pet||!pet->isAlive())
5348        return;
5349
5350    ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5351}
5352
5353void Spell::EffectSummonObject(uint32 i)
5354{
5355    uint32 go_id = m_spellInfo->EffectMiscValue[i];
5356
5357    uint8 slot = 0;
5358    switch(m_spellInfo->Effect[i])
5359    {
5360        case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5361        case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5362        case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5363        case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5364        default: return;
5365    }
5366
5367    uint64 guid = m_caster->m_ObjectSlot[slot];
5368    if(guid != 0)
5369    {
5370        GameObject* obj = NULL;
5371        if( m_caster )
5372            obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5373
5374        if(obj) obj->Delete();
5375        m_caster->m_ObjectSlot[slot] = 0;
5376    }
5377
5378    GameObject* pGameObj = new GameObject;
5379
5380    float rot2 = sin(m_caster->GetOrientation()/2);
5381    float rot3 = cos(m_caster->GetOrientation()/2);
5382
5383    float x,y,z;
5384    // If dest location if present
5385    if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5386    {
5387        x = m_targets.m_destX;
5388        y = m_targets.m_destY;
5389        z = m_targets.m_destZ;
5390    }
5391    // Summon in random point all other units if location present
5392    else
5393        m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5394
5395    Map *map = m_caster->GetMap();
5396    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
5397    {
5398        delete pGameObj;
5399        return;
5400    }
5401
5402    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5403    int32 duration = GetSpellDuration(m_spellInfo);
5404    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5405    pGameObj->SetSpellId(m_spellInfo->Id);
5406    m_caster->AddGameObject(pGameObj);
5407
5408    map->Add(pGameObj);
5409    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5410    data << pGameObj->GetGUID();
5411    m_caster->SendMessageToSet(&data,true);
5412
5413    m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5414}
5415
5416void Spell::EffectResurrect(uint32 i)
5417{
5418    if(!unitTarget)
5419        return;
5420    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5421        return;
5422
5423    if(unitTarget->isAlive())
5424        return;
5425    if(!unitTarget->IsInWorld())
5426        return;
5427
5428    switch (m_spellInfo->Id)
5429    {
5430        // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5431        case 8342:
5432            if (roll_chance_i(67))
5433            {
5434                m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5435                return;
5436            }
5437            break;
5438        // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5439        case 22999:
5440            if (roll_chance_i(50))
5441            {
5442                m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5443                return;
5444            }
5445            break;
5446        default:
5447            break;
5448    }
5449
5450    Player* pTarget = ((Player*)unitTarget);
5451
5452    if(pTarget->isRessurectRequested())       // already have one active request
5453        return;
5454
5455    uint32 health = pTarget->GetMaxHealth() * damage / 100;
5456    uint32 mana   = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5457
5458    pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5459    SendResurrectRequest(pTarget);
5460}
5461
5462void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5463{
5464    if(!unitTarget || !unitTarget->isAlive())
5465        return;
5466
5467    if( unitTarget->m_extraAttacks )
5468        return;
5469
5470    unitTarget->m_extraAttacks = damage;
5471}
5472
5473void Spell::EffectParry(uint32 /*i*/)
5474{
5475    if (unitTarget->GetTypeId() == TYPEID_PLAYER)
5476    {
5477        ((Player*)unitTarget)->SetCanParry(true);
5478    }
5479}
5480
5481void Spell::EffectBlock(uint32 /*i*/)
5482{
5483    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
5484        return;
5485
5486    ((Player*)unitTarget)->SetCanBlock(true);
5487}
5488
5489void Spell::EffectMomentMove(uint32 i)
5490{
5491    if(unitTarget->isInFlight())
5492        return;
5493
5494    if(!m_targets.HasDest())
5495        return;
5496
5497    uint32 mapid = unitTarget->GetMapId();
5498    float ox,oy,oz;
5499    unitTarget->GetPosition(ox,oy,oz);
5500
5501    float fx,fy,fz;                                  // getObjectHitPos overwrite last args in any result case
5502    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))
5503        unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5504
5505    if(unitTarget->GetTypeId() == TYPEID_PLAYER)
5506        ((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));
5507    else
5508        MapManager::Instance().GetMap(mapid, unitTarget)->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
5509}
5510
5511void Spell::EffectReputation(uint32 i)
5512{
5513    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5514        return;
5515
5516    Player *_player = (Player*)unitTarget;
5517
5518    int32  rep_change = m_currentBasePoints[i]+1;           // field store reputation change -1
5519
5520    uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5521
5522    FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5523
5524    if(!factionEntry)
5525        return;
5526
5527    _player->ModifyFactionReputation(factionEntry,rep_change);
5528}
5529
5530void Spell::EffectQuestComplete(uint32 i)
5531{
5532    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5533        return;
5534
5535    Player *_player = (Player*)m_caster;
5536
5537    uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5538    _player->AreaExploredOrEventHappens(quest_id);
5539}
5540
5541void Spell::EffectSelfResurrect(uint32 i)
5542{
5543    if(!unitTarget || unitTarget->isAlive())
5544        return;
5545    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5546        return;
5547    if(!unitTarget->IsInWorld())
5548        return;
5549
5550    uint32 health = 0;
5551    uint32 mana = 0;
5552
5553    // flat case
5554    if(damage < 0)
5555    {
5556        health = uint32(-damage);
5557        mana = m_spellInfo->EffectMiscValue[i];
5558    }
5559    // percent case
5560    else
5561    {
5562        health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5563        if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5564            mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5565    }
5566
5567    Player *plr = ((Player*)unitTarget);
5568    plr->ResurrectPlayer(0.0f);
5569
5570    plr->SetHealth( health );
5571    plr->SetPower(POWER_MANA, mana );
5572    plr->SetPower(POWER_RAGE, 0 );
5573    plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5574
5575    plr->SpawnCorpseBones();
5576
5577    plr->SaveToDB();
5578}
5579
5580void Spell::EffectSkinning(uint32 /*i*/)
5581{
5582    if(unitTarget->GetTypeId() != TYPEID_UNIT )
5583        return;
5584    if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5585        return;
5586
5587    Creature* creature = (Creature*) unitTarget;
5588    int32 targetLevel = creature->getLevel();
5589
5590    uint32 skill = creature->GetCreatureInfo()->GetRequiredLootSkill(); 
5591
5592    ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5593    creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5594
5595    int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5596
5597    int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5598
5599    // Double chances for elites
5600    ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5601}
5602
5603void Spell::EffectCharge(uint32 /*i*/)
5604{
5605    if(!unitTarget || !m_caster)
5606        return;
5607
5608    float x, y, z;
5609    unitTarget->GetContactPoint(m_caster, x, y, z);
5610    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5611        ((Creature *)unitTarget)->StopMoving();
5612
5613    // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5614    m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5615
5616    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5617        MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5618
5619    // not all charge effects used in negative spells
5620    if ( !IsPositiveSpell(m_spellInfo->Id))
5621        m_caster->Attack(unitTarget,true);
5622}
5623
5624void Spell::EffectSummonCritter(uint32 i)
5625{
5626    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5627        return;
5628    Player* player = (Player*)m_caster;
5629
5630    uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5631    if(!pet_entry)
5632        return;
5633
5634    Pet* old_critter = player->GetMiniPet();
5635
5636    // for same pet just despawn
5637    if(old_critter && old_critter->GetEntry() == pet_entry)
5638    {
5639        player->RemoveMiniPet();
5640        return;
5641    }
5642
5643    // despawn old pet before summon new
5644    if(old_critter)
5645        player->RemoveMiniPet();
5646
5647    // summon new pet
5648    Pet* critter = new Pet(MINI_PET);
5649
5650    Map *map = m_caster->GetMap();
5651    uint32 pet_number = objmgr.GeneratePetNumber();
5652    if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),
5653        map, pet_entry, pet_number))
5654    {
5655        sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5656        delete critter;
5657        return;
5658    }
5659
5660    float x,y,z;
5661    // If dest location if present
5662    if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5663    {
5664         x = m_targets.m_destX;
5665         y = m_targets.m_destY;
5666         z = m_targets.m_destZ;
5667     }
5668     // Summon if dest location not present near caster
5669     else
5670         m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5671
5672    critter->Relocate(x,y,z,m_caster->GetOrientation());
5673
5674    if(!critter->IsPositionValid())
5675    {
5676        sLog.outError("ERROR: Pet (guidlow %d, entry %d) not summoned. Suggested coordinates isn't valid (X: %d Y: ^%d)", critter->GetGUIDLow(), critter->GetEntry(), critter->GetPositionX(), critter->GetPositionY());
5677        delete critter;
5678        return;
5679    }
5680
5681    critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
5682    critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID());
5683    critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5684    critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5685
5686    critter->AIM_Initialize();
5687    critter->InitPetCreateSpells();                         // e.g. disgusting oozeling has a create spell as critter...
5688    critter->SetMaxHealth(1);
5689    critter->SetHealth(1);
5690    critter->SetLevel(1);
5691
5692    // set timer for unsummon
5693    int32 duration = GetSpellDuration(m_spellInfo);
5694    if(duration > 0)
5695        critter->SetDuration(duration);
5696
5697    std::string name = player->GetName();
5698    name.append(petTypeSuffix[critter->getPetType()]);
5699    critter->SetName( name );
5700    player->SetMiniPet(critter);
5701
5702    map->Add((Creature*)critter);
5703}
5704
5705void Spell::EffectKnockBack(uint32 i)
5706{
5707    if(!unitTarget || !m_caster)
5708        return;
5709
5710    // Effect only works on players
5711    if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5712        return;
5713
5714    float vsin = sin(m_caster->GetAngle(unitTarget));
5715    float vcos = cos(m_caster->GetAngle(unitTarget));
5716
5717    WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5718    data.append(unitTarget->GetPackGUID());
5719    data << uint32(0);                                      // Sequence
5720    data << float(vcos);                                    // x direction
5721    data << float(vsin);                                    // y direction
5722    data << float(m_spellInfo->EffectMiscValue[i])/10;      // Horizontal speed
5723    data << float(damage/-10);                              // Z Movement speed (vertical)
5724
5725    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5726}
5727
5728void Spell::EffectSendTaxi(uint32 i)
5729{
5730    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5731        return;
5732
5733    TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5734    if(!entry)
5735        return;
5736
5737    std::vector<uint32> nodes;
5738
5739    nodes.resize(2);
5740    nodes[0] = entry->from;
5741    nodes[1] = entry->to;
5742
5743    uint32 mountid = 0;
5744    switch(m_spellInfo->Id)
5745    {
5746        case 31606:       //Stormcrow Amulet
5747            mountid = 17447;
5748            break;
5749        case 45071:      //Quest - Sunwell Daily - Dead Scar Bombing Run
5750        case 45113:      //Quest - Sunwell Daily - Ship Bombing Run
5751        case 45353:      //Quest - Sunwell Daily - Ship Bombing Run Return
5752            mountid = 22840;
5753            break;
5754        case 34905:      //Stealth Flight
5755            mountid = 6851;
5756            break;
5757    }
5758
5759    ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
5760
5761}
5762
5763void Spell::EffectPlayerPull(uint32 i)
5764{
5765    if(!unitTarget || !m_caster)
5766        return;
5767
5768    // Effect only works on players
5769    if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5770        return;
5771
5772    float vsin = sin(unitTarget->GetAngle(m_caster));
5773    float vcos = cos(unitTarget->GetAngle(m_caster));
5774
5775    WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5776    data.append(unitTarget->GetPackGUID());
5777    data << uint32(0);                                      // Sequence
5778    data << float(vcos);                                    // x direction
5779    data << float(vsin);                                    // y direction
5780                                                            // Horizontal speed
5781    data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
5782    data << float(m_spellInfo->EffectMiscValue[i])/-10;     // Z Movement speed
5783
5784    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5785}
5786
5787void Spell::EffectDispelMechanic(uint32 i)
5788{
5789    if(!unitTarget)
5790        return;
5791
5792    uint32 mechanic = m_spellInfo->EffectMiscValue[i];
5793
5794    Unit::AuraMap& Auras = unitTarget->GetAuras();
5795    for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
5796    {
5797        next = iter;
5798        ++next;
5799        SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
5800        if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
5801        {
5802            unitTarget->RemoveAurasDueToSpell(spell->Id);
5803            if(Auras.empty())
5804                break;
5805            else
5806                next = Auras.begin();
5807        }
5808    }
5809    return;
5810}
5811
5812void Spell::EffectSummonDeadPet(uint32 /*i*/)
5813{
5814    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5815        return;
5816    Player *_player = (Player*)m_caster;
5817    Pet *pet = _player->GetPet();
5818    if(!pet)
5819        return;
5820    if(pet->isAlive())
5821        return;
5822    if(damage < 0)
5823        return;
5824    pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
5825    pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5826    pet->setDeathState( ALIVE );
5827    pet->clearUnitState(UNIT_STAT_ALL_STATE);
5828    pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
5829
5830    pet->AIM_Initialize();
5831
5832    _player->PetSpellInitialize();
5833    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
5834}
5835
5836void Spell::EffectDestroyAllTotems(uint32 /*i*/)
5837{
5838    float mana = 0;
5839    for(int slot = 0;  slot < MAX_TOTEM; ++slot)
5840    {
5841        if(!m_caster->m_TotemSlot[slot])
5842            continue;
5843
5844        Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
5845        if(totem && totem->isTotem())
5846        {
5847            uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
5848            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
5849            if(spellInfo)
5850                mana += spellInfo->manaCost * damage / 100;
5851            ((Totem*)totem)->UnSummon();
5852        }
5853    }
5854
5855    int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
5856    m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
5857}
5858
5859void Spell::EffectDurabilityDamage(uint32 i)
5860{
5861    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5862        return;
5863
5864    int32 slot = m_spellInfo->EffectMiscValue[i];
5865
5866    // FIXME: some spells effects have value -1/-2
5867    // Possibly its mean -1 all player equipped items and -2 all items
5868    if(slot < 0)
5869    {
5870        ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
5871        return;
5872    }
5873
5874    // invalid slot value
5875    if(slot >= INVENTORY_SLOT_BAG_END)
5876        return;
5877
5878    if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5879        ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
5880}
5881
5882void Spell::EffectDurabilityDamagePCT(uint32 i)
5883{
5884    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5885        return;
5886
5887    int32 slot = m_spellInfo->EffectMiscValue[i];
5888
5889    // FIXME: some spells effects have value -1/-2
5890    // Possibly its mean -1 all player equipped items and -2 all items
5891    if(slot < 0)
5892    {
5893        ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
5894        return;
5895    }
5896
5897    // invalid slot value
5898    if(slot >= INVENTORY_SLOT_BAG_END)
5899        return;
5900
5901    if(damage <= 0)
5902        return;
5903
5904    if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5905        ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
5906}
5907
5908void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
5909{
5910    if(!unitTarget)
5911        return;
5912
5913    unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
5914}
5915
5916void Spell::EffectTransmitted(uint32 effIndex)
5917{
5918    uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
5919
5920    GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
5921
5922    if (!goinfo)
5923    {
5924        sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
5925        return;
5926    }
5927
5928    float fx,fy,fz;
5929
5930    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5931    {
5932        fx = m_targets.m_destX;
5933        fy = m_targets.m_destY;
5934        fz = m_targets.m_destZ;
5935    }
5936    //FIXME: this can be better check for most objects but still hack
5937    else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
5938    {
5939        float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
5940        m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5941    }
5942    else
5943    {
5944        float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5945        float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5946        float dis = rand_norm() * (max_dis - min_dis) + min_dis;
5947
5948        m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5949    }
5950
5951    Map *cMap = m_caster->GetMap();
5952
5953    if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
5954    {
5955        if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
5956        { // but this is not proper, we really need to ignore not materialized objects
5957            SendCastResult(SPELL_FAILED_NOT_HERE);
5958            SendChannelUpdate(0);
5959            return;
5960        }
5961
5962        // replace by water level in this case
5963        fz = cMap->GetWaterLevel(fx,fy);
5964    }
5965    // if gameobject is summoning object, it should be spawned right on caster's position
5966    else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
5967    {
5968        m_caster->GetPosition(fx,fy,fz);
5969    }
5970
5971    GameObject* pGameObj = new GameObject;
5972
5973    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
5974        fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
5975    {
5976        delete pGameObj;
5977        return;
5978    }
5979
5980    int32 duration = GetSpellDuration(m_spellInfo);
5981
5982    switch(goinfo->type)
5983    {
5984        case GAMEOBJECT_TYPE_FISHINGNODE:
5985        {
5986            m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
5987                                                            // Orientation3
5988            pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 );
5989                                                            // Orientation4
5990            pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 );
5991            m_caster->AddGameObject(pGameObj);              // will removed at spell cancel
5992
5993            // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
5994            // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
5995            int32 lastSec;
5996            switch(urand(0, 3))
5997            {
5998                case 0: lastSec =  3; break;
5999                case 1: lastSec =  7; break;
6000                case 2: lastSec = 13; break;
6001                case 3: lastSec = 17; break;
6002            }
6003
6004            duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000;
6005            break;
6006        }
6007        case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6008        {
6009            if(m_caster->GetTypeId()==TYPEID_PLAYER)
6010            {
6011                pGameObj->AddUniqueUse((Player*)m_caster);
6012                m_caster->AddGameObject(pGameObj);          // will removed at spell cancel
6013            }
6014            break;
6015        }
6016        case GAMEOBJECT_TYPE_FISHINGHOLE:
6017        case GAMEOBJECT_TYPE_CHEST:
6018        default:
6019        {
6020            break;
6021        }
6022    }
6023
6024    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6025
6026    pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6027
6028    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6029    pGameObj->SetSpellId(m_spellInfo->Id);
6030
6031    DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6032    //m_caster->AddGameObject(pGameObj);
6033    //m_ObjToDel.push_back(pGameObj);
6034
6035    cMap->Add(pGameObj);
6036
6037    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6038    data << uint64(pGameObj->GetGUID());
6039    m_caster->SendMessageToSet(&data,true);
6040
6041    if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6042    {
6043        GameObject* linkedGO = new GameObject;
6044        if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6045            fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6046        {
6047            linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6048            linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6049            linkedGO->SetSpellId(m_spellInfo->Id);
6050            linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6051
6052            MapManager::Instance().GetMap(linkedGO->GetMapId(), linkedGO)->Add(linkedGO);
6053        }
6054        else
6055        {
6056            delete linkedGO;
6057            linkedGO = NULL;
6058            return;
6059        }
6060    }
6061}
6062
6063void Spell::EffectProspecting(uint32 /*i*/)
6064{
6065    if(m_caster->GetTypeId() != TYPEID_PLAYER)
6066        return;
6067
6068    Player* p_caster = (Player*)m_caster;
6069    if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6070        return;
6071
6072    if(itemTarget->GetCount() < 5)
6073        return;
6074
6075    if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6076    {
6077        uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6078        uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6079        p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6080    }
6081
6082    ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6083}
6084
6085void Spell::EffectSkill(uint32 /*i*/)
6086{
6087    sLog.outDebug("WORLD: SkillEFFECT");
6088}
6089
6090void Spell::EffectSummonDemon(uint32 i)
6091{
6092    float px = m_targets.m_destX;
6093    float py = m_targets.m_destY;
6094    float pz = m_targets.m_destZ;
6095
6096    Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000);
6097    if (!Charmed)
6098        return;
6099
6100    // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6101    Charmed->SetLevel(m_caster->getLevel());
6102
6103    // TODO: Add damage/mana/hp according to level
6104
6105    if (m_spellInfo->EffectMiscValue[i] == 89)              // Inferno summon
6106    {
6107        // Enslave demon effect, without mana cost and cooldown
6108        m_caster->CastSpell(Charmed, 20882, true);          // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6109
6110        // Inferno effect
6111        Charmed->CastSpell(Charmed, 22703, true, 0);
6112    }
6113}
6114
6115/* There is currently no need for this effect. We handle it in BattleGround.cpp
6116   If we would handle the resurrection here, the spiritguide would instantly disappear as the
6117   player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6118   This is why we use a half sec delay between the visual effect and the resurrection itself */
6119void Spell::EffectSpiritHeal(uint32 /*i*/)
6120{
6121    /*
6122    if(!unitTarget || unitTarget->isAlive())
6123        return;
6124    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6125        return;
6126    if(!unitTarget->IsInWorld())
6127        return;
6128
6129    //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6130    //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6131    ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6132    ((Player*)unitTarget)->SpawnCorpseBones();
6133    */
6134}
6135
6136// remove insignia spell effect
6137void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6138{
6139    sLog.outDebug("Effect: SkinPlayerCorpse");
6140    if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6141        return;
6142
6143    ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6144}
6145
6146void Spell::EffectStealBeneficialBuff(uint32 i)
6147{
6148    sLog.outDebug("Effect: StealBeneficialBuff");
6149
6150    if(!unitTarget || unitTarget==m_caster)                 // can't steal from self
6151        return;
6152
6153    std::vector <Aura *> steal_list;
6154    // Create dispel mask by dispel type
6155    uint32 dispelMask  = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6156    Unit::AuraMap const& auras = unitTarget->GetAuras();
6157    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6158    {
6159        Aura *aur = (*itr).second;
6160        if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6161        {
6162            // Need check for passive? this
6163            if (aur->IsPositive() && !aur->IsPassive())
6164                steal_list.push_back(aur);
6165        }
6166    }
6167    // Ok if exist some buffs for dispel try dispel it
6168    if (!steal_list.empty())
6169    {
6170        std::list < std::pair<uint32,uint64> > success_list;
6171        int32 list_size = steal_list.size();
6172        // Dispell N = damage buffs (or while exist buffs for dispel)
6173        for (int32 count=0; count < damage && list_size > 0; ++count)
6174        {
6175            // Random select buff for dispel
6176            Aura *aur = steal_list[urand(0, list_size-1)];
6177            // Not use chance for steal
6178            // TODO possible need do it
6179            success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6180
6181            // Remove buff from list for prevent doubles
6182            for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6183            {
6184                Aura *stealed = *j;
6185                if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6186                {
6187                    j = steal_list.erase(j);
6188                    --list_size;
6189                }
6190                else
6191                    ++j;
6192            }
6193        }
6194        // Really try steal and send log
6195        if (!success_list.empty())
6196        {
6197            int32 count = success_list.size();
6198            WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6199            data.append(unitTarget->GetPackGUID());  // Victim GUID
6200            data.append(m_caster->GetPackGUID());    // Caster GUID
6201            data << uint32(m_spellInfo->Id);         // Dispell spell id
6202            data << uint8(0);                        // not used
6203            data << uint32(count);                   // count
6204            for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6205            {
6206                SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6207                data << uint32(spellInfo->Id);       // Spell Id
6208                data << uint8(0);                    // 0 - steals !=0 transfers
6209                unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6210            }
6211            m_caster->SendMessageToSet(&data, true);
6212        }
6213    }
6214}
6215
6216void Spell::EffectKillCredit(uint32 i)
6217{
6218    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6219        return;
6220
6221    ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0);
6222}
6223
6224void Spell::EffectQuestFail(uint32 i)
6225{
6226    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6227        return;
6228
6229    ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6230}
Note: See TracBrowser for help on using the browser.