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

Revision 162, 239.3 kB (checked in by yumileroy, 17 years ago)

[svn] Remove a hack on triggered spell target selection.
Some minor fixes.

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