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

Revision 142, 240.5 kB (checked in by yumileroy, 17 years ago)

[svn] Fix teleport spells.
Fix cone spells.
Use interrupt_aura_flag to remove stealth/invisible/feign death auras.

Original author: megamage
Date: 2008-11-01 15:08:12-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "Common.h"
22#include "SharedDefines.h"
23#include "Database/DatabaseEnv.h"
24#include "WorldPacket.h"
25#include "WorldSession.h"
26#include "Opcodes.h"
27#include "Log.h"
28#include "UpdateMask.h"
29#include "World.h"
30#include "ObjectMgr.h"
31#include "SpellMgr.h"
32#include "Player.h"
33#include "SkillExtraItems.h"
34#include "Unit.h"
35#include "CreatureAI.h"
36#include "Spell.h"
37#include "DynamicObject.h"
38#include "SpellAuras.h"
39#include "Group.h"
40#include "UpdateData.h"
41#include "MapManager.h"
42#include "ObjectAccessor.h"
43#include "SharedDefines.h"
44#include "Pet.h"
45#include "GameObject.h"
46#include "GossipDef.h"
47#include "Creature.h"
48#include "Totem.h"
49#include "CreatureAI.h"
50#include "BattleGround.h"
51#include "BattleGroundEY.h"
52#include "BattleGroundWS.h"
53#include "OutdoorPvPMgr.h"
54#include "VMapFactory.h"
55#include "Language.h"
56#include "SocialMgr.h"
57#include "Util.h"
58#include "TemporarySummon.h"
59
60
61pEffect SpellEffects[TOTAL_SPELL_EFFECTS]=
62{
63    &Spell::EffectNULL,                                     //  0
64    &Spell::EffectInstaKill,                                //  1 SPELL_EFFECT_INSTAKILL
65    &Spell::EffectSchoolDMG,                                //  2 SPELL_EFFECT_SCHOOL_DAMAGE
66    &Spell::EffectDummy,                                    //  3 SPELL_EFFECT_DUMMY
67    &Spell::EffectUnused,                                   //  4 SPELL_EFFECT_PORTAL_TELEPORT          unused
68    &Spell::EffectTeleportUnits,                            //  5 SPELL_EFFECT_TELEPORT_UNITS
69    &Spell::EffectApplyAura,                                //  6 SPELL_EFFECT_APPLY_AURA
70    &Spell::EffectEnvirinmentalDMG,                         //  7 SPELL_EFFECT_ENVIRONMENTAL_DAMAGE
71    &Spell::EffectPowerDrain,                               //  8 SPELL_EFFECT_POWER_DRAIN
72    &Spell::EffectHealthLeech,                              //  9 SPELL_EFFECT_HEALTH_LEECH
73    &Spell::EffectHeal,                                     // 10 SPELL_EFFECT_HEAL
74    &Spell::EffectUnused,                                   // 11 SPELL_EFFECT_BIND
75    &Spell::EffectNULL,                                     // 12 SPELL_EFFECT_PORTAL
76    &Spell::EffectUnused,                                   // 13 SPELL_EFFECT_RITUAL_BASE              unused
77    &Spell::EffectUnused,                                   // 14 SPELL_EFFECT_RITUAL_SPECIALIZE        unused
78    &Spell::EffectUnused,                                   // 15 SPELL_EFFECT_RITUAL_ACTIVATE_PORTAL   unused
79    &Spell::EffectQuestComplete,                            // 16 SPELL_EFFECT_QUEST_COMPLETE
80    &Spell::EffectWeaponDmg,                                // 17 SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
81    &Spell::EffectResurrect,                                // 18 SPELL_EFFECT_RESURRECT
82    &Spell::EffectAddExtraAttacks,                          // 19 SPELL_EFFECT_ADD_EXTRA_ATTACKS
83    &Spell::EffectUnused,                                   // 20 SPELL_EFFECT_DODGE                    one spell: Dodge
84    &Spell::EffectUnused,                                   // 21 SPELL_EFFECT_EVADE                    one spell: Evade (DND)
85    &Spell::EffectParry,                                    // 22 SPELL_EFFECT_PARRY
86    &Spell::EffectBlock,                                    // 23 SPELL_EFFECT_BLOCK                    one spell: Block
87    &Spell::EffectCreateItem,                               // 24 SPELL_EFFECT_CREATE_ITEM
88    &Spell::EffectUnused,                                   // 25 SPELL_EFFECT_WEAPON
89    &Spell::EffectUnused,                                   // 26 SPELL_EFFECT_DEFENSE                  one spell: Defense
90    &Spell::EffectPersistentAA,                             // 27 SPELL_EFFECT_PERSISTENT_AREA_AURA
91    &Spell::EffectSummonType,                               // 28 SPELL_EFFECT_SUMMON
92    &Spell::EffectMomentMove,                               // 29 SPELL_EFFECT_LEAP
93    &Spell::EffectEnergize,                                 // 30 SPELL_EFFECT_ENERGIZE
94    &Spell::EffectWeaponDmg,                                // 31 SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
95    &Spell::EffectTriggerMissileSpell,                      // 32 SPELL_EFFECT_TRIGGER_MISSILE
96    &Spell::EffectOpenLock,                                 // 33 SPELL_EFFECT_OPEN_LOCK
97    &Spell::EffectSummonChangeItem,                         // 34 SPELL_EFFECT_SUMMON_CHANGE_ITEM
98    &Spell::EffectApplyAreaAura,                            // 35 SPELL_EFFECT_APPLY_AREA_AURA_PARTY
99    &Spell::EffectLearnSpell,                               // 36 SPELL_EFFECT_LEARN_SPELL
100    &Spell::EffectUnused,                                   // 37 SPELL_EFFECT_SPELL_DEFENSE            one spell: SPELLDEFENSE (DND)
101    &Spell::EffectDispel,                                   // 38 SPELL_EFFECT_DISPEL
102    &Spell::EffectUnused,                                   // 39 SPELL_EFFECT_LANGUAGE
103    &Spell::EffectDualWield,                                // 40 SPELL_EFFECT_DUAL_WIELD
104    &Spell::EffectSummonWild,                               // 41 SPELL_EFFECT_SUMMON_WILD
105    &Spell::EffectSummonGuardian,                           // 42 SPELL_EFFECT_SUMMON_GUARDIAN
106    &Spell::EffectTeleUnitsFaceCaster,                      // 43 SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
107    &Spell::EffectLearnSkill,                               // 44 SPELL_EFFECT_SKILL_STEP
108    &Spell::EffectAddHonor,                                 // 45 SPELL_EFFECT_ADD_HONOR                honor/pvp related
109    &Spell::EffectNULL,                                     // 46 SPELL_EFFECT_SPAWN                    we must spawn pet there
110    &Spell::EffectTradeSkill,                               // 47 SPELL_EFFECT_TRADE_SKILL
111    &Spell::EffectUnused,                                   // 48 SPELL_EFFECT_STEALTH                  one spell: Base Stealth
112    &Spell::EffectUnused,                                   // 49 SPELL_EFFECT_DETECT                   one spell: Detect
113    &Spell::EffectTransmitted,                              // 50 SPELL_EFFECT_TRANS_DOOR
114    &Spell::EffectUnused,                                   // 51 SPELL_EFFECT_FORCE_CRITICAL_HIT       unused
115    &Spell::EffectUnused,                                   // 52 SPELL_EFFECT_GUARANTEE_HIT            one spell: zzOLDCritical Shot
116    &Spell::EffectEnchantItemPerm,                          // 53 SPELL_EFFECT_ENCHANT_ITEM
117    &Spell::EffectEnchantItemTmp,                           // 54 SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
118    &Spell::EffectTameCreature,                             // 55 SPELL_EFFECT_TAMECREATURE
119    &Spell::EffectSummonPet,                                // 56 SPELL_EFFECT_SUMMON_PET
120    &Spell::EffectLearnPetSpell,                            // 57 SPELL_EFFECT_LEARN_PET_SPELL
121    &Spell::EffectWeaponDmg,                                // 58 SPELL_EFFECT_WEAPON_DAMAGE
122    &Spell::EffectOpenSecretSafe,                           // 59 SPELL_EFFECT_OPEN_LOCK_ITEM
123    &Spell::EffectProficiency,                              // 60 SPELL_EFFECT_PROFICIENCY
124    &Spell::EffectSendEvent,                                // 61 SPELL_EFFECT_SEND_EVENT
125    &Spell::EffectPowerBurn,                                // 62 SPELL_EFFECT_POWER_BURN
126    &Spell::EffectThreat,                                   // 63 SPELL_EFFECT_THREAT
127    &Spell::EffectTriggerSpell,                             // 64 SPELL_EFFECT_TRIGGER_SPELL
128    &Spell::EffectUnused,                                   // 65 SPELL_EFFECT_HEALTH_FUNNEL            unused
129    &Spell::EffectUnused,                                   // 66 SPELL_EFFECT_POWER_FUNNEL             unused
130    &Spell::EffectHealMaxHealth,                            // 67 SPELL_EFFECT_HEAL_MAX_HEALTH
131    &Spell::EffectInterruptCast,                            // 68 SPELL_EFFECT_INTERRUPT_CAST
132    &Spell::EffectDistract,                                 // 69 SPELL_EFFECT_DISTRACT
133    &Spell::EffectPull,                                     // 70 SPELL_EFFECT_PULL                     one spell: Distract Move
134    &Spell::EffectPickPocket,                               // 71 SPELL_EFFECT_PICKPOCKET
135    &Spell::EffectAddFarsight,                              // 72 SPELL_EFFECT_ADD_FARSIGHT
136    &Spell::EffectSummonGuardian,                           // 73 SPELL_EFFECT_SUMMON_POSSESSED
137    &Spell::EffectSummonTotem,                              // 74 SPELL_EFFECT_SUMMON_TOTEM
138    &Spell::EffectHealMechanical,                           // 75 SPELL_EFFECT_HEAL_MECHANICAL          one spell: Mechanical Patch Kit
139    &Spell::EffectSummonObjectWild,                         // 76 SPELL_EFFECT_SUMMON_OBJECT_WILD
140    &Spell::EffectScriptEffect,                             // 77 SPELL_EFFECT_SCRIPT_EFFECT
141    &Spell::EffectUnused,                                   // 78 SPELL_EFFECT_ATTACK
142    &Spell::EffectSanctuary,                                // 79 SPELL_EFFECT_SANCTUARY
143    &Spell::EffectAddComboPoints,                           // 80 SPELL_EFFECT_ADD_COMBO_POINTS
144    &Spell::EffectUnused,                                   // 81 SPELL_EFFECT_CREATE_HOUSE             one spell: Create House (TEST)
145    &Spell::EffectNULL,                                     // 82 SPELL_EFFECT_BIND_SIGHT
146    &Spell::EffectDuel,                                     // 83 SPELL_EFFECT_DUEL
147    &Spell::EffectStuck,                                    // 84 SPELL_EFFECT_STUCK
148    &Spell::EffectSummonPlayer,                             // 85 SPELL_EFFECT_SUMMON_PLAYER
149    &Spell::EffectActivateObject,                           // 86 SPELL_EFFECT_ACTIVATE_OBJECT
150    &Spell::EffectSummonTotem,                              // 87 SPELL_EFFECT_SUMMON_TOTEM_SLOT1
151    &Spell::EffectSummonTotem,                              // 88 SPELL_EFFECT_SUMMON_TOTEM_SLOT2
152    &Spell::EffectSummonTotem,                              // 89 SPELL_EFFECT_SUMMON_TOTEM_SLOT3
153    &Spell::EffectSummonTotem,                              // 90 SPELL_EFFECT_SUMMON_TOTEM_SLOT4
154    &Spell::EffectUnused,                                   // 91 SPELL_EFFECT_THREAT_ALL               one spell: zzOLDBrainwash
155    &Spell::EffectEnchantHeldItem,                          // 92 SPELL_EFFECT_ENCHANT_HELD_ITEM
156    &Spell::EffectUnused,                                   // 93 SPELL_EFFECT_SUMMON_PHANTASM
157    &Spell::EffectSelfResurrect,                            // 94 SPELL_EFFECT_SELF_RESURRECT
158    &Spell::EffectSkinning,                                 // 95 SPELL_EFFECT_SKINNING
159    &Spell::EffectCharge,                                   // 96 SPELL_EFFECT_CHARGE
160    &Spell::EffectSummonCritter,                            // 97 SPELL_EFFECT_SUMMON_CRITTER
161    &Spell::EffectKnockBack,                                // 98 SPELL_EFFECT_KNOCK_BACK
162    &Spell::EffectDisEnchant,                               // 99 SPELL_EFFECT_DISENCHANT
163    &Spell::EffectInebriate,                                //100 SPELL_EFFECT_INEBRIATE
164    &Spell::EffectFeedPet,                                  //101 SPELL_EFFECT_FEED_PET
165    &Spell::EffectDismissPet,                               //102 SPELL_EFFECT_DISMISS_PET
166    &Spell::EffectReputation,                               //103 SPELL_EFFECT_REPUTATION
167    &Spell::EffectSummonObject,                             //104 SPELL_EFFECT_SUMMON_OBJECT_SLOT1
168    &Spell::EffectSummonObject,                             //105 SPELL_EFFECT_SUMMON_OBJECT_SLOT2
169    &Spell::EffectSummonObject,                             //106 SPELL_EFFECT_SUMMON_OBJECT_SLOT3
170    &Spell::EffectSummonObject,                             //107 SPELL_EFFECT_SUMMON_OBJECT_SLOT4
171    &Spell::EffectDispelMechanic,                           //108 SPELL_EFFECT_DISPEL_MECHANIC
172    &Spell::EffectSummonDeadPet,                            //109 SPELL_EFFECT_SUMMON_DEAD_PET
173    &Spell::EffectDestroyAllTotems,                         //110 SPELL_EFFECT_DESTROY_ALL_TOTEMS
174    &Spell::EffectDurabilityDamage,                         //111 SPELL_EFFECT_DURABILITY_DAMAGE
175    &Spell::EffectSummonDemon,                              //112 SPELL_EFFECT_SUMMON_DEMON
176    &Spell::EffectResurrectNew,                             //113 SPELL_EFFECT_RESURRECT_NEW
177    &Spell::EffectTaunt,                                    //114 SPELL_EFFECT_ATTACK_ME
178    &Spell::EffectDurabilityDamagePCT,                      //115 SPELL_EFFECT_DURABILITY_DAMAGE_PCT
179    &Spell::EffectSkinPlayerCorpse,                         //116 SPELL_EFFECT_SKIN_PLAYER_CORPSE       one spell: Remove Insignia, bg usage, required special corpse flags...
180    &Spell::EffectSpiritHeal,                               //117 SPELL_EFFECT_SPIRIT_HEAL              one spell: Spirit Heal
181    &Spell::EffectSkill,                                    //118 SPELL_EFFECT_SKILL                    professions and more
182    &Spell::EffectApplyAreaAura,                            //119 SPELL_EFFECT_APPLY_AREA_AURA_PET
183    &Spell::EffectUnused,                                   //120 SPELL_EFFECT_TELEPORT_GRAVEYARD       one spell: Graveyard Teleport Test
184    &Spell::EffectWeaponDmg,                                //121 SPELL_EFFECT_NORMALIZED_WEAPON_DMG
185    &Spell::EffectUnused,                                   //122 SPELL_EFFECT_122                      unused
186    &Spell::EffectSendTaxi,                                 //123 SPELL_EFFECT_SEND_TAXI                taxi/flight related (misc value is taxi path id)
187    &Spell::EffectPlayerPull,                               //124 SPELL_EFFECT_PLAYER_PULL              opposite of knockback effect (pulls player twoard caster)
188    &Spell::EffectModifyThreatPercent,                      //125 SPELL_EFFECT_MODIFY_THREAT_PERCENT
189    &Spell::EffectStealBeneficialBuff,                      //126 SPELL_EFFECT_STEAL_BENEFICIAL_BUFF    spell steal effect?
190    &Spell::EffectProspecting,                              //127 SPELL_EFFECT_PROSPECTING              Prospecting spell
191    &Spell::EffectApplyAreaAura,                            //128 SPELL_EFFECT_APPLY_AREA_AURA_FRIEND
192    &Spell::EffectApplyAreaAura,                            //129 SPELL_EFFECT_APPLY_AREA_AURA_ENEMY
193    &Spell::EffectNULL,                                     //130 SPELL_EFFECT_REDIRECT_THREAT
194    &Spell::EffectUnused,                                   //131 SPELL_EFFECT_131                      used in some test spells
195    &Spell::EffectNULL,                                     //132 SPELL_EFFECT_PLAY_MUSIC               sound id in misc value
196    &Spell::EffectUnlearnSpecialization,                    //133 SPELL_EFFECT_UNLEARN_SPECIALIZATION   unlearn profession specialization
197    &Spell::EffectKillCredit,                               //134 SPELL_EFFECT_KILL_CREDIT              misc value is creature entry
198    &Spell::EffectNULL,                                     //135 SPELL_EFFECT_CALL_PET
199    &Spell::EffectHealPct,                                  //136 SPELL_EFFECT_HEAL_PCT
200    &Spell::EffectEnergisePct,                              //137 SPELL_EFFECT_ENERGIZE_PCT
201    &Spell::EffectNULL,                                     //138 SPELL_EFFECT_138                      Leap
202    &Spell::EffectUnused,                                   //139 SPELL_EFFECT_139                      unused
203    &Spell::EffectForceCast,                                //140 SPELL_EFFECT_FORCE_CAST
204    &Spell::EffectNULL,                                     //141 SPELL_EFFECT_141                      damage and reduce speed?
205    &Spell::EffectTriggerSpellWithValue,                    //142 SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE
206    &Spell::EffectApplyAreaAura,                            //143 SPELL_EFFECT_APPLY_AREA_AURA_OWNER
207    &Spell::EffectNULL,                                     //144 SPELL_EFFECT_144                      Spectral Blast
208    &Spell::EffectNULL,                                     //145 SPELL_EFFECT_145                      Black Hole Effect
209    &Spell::EffectUnused,                                   //146 SPELL_EFFECT_146                      unused
210    &Spell::EffectQuestFail,                                //147 SPELL_EFFECT_QUEST_FAIL               quest fail
211    &Spell::EffectUnused,                                   //148 SPELL_EFFECT_148                      unused
212    &Spell::EffectNULL,                                     //149 SPELL_EFFECT_149                      swoop
213    &Spell::EffectUnused,                                   //150 SPELL_EFFECT_150                      unused
214    &Spell::EffectTriggerRitualOfSummoning,                 //151 SPELL_EFFECT_TRIGGER_SPELL_2
215    &Spell::EffectNULL,                                     //152 SPELL_EFFECT_152                      summon Refer-a-Friend
216    &Spell::EffectNULL,                                     //153 SPELL_EFFECT_CREATE_PET               misc value is creature entry
217};
218
219void Spell::EffectNULL(uint32 /*i*/)
220{
221    sLog.outDebug("WORLD: Spell Effect DUMMY");
222}
223
224void Spell::EffectUnused(uint32 /*i*/)
225{
226    // NOT USED BY ANY SPELL OR USELESS OR IMPLEMENTED IN DIFFERENT WAY IN TRINITY
227}
228
229void Spell::EffectResurrectNew(uint32 i)
230{
231    if(!unitTarget || unitTarget->isAlive())
232        return;
233
234    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
235        return;
236
237    if(!unitTarget->IsInWorld())
238        return;
239
240    Player* pTarget = ((Player*)unitTarget);
241
242    if(pTarget->isRessurectRequested())       // already have one active request
243        return;
244
245    uint32 health = damage;
246    uint32 mana = m_spellInfo->EffectMiscValue[i];
247    pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
248    SendResurrectRequest(pTarget);
249}
250
251void Spell::EffectInstaKill(uint32 /*i*/)
252{
253    if( !unitTarget || !unitTarget->isAlive() )
254        return;
255
256    // Demonic Sacrifice
257    if(m_spellInfo->Id==18788 && unitTarget->GetTypeId()==TYPEID_UNIT)
258    {
259        uint32 entry = unitTarget->GetEntry();
260        uint32 spellID;
261        switch(entry)
262        {
263            case   416: spellID=18789; break;               //imp
264            case   417: spellID=18792; break;               //fellhunter
265            case  1860: spellID=18790; break;               //void
266            case  1863: spellID=18791; break;               //succubus
267            case 17252: spellID=35701; break;               //fellguard
268            default:
269                sLog.outError("EffectInstaKill: Unhandled creature entry (%u) case.",entry);
270                return;
271        }
272
273        m_caster->CastSpell(m_caster,spellID,true);
274    }
275
276    if(m_caster==unitTarget)                                // prevent interrupt message
277        finish();
278
279    uint32 health = unitTarget->GetHealth();
280    m_caster->DealDamage(unitTarget, health, NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
281}
282
283void Spell::EffectEnvirinmentalDMG(uint32 i)
284{
285    uint32 absorb = 0;
286    uint32 resist = 0;
287
288    // Note: this hack with damage replace required until GO casting not implemented
289    // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
290    // currently each enemy selected explicitly and self cast damage, we prevent apply self casted spell bonuses/etc
291    damage = m_spellInfo->EffectBasePoints[i]+m_spellInfo->EffectBaseDice[i];
292
293    m_caster->CalcAbsorbResist(m_caster,GetSpellSchoolMask(m_spellInfo), SPELL_DIRECT_DAMAGE, damage, &absorb, &resist);
294
295    m_caster->SendSpellNonMeleeDamageLog(m_caster, m_spellInfo->Id, damage, GetSpellSchoolMask(m_spellInfo), absorb, resist, false, 0, false);
296    if(m_caster->GetTypeId() == TYPEID_PLAYER)
297        ((Player*)m_caster)->EnvironmentalDamage(m_caster->GetGUID(),DAMAGE_FIRE,damage);
298}
299
300void Spell::EffectSchoolDMG(uint32 effect_idx)
301{
302    if( unitTarget && unitTarget->isAlive())
303    {
304        switch(m_spellInfo->SpellFamilyName)
305        {
306            case SPELLFAMILY_GENERIC:
307            {
308                //Gore
309                if(m_spellInfo->SpellIconID == 2269 )
310                {
311                    damage+= rand()%2 ? damage : 0;
312                }
313
314                // Meteor like spells (divided damage to targets)
315                if(spellmgr.GetSpellExtraAttr(m_spellInfo->Id, SPELL_EXTRA_ATTR_SHARE_DAMAGE))
316                {
317                    uint32 count = 0;
318                    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
319                        if(ihit->effectMask & (1<<effect_idx))
320                            ++count;
321
322                    damage /= count;                    // divide to all targets
323                }
324
325                switch(m_spellInfo->Id)                     // better way to check unknown
326                {
327                    // percent from health with min
328                    case 25599:                             // Thundercrash
329                    {
330                        damage = unitTarget->GetHealth() / 2;
331                        if(damage < 200)
332                            damage = 200;
333                        break;
334                    }
335                    // must only affect demons
336                    case 45072:
337                    {
338                        if(unitTarget->GetCreatureType() != CREATURE_TYPE_DEMON)
339                            return;
340                        break;
341                    }
342                }
343                break;
344            }
345
346            case SPELLFAMILY_MAGE:
347            {
348                // Arcane Blast
349                if(m_spellInfo->SpellFamilyFlags & 0x20000000LL)
350                {
351                    m_caster->CastSpell(m_caster,36032,true);
352                }
353                break;
354            }
355            case SPELLFAMILY_WARRIOR:
356            {
357                // Bloodthirst
358                if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
359                {
360                    damage = uint32(damage * (m_caster->GetTotalAttackPowerValue(BASE_ATTACK)) / 100);
361                }
362                // Shield Slam
363                else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
364                    damage += int32(m_caster->GetShieldBlockValue());
365                // Victory Rush
366                else if(m_spellInfo->SpellFamilyFlags & 0x10000000000LL)
367                {
368                    damage = uint32(damage * m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
369                    m_caster->ModifyAuraState(AURA_STATE_WARRIOR_VICTORY_RUSH, false);
370                }
371                break;
372            }
373            case SPELLFAMILY_WARLOCK:
374            {
375                // Incinerate Rank 1 & 2
376                if((m_spellInfo->SpellFamilyFlags & 0x00004000000000LL) && m_spellInfo->SpellIconID==2128)
377                {
378                    // Incinerate does more dmg (dmg*0.25) if the target is Immolated.
379                    if(unitTarget->HasAuraState(AURA_STATE_IMMOLATE))
380                        damage += int32(damage*0.25);
381                }
382                break;
383            }
384            case SPELLFAMILY_DRUID:
385            {
386                // Ferocious Bite
387                if((m_spellInfo->SpellFamilyFlags & 0x000800000) && m_spellInfo->SpellVisual==6587)
388                {
389                    // converts each extra point of energy into ($f1+$AP/630) additional damage
390                    float multiple = m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 630 + m_spellInfo->DmgMultiplier[effect_idx];
391                    damage += int32(m_caster->GetPower(POWER_ENERGY) * multiple);
392                    m_caster->SetPower(POWER_ENERGY,0);
393                }
394                // Rake
395                else if(m_spellInfo->SpellFamilyFlags & 0x0000000000001000LL)
396                {
397                    damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) / 100);
398                }
399                // Swipe
400                else if(m_spellInfo->SpellFamilyFlags & 0x0010000000000000LL)
401                {
402                    damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.08f);
403                }
404                // Starfire
405                else if ( m_spellInfo->SpellFamilyFlags & 0x0004LL )
406                {
407                    Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
408                    for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
409                    {
410                        // Starfire Bonus (caster)
411                        switch((*i)->GetModifier()->m_miscvalue)
412                        {
413                            case 5481:                      // Nordrassil Regalia - bonus
414                            {
415                                Unit::AuraList const& m_periodicDamageAuras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
416                                for(Unit::AuraList::const_iterator itr = m_periodicDamageAuras.begin(); itr != m_periodicDamageAuras.end(); ++itr)
417                                {
418                                    // Moonfire or Insect Swarm (target debuff from any casters)
419                                    if ( (*itr)->GetSpellProto()->SpellFamilyFlags & 0x00200002LL )
420                                    {
421                                        int32 mod = (*i)->GetModifier()->m_amount;
422                                        damage += damage*mod/100;
423                                        break;
424                                    }
425                                }
426                                break;
427                            }
428                            case 5148:                      //Improved Starfire - Ivory Idol of the Moongoddes Aura
429                            {
430                                damage += (*i)->GetModifier()->m_amount;
431                                break;
432                            }
433                        }
434                    }
435                }
436                //Mangle Bonus for the initial damage of Lacerate and Rake
437                if((m_spellInfo->SpellFamilyFlags==0x0000000000001000LL && m_spellInfo->SpellIconID==494) ||
438                    (m_spellInfo->SpellFamilyFlags==0x0000010000000000LL && m_spellInfo->SpellIconID==2246))
439                {
440                    Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
441                    for(Unit::AuraList::const_iterator i = mDummyAuras.begin(); i != mDummyAuras.end(); ++i)
442                        if((*i)->GetSpellProto()->SpellFamilyFlags & 0x0000044000000000LL && (*i)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_DRUID)
443                        {
444                            damage = int32(damage*(100.0f+(*i)->GetModifier()->m_amount)/100.0f);
445                            break;
446                        }
447                }
448                break;
449            }
450            case SPELLFAMILY_ROGUE:
451            {
452                // Envenom
453                if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x800000000LL))
454                {
455                    // consume from stack dozes not more that have combo-points
456                    if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
457                    {
458                        // count consumed deadly poison doses at target
459                        uint32 doses = 0;
460
461                        // remove consumed poison doses
462                        Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
463                        for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end() && combo;)
464                        {
465                            // Deadly poison (only attacker applied)
466                            if( (*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_ROGUE && ((*itr)->GetSpellProto()->SpellFamilyFlags & 0x10000) &&
467                                (*itr)->GetSpellProto()->SpellVisual==5100 && (*itr)->GetCasterGUID()==m_caster->GetGUID() )
468                            {
469                                --combo;
470                                ++doses;
471
472                                unitTarget->RemoveSingleAuraFromStack((*itr)->GetId(), (*itr)->GetEffIndex());
473
474                                itr = auras.begin();
475                            }
476                            else
477                                ++itr;
478                        }
479
480                        damage *= doses;
481                        damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.03f * doses);
482
483                        // Eviscerate and Envenom Bonus Damage (item set effect)
484                        if(m_caster->GetDummyAura(37169))
485                            damage += ((Player*)m_caster)->GetComboPoints()*40;
486                    }
487                }
488                // Eviscerate
489                else if((m_spellInfo->SpellFamilyFlags & 0x00020000LL) && m_caster->GetTypeId()==TYPEID_PLAYER)
490                {
491                    if(uint32 combo = ((Player*)m_caster)->GetComboPoints())
492                    {
493                        damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK) * combo * 0.03f);
494
495                        // Eviscerate and Envenom Bonus Damage (item set effect)
496                        if(m_caster->GetDummyAura(37169))
497                            damage += combo*40;
498                    }
499                }
500                break;
501            }
502            case SPELLFAMILY_HUNTER:
503            {
504                // Mongoose Bite
505                if((m_spellInfo->SpellFamilyFlags & 0x000000002) && m_spellInfo->SpellVisual==342)
506                {
507                    damage += int32(m_caster->GetTotalAttackPowerValue(BASE_ATTACK)*0.2);
508                }
509                // Arcane Shot
510                else if((m_spellInfo->SpellFamilyFlags & 0x00000800) && m_spellInfo->maxLevel > 0)
511                {
512                    damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.15);
513                }
514                // Steady Shot
515                else if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
516                {
517                    int32 base = irand((int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MINDAMAGE),(int32)m_caster->GetWeaponDamageRange(RANGED_ATTACK, MAXDAMAGE));
518                    damage += int32(float(base)/m_caster->GetAttackTime(RANGED_ATTACK)*2800 + m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.2f);
519                }
520                //Explosive Trap Effect
521                else if(m_spellInfo->SpellFamilyFlags & 0x00000004)
522                {
523                    damage += int32(m_caster->GetTotalAttackPowerValue(RANGED_ATTACK)*0.1);
524                }
525                break;
526            }
527            case SPELLFAMILY_PALADIN:
528            {
529                //Judgement of Vengeance
530                if((m_spellInfo->SpellFamilyFlags & 0x800000000LL) && m_spellInfo->SpellIconID==2292)
531                {
532                    uint32 stacks = 0;
533                    Unit::AuraList const& auras = unitTarget->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
534                    for(Unit::AuraList::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
535                        if((*itr)->GetId() == 31803 && (*itr)->GetCasterGUID()==m_caster->GetGUID())
536                            ++stacks;
537                    if(!stacks)
538                        //No damage if the target isn't affected by this
539                        damage = -1;
540                    else
541                        damage *= stacks;
542                }
543                break;
544            }
545        }
546
547        if(damage >= 0)
548        {
549            uint32 finalDamage;
550            if(m_originalCaster)                            // m_caster only passive source of cast
551                finalDamage = m_originalCaster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
552            else
553                finalDamage = m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
554
555            // post effects
556            switch(m_spellInfo->SpellFamilyName)
557            {
558                case SPELLFAMILY_WARRIOR:
559                {
560                    // Bloodthirst
561                    if(m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
562                    {
563                        uint32 BTAura = 0;
564                        switch(m_spellInfo->Id)
565                        {
566                            case 23881: BTAura = 23885; break;
567                            case 23892: BTAura = 23886; break;
568                            case 23893: BTAura = 23887; break;
569                            case 23894: BTAura = 23888; break;
570                            case 25251: BTAura = 25252; break;
571                            case 30335: BTAura = 30339; break;
572                            default:
573                                sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura",m_spellInfo->Id);
574                                break;
575                        }
576
577                        if (BTAura)
578                            m_caster->CastSpell(m_caster,BTAura,true);
579                    }
580                    break;
581                }
582                case SPELLFAMILY_PRIEST:
583                {
584                    // Shadow Word: Death
585                    if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000200000000LL) && unitTarget->isAlive())
586                        // deals damage equal to damage done to caster if victim is not killed
587                        m_caster->SpellNonMeleeDamageLog( m_caster, m_spellInfo->Id, finalDamage, m_IsTriggeredSpell, false);
588
589                    break;
590                }
591                case SPELLFAMILY_PALADIN:
592                {
593                    // Judgement of Blood
594                    if(finalDamage > 0 && (m_spellInfo->SpellFamilyFlags & 0x0000000800000000LL) && m_spellInfo->SpellIconID==153)
595                    {
596                        int32 damagePoint  = finalDamage * 33 / 100;
597                        m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true);
598                    }
599                    break;
600                }
601            }
602        }
603    }
604}
605
606void Spell::EffectDummy(uint32 i)
607{
608    if(!unitTarget && !gameObjTarget && !itemTarget)
609        return;
610
611    // selection by spell family
612    switch(m_spellInfo->SpellFamilyName)
613    {
614        case SPELLFAMILY_GENERIC:
615            // Gnomish Poultryizer trinket
616            switch(m_spellInfo->Id )
617            {
618                // Mingo's Fortune Giblets
619                case 40802:
620                {
621                    if (m_caster->GetTypeId() != TYPEID_PLAYER) return;
622
623                    Player *player = (Player*)m_caster;
624                    uint32 newitemid;
625
626                    switch(urand(1,20))
627                    {
628                        case 1: newitemid = 32688; break;
629                        case 2: newitemid = 32689; break;
630                        case 3: newitemid = 32690; break;
631                        case 4: newitemid = 32691; break;
632                        case 5: newitemid = 32692; break;
633                        case 6: newitemid = 32693; break;
634                        case 7: newitemid = 32700; break;
635                        case 8: newitemid = 32701; break;
636                        case 9: newitemid = 32702; break;
637                        case 10: newitemid = 32703; break;
638                        case 11: newitemid = 32704; break;
639                        case 12: newitemid = 32705; break;
640                        case 13: newitemid = 32706; break;
641                        case 14: newitemid = 32707; break;
642                        case 15: newitemid = 32708; break;
643                        case 16: newitemid = 32709; break;
644                        case 17: newitemid = 32710; break;
645                        case 18: newitemid = 32711; break;
646                        case 19: newitemid = 32712; break;
647                        case 20: newitemid = 32713; break;
648                    }
649                    ItemPosCountVec dest;
650                    uint8 msg = player->CanStoreNewItem( NULL_BAG, NULL_SLOT, dest, newitemid, 1, false);
651                    if (msg != EQUIP_ERR_OK)
652                    {
653                        player->SendEquipError(msg, NULL, NULL);
654                        return;
655                    }
656                    Item *pItem = player->StoreNewItem(dest, newitemid, true, Item::GenerateItemRandomPropertyId(newitemid));
657
658                    if (!pItem)
659                    {
660                        player->SendEquipError(EQUIP_ERR_ITEM_NOT_FOUND, NULL, NULL);
661                        return;
662                    }
663                    player->SendNewItem(pItem, 1, true, true);
664                   
665                    return;
666                }
667                // Encapsulate Voidwalker
668                case 29364:
669                {
670                    if (!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet()) return;
671
672                    Creature* creatureTarget = (Creature*)unitTarget;
673                    GameObject* pGameObj = new GameObject;
674
675                    if (!creatureTarget || !pGameObj) return;
676
677                    if (!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), 181574, creatureTarget->GetMap(),
678                        creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), 
679                        creatureTarget->GetOrientation(), 0, 0, 0, 0, 100, 1))
680                    {
681                        delete pGameObj;
682                        return;
683                    }
684
685                    pGameObj->SetRespawnTime(0);
686                    pGameObj->SetOwnerGUID(m_caster->GetGUID());
687                    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel());
688                    pGameObj->SetSpellId(m_spellInfo->Id);
689
690                    MapManager::Instance().GetMap(creatureTarget->GetMapId(), pGameObj)->Add(pGameObj);
691
692                    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
693                    data << uint64(pGameObj->GetGUID());
694                    m_caster->SendMessageToSet(&data,true);
695
696                    return;
697                }
698                // Demon Broiled Surprise
699                case 43723:
700                {
701                    if (!unitTarget || unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT ||
702                        ((Creature*)unitTarget)->isPet()) return;
703
704                    Player *player = (Player*)m_caster;
705
706                    if (!player) return;
707
708                    player->CastSpell(unitTarget, 43753, true);
709
710                    if (player->GetQuestStatus(11379) == QUEST_STATUS_INCOMPLETE && unitTarget->GetEntry() == 19973)
711                        player->CastedCreatureOrGO(19973, unitTarget->GetGUID(), 43723);
712
713                    return;
714                }
715                case 8063:                                  // Deviate Fish
716                {
717                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
718                        return;
719
720                    uint32 spell_id = 0;
721                    switch(urand(1,5))
722                    {
723                        case 1: spell_id = 8064; break;     // Sleepy
724                        case 2: spell_id = 8065; break;     // Invigorate
725                        case 3: spell_id = 8066; break;     // Shrink
726                        case 4: spell_id = 8067; break;     // Party Time!
727                        case 5: spell_id = 8068; break;     // Healthy Spirit
728                    }
729                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
730                    return;
731                }
732                case 8213:                                  // Savory Deviate Delight
733                {
734                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
735                        return;
736
737                    uint32 spell_id = 0;
738                    switch(urand(1,2))
739                    {
740                        // Flip Out - ninja
741                        case 1: spell_id = (m_caster->getGender() == GENDER_MALE ? 8219 : 8220); break;
742                        // Yaaarrrr - pirate
743                        case 2: spell_id = (m_caster->getGender() == GENDER_MALE ? 8221 : 8222); break;
744                    }
745                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
746                    return;
747                }
748                case 8593:                                  // Symbol of life (restore creature to life)
749                case 31225:                                 // Shimmering Vessel (restore creature to life)
750                {
751                    if(!unitTarget || unitTarget->GetTypeId()!=TYPEID_UNIT)
752                        return;
753                    ((Creature*)unitTarget)->setDeathState(JUST_ALIVED);
754                    return;
755                }
756                case 12162:                                 // Deep wounds
757                case 12850:                                 // (now good common check for this spells)
758                case 12868:
759                {
760                    if(!unitTarget)
761                        return;
762
763                    float damage;
764                    // DW should benefit of attack power, damage percent mods etc.
765                    // TODO: check if using offhand damage is correct and if it should be divided by 2
766                    if (m_caster->haveOffhandWeapon() && m_caster->getAttackTimer(BASE_ATTACK) > m_caster->getAttackTimer(OFF_ATTACK))
767                        damage = (m_caster->GetFloatValue(UNIT_FIELD_MINOFFHANDDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXOFFHANDDAMAGE))/2;
768                    else
769                        damage = (m_caster->GetFloatValue(UNIT_FIELD_MINDAMAGE) + m_caster->GetFloatValue(UNIT_FIELD_MAXDAMAGE))/2;
770
771                    switch (m_spellInfo->Id)
772                    {
773                        case 12850: damage *= 0.2f; break;
774                        case 12162: damage *= 0.4f; break;
775                        case 12868: damage *= 0.6f; break;
776                        default:
777                            sLog.outError("Spell::EffectDummy: Spell %u not handled in DW",m_spellInfo->Id);
778                            return;
779                    };
780
781                    int32 deepWoundsDotBasePoints0 = int32(damage / 4);
782                    m_caster->CastCustomSpell(unitTarget, 12721, &deepWoundsDotBasePoints0, NULL, NULL, true, NULL);
783                    return;
784                }
785                case 12975:                                 //Last Stand
786                {
787                    int32 healthModSpellBasePoints0 = int32(m_caster->GetMaxHealth()*0.3);
788                    m_caster->CastCustomSpell(m_caster, 12976, &healthModSpellBasePoints0, NULL, NULL, true, NULL);
789                    return;
790                }
791                case 13120:                                 // net-o-matic
792                {
793                    if(!unitTarget)
794                        return;
795
796                    uint32 spell_id = 0;
797
798                    uint32 roll = urand(0, 99);
799
800                    if(roll < 2)                            // 2% for 30 sec self root (off-like chance unknown)
801                        spell_id = 16566;
802                    else if(roll < 4)                       // 2% for 20 sec root, charge to target (off-like chance unknown)
803                        spell_id = 13119;
804                    else                                    // normal root
805                        spell_id = 13099;
806
807                    m_caster->CastSpell(unitTarget,spell_id,true,NULL);
808                    return;
809                }
810                case 13567:                                 // Dummy Trigger
811                {
812                    // can be used for different aura triggreing, so select by aura
813                    if(!m_triggeredByAuraSpell || !unitTarget)
814                        return;
815
816                    switch(m_triggeredByAuraSpell->Id)
817                    {
818                        case 26467:                         // Persistent Shield
819                            m_caster->CastCustomSpell(unitTarget, 26470, &damage, NULL, NULL, true);
820                            break;
821                        default:
822                            sLog.outError("EffectDummy: Non-handled case for spell 13567 for triggered aura %u",m_triggeredByAuraSpell->Id);
823                            break;
824                    }
825                    return;
826                }
827                case 14185:                                 // Preparation Rogue
828                {
829                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
830                        return;
831
832                    //immediately finishes the cooldown on certain Rogue abilities
833                    const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
834                    for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
835                    {
836                        uint32 classspell = itr->first;
837                        SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
838
839                        if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (spellInfo->SpellFamilyFlags & 0x26000000860LL))
840                        {
841                            ((Player*)m_caster)->RemoveSpellCooldown(classspell);
842
843                            WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
844                            data << uint32(classspell);
845                            data << uint64(m_caster->GetGUID());
846                            ((Player*)m_caster)->GetSession()->SendPacket(&data);
847                        }
848                    }
849                    return;
850                }
851                case 15998:                                 // Capture Worg Pup
852                case 29435:                                 // Capture Female Kaliri Hatchling
853                {
854                    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
855                        return;
856
857                    Creature* creatureTarget = (Creature*)unitTarget;
858                    creatureTarget->setDeathState(JUST_DIED);
859                    creatureTarget->RemoveCorpse();
860                    creatureTarget->SetHealth(0);           // just for nice GM-mode view
861                    return;
862                }
863                case 16589:                                 // Noggenfogger Elixir
864                {
865                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
866                        return;
867
868                    uint32 spell_id = 0;
869                    switch(urand(1,3))
870                    {
871                        case 1: spell_id = 16595; break;
872                        case 2: spell_id = 16593; break;
873                        default:spell_id = 16591; break;
874                    }
875
876                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
877                    return;
878                }
879                case 17251:                                 // Spirit Healer Res
880                {
881                    if(!unitTarget || !m_originalCaster)
882                        return;
883
884                    if(m_originalCaster->GetTypeId() == TYPEID_PLAYER)
885                    {
886                        WorldPacket data(SMSG_SPIRIT_HEALER_CONFIRM, 8);
887                        data << unitTarget->GetGUID();
888                        ((Player*)m_originalCaster)->GetSession()->SendPacket( &data );
889                    }
890                    return;
891                }
892                case 17271:                                 // Test Fetid Skull
893                {
894                    if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
895                        return;
896
897                    uint32 spell_id = roll_chance_i(50) ? 17269 : 17270;
898
899                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
900                    return;
901                }
902                case 20577:                                 // Cannibalize
903                    if (unitTarget)
904                        m_caster->CastSpell(m_caster,20578,false,NULL);
905                    return;
906                case 23019:                                 // Crystal Prison Dummy DND
907                {
908                    if(!unitTarget || !unitTarget->isAlive() || unitTarget->GetTypeId() != TYPEID_UNIT || ((Creature*)unitTarget)->isPet())
909                        return;
910
911                    Creature* creatureTarget = (Creature*)unitTarget;
912                    if(creatureTarget->isPet())
913                        return;
914
915                    creatureTarget->setDeathState(JUST_DIED);
916                    creatureTarget->RemoveCorpse();
917                    creatureTarget->SetHealth(0);                   // just for nice GM-mode view
918
919                    GameObject* Crystal_Prison = m_caster->SummonGameObject(179644, creatureTarget->GetPositionX(), creatureTarget->GetPositionY(), creatureTarget->GetPositionZ(), creatureTarget->GetOrientation(), 0, 0, 0, 0, creatureTarget->GetRespawnTime()-time(NULL));
920                    sLog.outDebug("SummonGameObject at SpellEfects.cpp EffectDummy for Spell 23019\n");
921                    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
922                    data << uint64(Crystal_Prison->GetGUID());
923                    m_caster->SendMessageToSet(&data,true);
924
925                    return;
926                }
927                case 23074:                                 // Arc. Dragonling
928                    if (!m_CastItem) return;
929                    m_caster->CastSpell(m_caster,19804,true,m_CastItem);
930                    return;
931                case 23075:                                 // Mithril Mechanical Dragonling
932                    if (!m_CastItem) return;
933                    m_caster->CastSpell(m_caster,12749,true,m_CastItem);
934                    return;
935                case 23076:                                 // Mechanical Dragonling
936                    if (!m_CastItem) return;
937                    m_caster->CastSpell(m_caster,4073,true,m_CastItem);
938                    return;
939                case 23133:                                 // Gnomish Battle Chicken
940                    if (!m_CastItem) return;
941                    m_caster->CastSpell(m_caster,13166,true,m_CastItem);
942                    return;
943                case 23448:                                 // Ultrasafe Transporter: Gadgetzan - backfires
944                {
945                    int32 r = irand(0, 119);
946                    if ( r < 20 )                           // 1/6 polymorph
947                        m_caster->CastSpell(m_caster,23444,true);
948                    else if ( r < 100 )                     // 4/6 evil twin
949                        m_caster->CastSpell(m_caster,23445,true);
950                    else                                    // 1/6 miss the target
951                        m_caster->CastSpell(m_caster,36902,true);
952                    return;
953                }
954                case 23453:                                 // Ultrasafe Transporter: Gadgetzan
955                    if ( roll_chance_i(50) )                // success
956                        m_caster->CastSpell(m_caster,23441,true);
957                    else                                    // failure
958                        m_caster->CastSpell(m_caster,23446,true);
959                    return;
960                case 23645:                                 // Hourglass Sand
961                    m_caster->RemoveAurasDueToSpell(23170);
962                    return;
963                case 23725:                                 // Gift of Life (warrior bwl trinket)
964                    m_caster->CastSpell(m_caster,23782,true);
965                    m_caster->CastSpell(m_caster,23783,true);
966                    return;
967                case 25860:                                 // Reindeer Transformation
968                {
969                    if (!m_caster->HasAuraType(SPELL_AURA_MOUNTED))
970                        return;
971
972                    float flyspeed = m_caster->GetSpeedRate(MOVE_FLY);
973                    float speed = m_caster->GetSpeedRate(MOVE_RUN);
974
975                    m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
976
977                    //5 different spells used depending on mounted speed and if mount can fly or not
978                    if (flyspeed >= 4.1f)
979                        m_caster->CastSpell(m_caster, 44827, true); //310% flying Reindeer
980                    else if (flyspeed >= 3.8f)
981                        m_caster->CastSpell(m_caster, 44825, true); //280% flying Reindeer
982                    else if (flyspeed >= 1.6f)
983                        m_caster->CastSpell(m_caster, 44824, true); //60% flying Reindeer
984                    else if (speed >= 2.0f)
985                        m_caster->CastSpell(m_caster, 25859, true); //100% ground Reindeer
986                    else
987                        m_caster->CastSpell(m_caster, 25858, true); //60% ground Reindeer
988
989                    return;
990                }
991                //case 26074:                               // Holiday Cheer
992                //    return; -- implemented at client side
993                case 28006:                                 // Arcane Cloaking
994                {
995                    if( unitTarget->GetTypeId() == TYPEID_PLAYER )
996                        m_caster->CastSpell(unitTarget,29294,true);
997                    return;
998                }
999                case 28730:                                 // Arcane Torrent (Mana)
1000                {
1001                    int32 count = 0;
1002                    Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1003                    for(Unit::AuraList::const_iterator i = m_dummyAuras.begin(); i != m_dummyAuras.end(); ++i)
1004                        if ((*i)->GetId() == 28734)
1005                            ++count;
1006                    if (count)
1007                    {
1008                        m_caster->RemoveAurasDueToSpell(28734);
1009                        int32 bp = damage * count;
1010                        m_caster->CastCustomSpell(m_caster, 28733, &bp, NULL, NULL, true);
1011                    }
1012                    return;
1013                }
1014                case 29200:                                 // Purify Helboar Meat
1015                {
1016                    if( m_caster->GetTypeId() != TYPEID_PLAYER )
1017                        return;
1018
1019                    uint32 spell_id = roll_chance_i(50) ? 29277 : 29278;
1020
1021                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
1022                    return;
1023                }
1024                case 29858:                                 // Soulshatter
1025                    if (unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT && unitTarget->IsHostileTo(m_caster))
1026                        m_caster->CastSpell(unitTarget,32835,true);
1027                    return;
1028                case 30458:                                 // Nigh Invulnerability
1029                    if (!m_CastItem) return;
1030                    if(roll_chance_i(86))                   // success
1031                        m_caster->CastSpell(m_caster, 30456, true, m_CastItem);
1032                    else                                    // backfire in 14% casts
1033                        m_caster->CastSpell(m_caster, 30457, true, m_CastItem);
1034                    return;
1035                case 30507:                                 // Poultryizer
1036                    if (!m_CastItem) return;
1037                    if(roll_chance_i(80))                   // success
1038                        m_caster->CastSpell(unitTarget, 30501, true, m_CastItem);
1039                    else                                    // backfire 20%
1040                        m_caster->CastSpell(unitTarget, 30504, true, m_CastItem);
1041                    return;
1042                case 33060:                                         // Make a Wish
1043                {
1044                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1045                        return;
1046
1047                    uint32 spell_id = 0;
1048
1049                    switch(urand(1,5))
1050                    {
1051                        case 1: spell_id = 33053; break;
1052                        case 2: spell_id = 33057; break;
1053                        case 3: spell_id = 33059; break;
1054                        case 4: spell_id = 33062; break;
1055                        case 5: spell_id = 33064; break;
1056                    }
1057
1058                    m_caster->CastSpell(m_caster,spell_id,true,NULL);
1059                    return;
1060                }
1061                case 35745:
1062                {
1063                    uint32 spell_id;
1064                    switch(m_caster->GetAreaId())
1065                    {
1066                        case 3900: spell_id = 35743; break;
1067                        case 3742: spell_id = 35744; break;
1068                        default: return;
1069                    }
1070
1071                    m_caster->CastSpell(m_caster,spell_id,true);
1072                    return;
1073                }
1074                case 37674:                                 // Chaos Blast
1075                    if(unitTarget)
1076                        m_caster->CastSpell(unitTarget,37675,true);
1077                    return;
1078                case 44875:                                 // Complete Raptor Capture
1079                {
1080                    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT)
1081                        return;
1082
1083                    Creature* creatureTarget = (Creature*)unitTarget;
1084
1085                    creatureTarget->setDeathState(JUST_DIED);
1086                    creatureTarget->RemoveCorpse();
1087                    creatureTarget->SetHealth(0);           // just for nice GM-mode view
1088
1089                    //cast spell Raptor Capture Credit
1090                    m_caster->CastSpell(m_caster,42337,true,NULL);
1091                    return;
1092                }
1093                case 37573:                                 //Temporal Phase Modulator
1094                {
1095                    if(!unitTarget)
1096                        return;
1097
1098                    TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1099                    if(!tempSummon)
1100                        return;
1101
1102                    uint32 health = tempSummon->GetHealth();
1103                    const uint32 entry_list[6] = {21821, 21820, 21817};
1104
1105                    float x = tempSummon->GetPositionX();
1106                    float y = tempSummon->GetPositionY();
1107                    float z = tempSummon->GetPositionZ();
1108                    float o = tempSummon->GetOrientation();
1109
1110                    tempSummon->UnSummon();
1111
1112                    Creature* pCreature = m_caster->SummonCreature(entry_list[urand(0, 2)], x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1113                    if (!pCreature)
1114                        return;
1115
1116                    pCreature->SetHealth(health);
1117
1118                    if(pCreature->AI())
1119                        pCreature->AI()->AttackStart(m_caster);
1120
1121                    return;
1122                }
1123                case 34665:                                 //Administer Antidote
1124                {
1125                    if(!unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER )
1126                        return;
1127
1128                    if(!unitTarget)
1129                        return;
1130
1131                    TemporarySummon* tempSummon = dynamic_cast<TemporarySummon*>(unitTarget);
1132                    if(!tempSummon)
1133                        return;
1134
1135                    uint32 health = tempSummon->GetHealth();
1136
1137                    float x = tempSummon->GetPositionX();
1138                    float y = tempSummon->GetPositionY();
1139                    float z = tempSummon->GetPositionZ();
1140                    float o = tempSummon->GetOrientation();
1141                    tempSummon->UnSummon();
1142
1143                    Creature* pCreature = m_caster->SummonCreature(16992, x, y, z, o,TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,180000);
1144                    if (!pCreature)
1145                        return;
1146
1147                    pCreature->SetHealth(health);
1148                    ((Player*)m_caster)->KilledMonster(16992,pCreature->GetGUID());
1149
1150                    if (pCreature->AI())
1151                        pCreature->AI()->AttackStart(m_caster);
1152
1153                    return;
1154                }
1155                case 44997:                                 // Converting Sentry
1156                {
1157                    //Converted Sentry Credit
1158                    m_caster->CastSpell(m_caster, 45009, true);
1159                    return;
1160                }               
1161                case 45030:                                 // Impale Emissary
1162                {
1163                    // Emissary of Hate Credit
1164                    m_caster->CastSpell(m_caster, 45088, true);
1165                    return;
1166                }
1167                case 50243:                                 // Teach Language
1168                {
1169                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
1170                        return;
1171
1172                    // spell has a 1/3 chance to trigger one of the below
1173                    if(roll_chance_i(66))
1174                        return;
1175                    if(((Player*)m_caster)->GetTeam() == ALLIANCE)
1176                    {
1177                        // 1000001 - gnomish binary
1178                        m_caster->CastSpell(m_caster, 50242, true);
1179                    }
1180                    else
1181                    {
1182                        // 01001000 - goblin binary
1183                        m_caster->CastSpell(m_caster, 50246, true);
1184                    }
1185
1186                    return;
1187                }
1188                case 51582:                                 //Rocket Boots Engaged (Rocket Boots Xtreme and Rocket Boots Xtreme Lite)
1189                {
1190                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
1191                        return;
1192
1193                    if(BattleGround* bg = ((Player*)m_caster)->GetBattleGround())
1194                        bg->EventPlayerDroppedFlag((Player*)m_caster);
1195
1196                    m_caster->CastSpell(m_caster, 30452, true, NULL);
1197                    return;
1198                }
1199            }
1200
1201            //All IconID Check in there
1202            switch(m_spellInfo->SpellIconID)
1203            {
1204                // Berserking (troll racial traits)
1205                case 1661:
1206                {
1207                    uint32 healthPerc = uint32((float(m_caster->GetHealth())/m_caster->GetMaxHealth())*100);
1208                    int32 melee_mod = 10;
1209                    if (healthPerc <= 40)
1210                        melee_mod = 30;
1211                    if (healthPerc < 100 && healthPerc > 40)
1212                        melee_mod = 10+(100-healthPerc)/3;
1213
1214                    int32 hasteModBasePoints0 = melee_mod;          // (EffectBasePoints[0]+1)-1+(5-melee_mod) = (melee_mod-1+1)-1+5-melee_mod = 5-1
1215                    int32 hasteModBasePoints1 = (5-melee_mod);
1216                    int32 hasteModBasePoints2 = 5;
1217
1218                    // FIXME: custom spell required this aura state by some unknown reason, we not need remove it anyway
1219                    m_caster->ModifyAuraState(AURA_STATE_BERSERKING,true);
1220                    m_caster->CastCustomSpell(m_caster,26635,&hasteModBasePoints0,&hasteModBasePoints1,&hasteModBasePoints2,true,NULL);
1221                    return;
1222                }
1223            }
1224            break;
1225        case SPELLFAMILY_MAGE:
1226            switch(m_spellInfo->Id )
1227            {
1228                case 11958:                                 // Cold Snap
1229                {
1230                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1231                        return;
1232
1233                    // immediately finishes the cooldown on Frost spells
1234                    const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1235                    for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1236                    {
1237                        if (itr->second->state == PLAYERSPELL_REMOVED)
1238                            continue;
1239
1240                        uint32 classspell = itr->first;
1241                        SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1242
1243                        if( spellInfo->SpellFamilyName == SPELLFAMILY_MAGE &&
1244                            (GetSpellSchoolMask(spellInfo) & SPELL_SCHOOL_MASK_FROST) &&
1245                            spellInfo->Id != 11958 && GetSpellRecoveryTime(spellInfo) > 0 )
1246                        {
1247                            ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1248
1249                            WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1250                            data << uint32(classspell);
1251                            data << uint64(m_caster->GetGUID());
1252                            ((Player*)m_caster)->GetSession()->SendPacket(&data);
1253                        }
1254                    }
1255                    return;
1256                }
1257                case 32826:
1258                {
1259                    if ( unitTarget && unitTarget->GetTypeId() == TYPEID_UNIT )
1260                    {
1261                        //Polymorph Cast Visual Rank 1
1262                        const uint32 spell_list[6] = {32813, 32816, 32817, 32818, 32819, 32820};
1263                        unitTarget->CastSpell( unitTarget, spell_list[urand(0, 5)], true); 
1264                    }
1265                    return;
1266                }
1267            }
1268            break;
1269        case SPELLFAMILY_WARRIOR:
1270            // Charge
1271            if(m_spellInfo->SpellFamilyFlags & 0x1 && m_spellInfo->SpellVisual == 867)
1272            {
1273                int32 chargeBasePoints0 = damage;
1274                m_caster->CastCustomSpell(m_caster,34846,&chargeBasePoints0,NULL,NULL,true);
1275                return;
1276            }
1277            // Execute
1278            if(m_spellInfo->SpellFamilyFlags & 0x20000000)
1279            {
1280                if(!unitTarget)
1281                    return;
1282
1283                int32 basePoints0 = damage+int32(m_caster->GetPower(POWER_RAGE) * m_spellInfo->DmgMultiplier[i]);
1284                m_caster->CastCustomSpell(unitTarget, 20647, &basePoints0, NULL, NULL, true, 0);
1285                m_caster->SetPower(POWER_RAGE,0);
1286                return;
1287            }
1288            if(m_spellInfo->Id==21977)                      //Warrior's Wrath
1289            {
1290                if(!unitTarget)
1291                    return;
1292
1293                m_caster->CastSpell(unitTarget,21887,true); // spell mod
1294                return;
1295            }
1296            break;
1297        case SPELLFAMILY_WARLOCK:
1298            //Life Tap (only it have this with dummy effect)
1299            if (m_spellInfo->SpellFamilyFlags == 0x40000)
1300            {
1301                float cost = m_currentBasePoints[0]+1;
1302
1303                if(Player* modOwner = m_caster->GetSpellModOwner())
1304                    modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, cost,this);
1305
1306                int32 dmg = m_caster->SpellDamageBonus(m_caster, m_spellInfo,uint32(cost > 0 ? cost : 0), SPELL_DIRECT_DAMAGE);
1307
1308                if(int32(m_caster->GetHealth()) > dmg)
1309                {
1310                    // Shouldn't Appear in Combat Log
1311                    m_caster->ModifyHealth(-dmg);
1312
1313                    int32 mana = dmg;
1314
1315                    Unit::AuraList const& auraDummy = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
1316                    for(Unit::AuraList::const_iterator itr = auraDummy.begin(); itr != auraDummy.end(); ++itr)
1317                    {
1318                        // only Imp. Life Tap have this in combination with dummy aura
1319                        if((*itr)->GetSpellProto()->SpellFamilyName==SPELLFAMILY_WARLOCK && (*itr)->GetSpellProto()->SpellIconID == 208)
1320                            mana = ((*itr)->GetModifier()->m_amount + 100)* mana / 100;
1321                    }
1322
1323                    m_caster->CastCustomSpell(m_caster,31818,&mana,NULL,NULL,true,NULL);
1324
1325                    // Mana Feed
1326                    int32 manaFeedVal = m_caster->CalculateSpellDamage(m_spellInfo,1, m_spellInfo->EffectBasePoints[1],m_caster);
1327                    manaFeedVal = manaFeedVal * mana / 100;
1328                    if(manaFeedVal > 0)
1329                        m_caster->CastCustomSpell(m_caster,32553,&manaFeedVal,NULL,NULL,true,NULL);
1330                }
1331                else
1332                    SendCastResult(SPELL_FAILED_FIZZLE);
1333                return;
1334            }
1335            break;
1336        case SPELLFAMILY_PRIEST:
1337            switch(m_spellInfo->Id )
1338            {
1339                case 28598:                                 // Touch of Weakness triggered spell
1340                {
1341                    if(!unitTarget || !m_triggeredByAuraSpell)
1342                        return;
1343
1344                    uint32 spellid = 0;
1345                    switch(m_triggeredByAuraSpell->Id)
1346                    {
1347                        case 2652:  spellid =  2943; break; // Rank 1
1348                        case 19261: spellid = 19249; break; // Rank 2
1349                        case 19262: spellid = 19251; break; // Rank 3
1350                        case 19264: spellid = 19252; break; // Rank 4
1351                        case 19265: spellid = 19253; break; // Rank 5
1352                        case 19266: spellid = 19254; break; // Rank 6
1353                        case 25461: spellid = 25460; break; // Rank 7
1354                        default:
1355                            sLog.outError("Spell::EffectDummy: Spell 28598 triggered by unhandeled spell %u",m_triggeredByAuraSpell->Id);
1356                            return;
1357                    }
1358                    m_caster->CastSpell(unitTarget, spellid, true, NULL);
1359                    return;
1360                }
1361            }
1362            break;
1363        case SPELLFAMILY_DRUID:
1364            switch(m_spellInfo->Id )
1365            {
1366                case 5420:                                  // Tree of Life passive
1367                {
1368                    // Tree of Life area effect
1369                    int32 health_mod = int32(m_caster->GetStat(STAT_SPIRIT)/4);
1370                    m_caster->CastCustomSpell(m_caster,34123,&health_mod,NULL,NULL,true,NULL);
1371                    return;
1372                }
1373            }
1374            break;
1375        case SPELLFAMILY_ROGUE:
1376            switch(m_spellInfo->Id )
1377            {
1378                case 31231:                                 // Cheat Death
1379                {
1380                    m_caster->CastSpell(m_caster,45182,true);
1381                    return;
1382                }
1383                case 5938:                                  // Shiv
1384                {
1385                    if(m_caster->GetTypeId() != TYPEID_PLAYER)
1386                        return;
1387
1388                    Player *pCaster = ((Player*)m_caster);
1389
1390                    Item *item = pCaster->GetWeaponForAttack(OFF_ATTACK);
1391                    if(!item)
1392                        return;
1393
1394                    // all poison enchantments is temporary
1395                    uint32 enchant_id = item->GetEnchantmentId(TEMP_ENCHANTMENT_SLOT);
1396                    if(!enchant_id)
1397                        return;
1398
1399                    SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
1400                    if(!pEnchant)
1401                        return;
1402
1403                    for (int s=0;s<3;s++)
1404                    {
1405                        if(pEnchant->type[s]!=ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL)
1406                            continue;
1407
1408                        SpellEntry const* combatEntry = sSpellStore.LookupEntry(pEnchant->spellid[s]);
1409                        if(!combatEntry || combatEntry->Dispel != DISPEL_POISON)
1410                            continue;
1411
1412                        m_caster->CastSpell(unitTarget, combatEntry, true, item);
1413                    }
1414
1415                    m_caster->CastSpell(unitTarget, 5940, true);
1416                    return;
1417                }
1418            }
1419            break;
1420        case SPELLFAMILY_HUNTER:
1421            // Steady Shot
1422            if(m_spellInfo->SpellFamilyFlags & 0x100000000LL)
1423            {
1424                if( !unitTarget || !unitTarget->isAlive())
1425                    return;
1426
1427                bool found = false;
1428
1429                // check dazed affect
1430                Unit::AuraList const& decSpeedList = unitTarget->GetAurasByType(SPELL_AURA_MOD_DECREASE_SPEED);
1431                for(Unit::AuraList::const_iterator iter = decSpeedList.begin(); iter != decSpeedList.end(); ++iter)
1432                {
1433                    if((*iter)->GetSpellProto()->SpellIconID==15 && (*iter)->GetSpellProto()->Dispel==0)
1434                    {
1435                        found = true;
1436                        break;
1437                    }
1438                }
1439
1440                if(found)
1441                    m_caster->SpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, damage, m_IsTriggeredSpell, true);
1442                return;
1443            }
1444            // Kill command
1445            if(m_spellInfo->SpellFamilyFlags & 0x00080000000000LL)
1446            {
1447                if(m_caster->getClass()!=CLASS_HUNTER)
1448                    return;
1449
1450                // clear hunter crit aura state
1451                m_caster->ModifyAuraState(AURA_STATE_HUNTER_CRIT_STRIKE,false);
1452
1453                // additional damage from pet to pet target
1454                Pet* pet = m_caster->GetPet();
1455                if(!pet || !pet->getVictim())
1456                    return;
1457
1458                uint32 spell_id = 0;
1459                switch (m_spellInfo->Id)
1460                {
1461                case 34026: spell_id = 34027; break;        // rank 1
1462                default:
1463                    sLog.outError("Spell::EffectDummy: Spell %u not handled in KC",m_spellInfo->Id);
1464                    return;
1465                }
1466
1467                pet->CastSpell(pet->getVictim(), spell_id, true);
1468                return;
1469            }
1470
1471            switch(m_spellInfo->Id)
1472            {
1473                case 23989:                                 //Readiness talent
1474                {
1475                    if(m_caster->GetTypeId()!=TYPEID_PLAYER)
1476                        return;
1477
1478                    //immediately finishes the cooldown for hunter abilities
1479                    const PlayerSpellMap& sp_list = ((Player *)m_caster)->GetSpellMap();
1480                    for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1481                    {
1482                        uint32 classspell = itr->first;
1483                        SpellEntry const *spellInfo = sSpellStore.LookupEntry(classspell);
1484
1485                        if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && spellInfo->Id != 23989 && GetSpellRecoveryTime(spellInfo) > 0 )
1486                        {
1487                            ((Player*)m_caster)->RemoveSpellCooldown(classspell);
1488
1489                            WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1490                            data << uint32(classspell);
1491                            data << uint64(m_caster->GetGUID());
1492                            ((Player*)m_caster)->GetSession()->SendPacket(&data);
1493                        }
1494                    }
1495                    return;
1496                }
1497                case 37506:                                 // Scatter Shot
1498                {
1499                    if (m_caster->GetTypeId()!=TYPEID_PLAYER)
1500                        return;
1501
1502                    // break Auto Shot and autohit
1503                    m_caster->InterruptSpell(CURRENT_AUTOREPEAT_SPELL);
1504                    m_caster->AttackStop();
1505                    ((Player*)m_caster)->SendAttackSwingCancelAttack();
1506                    return;
1507                }
1508            }
1509            break;
1510        case SPELLFAMILY_PALADIN:
1511            switch(m_spellInfo->SpellIconID)
1512            {
1513                case  156:                                  // Holy Shock
1514                {
1515                    if(!unitTarget)
1516                        return;
1517
1518                    int hurt = 0;
1519                    int heal = 0;
1520
1521                    switch(m_spellInfo->Id)
1522                    {
1523                        case 20473: hurt = 25912; heal = 25914; break;
1524                        case 20929: hurt = 25911; heal = 25913; break;
1525                        case 20930: hurt = 25902; heal = 25903; break;
1526                        case 27174: hurt = 27176; heal = 27175; break;
1527                        case 33072: hurt = 33073; heal = 33074; break;
1528                        default:
1529                            sLog.outError("Spell::EffectDummy: Spell %u not handled in HS",m_spellInfo->Id);
1530                            return;
1531                    }
1532
1533                    if(m_caster->IsFriendlyTo(unitTarget))
1534                        m_caster->CastSpell(unitTarget, heal, true, 0);
1535                    else
1536                        m_caster->CastSpell(unitTarget, hurt, true, 0);
1537
1538                    return;
1539                }
1540                case 561:                                   // Judgement of command
1541                {
1542                    if(!unitTarget)
1543                        return;
1544
1545                    uint32 spell_id = m_currentBasePoints[i]+1;
1546                    SpellEntry const* spell_proto = sSpellStore.LookupEntry(spell_id);
1547                    if(!spell_proto)
1548                        return;
1549
1550                    if( !unitTarget->hasUnitState(UNIT_STAT_STUNNED) && m_caster->GetTypeId()==TYPEID_PLAYER)
1551                    {
1552                        // decreased damage (/2) for non-stunned target.
1553                        SpellModifier *mod = new SpellModifier;
1554                        mod->op = SPELLMOD_DAMAGE;
1555                        mod->value = -50;
1556                        mod->type = SPELLMOD_PCT;
1557                        mod->spellId = m_spellInfo->Id;
1558                        mod->effectId = i;
1559                        mod->lastAffected = NULL;
1560                        mod->mask = 0x0000020000000000LL;
1561                        mod->charges = 0;
1562
1563                        ((Player*)m_caster)->AddSpellMod(mod, true);
1564                        m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1565                                                            // mod deleted
1566                        ((Player*)m_caster)->AddSpellMod(mod, false);
1567                    }
1568                    else
1569                        m_caster->CastSpell(unitTarget,spell_proto,true,NULL);
1570
1571                    return;
1572                }
1573            }
1574
1575            switch(m_spellInfo->Id)
1576            {
1577                case 31789:                                 // Righteous Defense (step 1)
1578                {
1579                    // 31989 -> dummy effect (step 1) + dummy effect (step 2) -> 31709 (taunt like spell for each target)
1580
1581                    // non-standard cast requirement check
1582                    if (!unitTarget || unitTarget->getAttackers().empty())
1583                    {
1584                        // clear cooldown at fail
1585                        if(m_caster->GetTypeId()==TYPEID_PLAYER)
1586                        {
1587                            ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
1588
1589                            WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
1590                            data << uint32(m_spellInfo->Id);
1591                            data << uint64(m_caster->GetGUID());
1592                            ((Player*)m_caster)->GetSession()->SendPacket(&data);
1593                        }
1594
1595                        SendCastResult(SPELL_FAILED_TARGET_AFFECTING_COMBAT);
1596                        return;
1597                    }
1598
1599                    // Righteous Defense (step 2) (in old version 31980 dummy effect)
1600                    // Clear targets for eff 1
1601                    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1602                        ihit->effectMask &= ~(1<<1);
1603
1604                    // not empty (checked)
1605                    Unit::AttackerSet const& attackers = unitTarget->getAttackers();
1606
1607                    // chance to be selected from list
1608                    float chance = 100.0f/attackers.size();
1609                    uint32 count=0;
1610                    for(Unit::AttackerSet::const_iterator aItr = attackers.begin(); aItr != attackers.end() && count < 3; ++aItr)
1611                    {
1612                        if(!roll_chance_f(chance))
1613                            continue;
1614                        ++count;
1615                        AddUnitTarget((*aItr), 1);
1616                    }
1617
1618                    // now let next effect cast spell at each target.
1619                    return;
1620                }
1621                case 37877:                                 // Blessing of Faith
1622                {
1623                    if(!unitTarget)
1624                        return;
1625
1626                    uint32 spell_id = 0;
1627                    switch(unitTarget->getClass())
1628                    {
1629                        case CLASS_DRUID:   spell_id = 37878; break;
1630                        case CLASS_PALADIN: spell_id = 37879; break;
1631                        case CLASS_PRIEST:  spell_id = 37880; break;
1632                        case CLASS_SHAMAN:  spell_id = 37881; break;
1633                        default: return;                    // ignore for not healing classes
1634                    }
1635
1636                    m_caster->CastSpell(m_caster,spell_id,true);
1637                    return;
1638                }
1639            }
1640            break;
1641        case SPELLFAMILY_SHAMAN:
1642            //Shaman Rockbiter Weapon
1643            if (m_spellInfo->SpellFamilyFlags == 0x400000)
1644            {
1645                uint32 spell_id = 0;
1646                switch(m_spellInfo->Id)
1647                {
1648                    case  8017: spell_id = 36494; break;    // Rank 1
1649                    case  8018: spell_id = 36750; break;    // Rank 2
1650                    case  8019: spell_id = 36755; break;    // Rank 3
1651                    case 10399: spell_id = 36759; break;    // Rank 4
1652                    case 16314: spell_id = 36763; break;    // Rank 5
1653                    case 16315: spell_id = 36766; break;    // Rank 6
1654                    case 16316: spell_id = 36771; break;    // Rank 7
1655                    case 25479: spell_id = 36775; break;    // Rank 8
1656                    case 25485: spell_id = 36499; break;    // Rank 9
1657                    default:
1658                        sLog.outError("Spell::EffectDummy: Spell %u not handled in RW",m_spellInfo->Id);
1659                        return;
1660                }
1661
1662                SpellEntry const *spellInfo = sSpellStore.LookupEntry( spell_id );
1663
1664                if(!spellInfo)
1665                {
1666                    sLog.outError("WORLD: unknown spell id %i\n", spell_id);
1667                    return;
1668                }
1669
1670                if(m_caster->GetTypeId() != TYPEID_PLAYER)
1671                    return;
1672
1673                for(int i = BASE_ATTACK; i <= OFF_ATTACK; ++i)
1674                {
1675                    if(Item* item = ((Player*)m_caster)->GetWeaponForAttack(WeaponAttackType(i)))
1676                    {
1677                        if(item->IsFitToSpellRequirements(m_spellInfo))
1678                        {
1679                            Spell *spell = new Spell(m_caster, spellInfo, true);
1680
1681                            // enchanting spell selected by calculated damage-per-sec in enchanting effect
1682                            // at calculation applied affect from Elemental Weapons talent
1683                            // real enchantment damage-1
1684                            spell->m_currentBasePoints[1] = damage-1;
1685
1686                            SpellCastTargets targets;
1687                            targets.setItemTarget( item );
1688                            spell->prepare(&targets);
1689                        }
1690                    }
1691                }
1692                return;
1693            }
1694
1695            if(m_spellInfo->Id == 39610)                    // Mana-Tide Totem effect
1696            {
1697                if(!unitTarget || unitTarget->getPowerType() != POWER_MANA)
1698                    return;
1699
1700                // Regenerate 6% of Total Mana Every 3 secs
1701                int32 EffectBasePoints0 = unitTarget->GetMaxPower(POWER_MANA)  * damage / 100;
1702                m_caster->CastCustomSpell(unitTarget,39609,&EffectBasePoints0,NULL,NULL,true,NULL,NULL,m_originalCasterGUID);
1703                return;
1704            }
1705
1706            break;
1707    }
1708
1709    // pet auras
1710    if(PetAura const* petSpell = spellmgr.GetPetAura(m_spellInfo->Id))
1711    {
1712        m_caster->AddPetAura(petSpell);
1713        return;
1714    }
1715}
1716
1717void Spell::EffectTriggerSpellWithValue(uint32 i)
1718{
1719    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1720
1721    // normal case
1722    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1723
1724    if(!spellInfo)
1725    {
1726        sLog.outError("EffectTriggerSpellWithValue of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id,triggered_spell_id);
1727        return;
1728    }
1729
1730    int32 bp = damage;
1731    m_caster->CastCustomSpell(unitTarget,triggered_spell_id,&bp,&bp,&bp,true,NULL,NULL,m_originalCasterGUID);
1732}
1733
1734void Spell::EffectTriggerRitualOfSummoning(uint32 i)
1735{
1736    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1737    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1738
1739    if(!spellInfo)
1740    {
1741        sLog.outError("EffectTriggerRitualOfSummoning of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1742        return;
1743    }
1744
1745    finish();
1746    Spell *spell = new Spell(m_caster, spellInfo, true);
1747
1748    SpellCastTargets targets;
1749    targets.setUnitTarget( unitTarget);
1750    spell->prepare(&targets);
1751
1752    m_caster->SetCurrentCastedSpell(spell);
1753    spell->m_selfContainer = &(m_caster->m_currentSpells[spell->GetCurrentContainer()]);
1754
1755}
1756
1757void Spell::EffectForceCast(uint32 i)
1758{
1759    if( !unitTarget )
1760        return;
1761
1762    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1763
1764    // normal case
1765    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1766
1767    if(!spellInfo)
1768    {
1769        sLog.outError("EffectForceCast of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1770        return;
1771    }
1772
1773    unitTarget->CastSpell(unitTarget,spellInfo,true,NULL,NULL,m_originalCasterGUID);
1774}
1775
1776void Spell::EffectTriggerSpell(uint32 i)
1777{
1778    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[i];
1779
1780    // special cases
1781    switch(triggered_spell_id)
1782    {
1783        // Vanish
1784        case 18461:
1785        {
1786            m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
1787            m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_DECREASE_SPEED);
1788            m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STALKED);
1789
1790            // if this spell is given to NPC it must handle rest by it's own AI
1791            if ( m_caster->GetTypeId() != TYPEID_PLAYER )
1792                return;
1793
1794            // get highest rank of the Stealth spell
1795            uint32 spellId = 0;
1796            const PlayerSpellMap& sp_list = ((Player*)m_caster)->GetSpellMap();
1797            for (PlayerSpellMap::const_iterator itr = sp_list.begin(); itr != sp_list.end(); ++itr)
1798            {
1799                // only highest rank is shown in spell book, so simply check if shown in spell book
1800                if(!itr->second->active || itr->second->disabled || itr->second->state == PLAYERSPELL_REMOVED)
1801                    continue;
1802
1803                SpellEntry const *spellInfo = sSpellStore.LookupEntry(itr->first);
1804                if (!spellInfo)
1805                    continue;
1806
1807                if (spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_STEALTH)
1808                {
1809                    spellId = spellInfo->Id;
1810                    break;
1811                }
1812            }
1813
1814            // no Stealth spell found
1815            if (!spellId)
1816                return;
1817
1818            // reset cooldown on it if needed
1819            if(((Player*)m_caster)->HasSpellCooldown(spellId))
1820                ((Player*)m_caster)->RemoveSpellCooldown(spellId);
1821
1822            m_caster->CastSpell(m_caster, spellId, true);
1823            return;
1824        }
1825        // just skip
1826        case 23770:                                         // Sayge's Dark Fortune of *
1827            // not exist, common cooldown can be implemented in scripts if need.
1828            return;
1829        // Brittle Armor - (need add max stack of 24575 Brittle Armor)
1830        case 29284:
1831        {
1832            const SpellEntry *spell = sSpellStore.LookupEntry(24575);
1833            if (!spell)
1834                return;
1835
1836            for (int i=0; i < spell->StackAmount; ++i)
1837                m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1838            return;
1839        }
1840        // Mercurial Shield - (need add max stack of 26464 Mercurial Shield)
1841        case 29286:
1842        {
1843            const SpellEntry *spell = sSpellStore.LookupEntry(26464);
1844            if (!spell)
1845                return;
1846
1847            for (int i=0; i < spell->StackAmount; ++i)
1848                m_caster->CastSpell(unitTarget,spell->Id, true, m_CastItem, NULL, m_originalCasterGUID);
1849            return;
1850        }
1851        // Righteous Defense
1852        case 31980:
1853        {
1854            m_caster->CastSpell(unitTarget, 31790, true,m_CastItem,NULL,m_originalCasterGUID);
1855            return;
1856        }
1857        // Cloak of Shadows
1858        case 35729 :
1859        {
1860            Unit::AuraMap& Auras = m_caster->GetAuras();
1861            for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
1862            {
1863                // remove all harmful spells on you...
1864                if(// only affect magic spells
1865                    iter->second->GetSpellProto()->DmgClass == SPELL_DAMAGE_CLASS_MAGIC
1866                    // ignore positive and passive auras
1867                    && !iter->second->IsPositive() && !iter->second->IsPassive())
1868                {
1869                    m_caster->RemoveAurasDueToSpell(iter->second->GetSpellProto()->Id);
1870                    iter = Auras.begin();
1871                }
1872            }
1873            return;
1874        }
1875        // Priest Shadowfiend (34433) need apply mana gain trigger aura on pet
1876        case 41967:
1877        {
1878            if (Unit *pet = m_caster->GetPet())
1879                pet->CastSpell(pet, 28305, true);
1880            return;
1881        }
1882    }
1883
1884    // normal case
1885    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1886
1887    if(!spellInfo)
1888    {
1889        sLog.outError("EffectTriggerSpell of spell %u: triggering unknown spell id %i", m_spellInfo->Id,triggered_spell_id);
1890        return;
1891    }
1892
1893    // some triggered spells require specific equipment
1894    if(spellInfo->EquippedItemClass >=0 && m_caster->GetTypeId()==TYPEID_PLAYER)
1895    {
1896        // main hand weapon required
1897        if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_MAIN_HAND)
1898        {
1899            Item* item = ((Player*)m_caster)->GetWeaponForAttack(BASE_ATTACK);
1900
1901            // skip spell if no weapon in slot or broken
1902            if(!item || item->IsBroken() )
1903                return;
1904
1905            // skip spell if weapon not fit to triggered spell
1906            if(!item->IsFitToSpellRequirements(spellInfo))
1907                return;
1908        }
1909
1910        // offhand hand weapon required
1911        if(spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
1912        {
1913            Item* item = ((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK);
1914
1915            // skip spell if no weapon in slot or broken
1916            if(!item || item->IsBroken() )
1917                return;
1918
1919            // skip spell if weapon not fit to triggered spell
1920            if(!item->IsFitToSpellRequirements(spellInfo))
1921                return;
1922        }
1923    }
1924
1925    // some triggered spells must be casted instantly (for example, if next effect case instant kill caster)
1926    bool instant = false;
1927    for(uint32 j = i+1; j < 3; ++j)
1928    {
1929        if(m_spellInfo->Effect[j]==SPELL_EFFECT_INSTAKILL && m_spellInfo->EffectImplicitTargetA[j]==TARGET_SELF)
1930        {
1931            instant = true;
1932            break;
1933        }
1934    }
1935
1936    if(instant)
1937    {
1938        if (unitTarget)
1939            m_caster->CastSpell(unitTarget,spellInfo,true,m_CastItem,NULL,m_originalCasterGUID);
1940    }
1941    else
1942        m_TriggerSpells.push_back(spellInfo);
1943}
1944
1945void Spell::EffectTriggerMissileSpell(uint32 effect_idx)
1946{
1947    uint32 triggered_spell_id = m_spellInfo->EffectTriggerSpell[effect_idx];
1948
1949    // normal case
1950    SpellEntry const *spellInfo = sSpellStore.LookupEntry( triggered_spell_id );
1951
1952    if(!spellInfo)
1953    {
1954        sLog.outError("EffectTriggerMissileSpell of spell %u: triggering unknown spell id %effect_idx", m_spellInfo->Id,triggered_spell_id);
1955        return;
1956    }
1957
1958    if (m_CastItem)
1959        DEBUG_LOG("WORLD: cast Item spellId - %i", spellInfo->Id);
1960
1961    Spell *spell = new Spell(m_caster, spellInfo, true, m_originalCasterGUID );
1962
1963    SpellCastTargets targets;
1964    targets.setDestination(m_targets.m_destX,m_targets.m_destY,m_targets.m_destZ);
1965    spell->m_CastItem = m_CastItem;
1966    spell->prepare(&targets, NULL);
1967}
1968
1969void Spell::EffectTeleportUnits(uint32 i)
1970{
1971    if(!unitTarget || unitTarget->isInFlight())
1972        return;
1973
1974    // If not exist data for dest location - return
1975    if(!m_targets.HasDest())
1976    {
1977        sLog.outError( "Spell::EffectTeleportUnits - does not have destination for spell ID %u\n", m_spellInfo->Id );
1978        return;
1979    }
1980    // Init dest coordinates
1981    uint32 mapid = m_targets.m_mapId;
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,m_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    {
3922        // cast finish successfully
3923        //SendChannelUpdate(0);
3924        finish();
3925
3926        Pet* pet = new Pet(HUNTER_PET);
3927
3928        if(!pet->CreateBaseAtCreature(creatureTarget))
3929        {
3930            delete pet;
3931            return;
3932        }
3933
3934        creatureTarget->setDeathState(JUST_DIED);
3935        creatureTarget->RemoveCorpse();
3936        creatureTarget->SetHealth(0);                       // just for nice GM-mode view
3937
3938        pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
3939        pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
3940        pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3941        pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3942
3943        if(!pet->InitStatsForLevel(creatureTarget->getLevel()))
3944        {
3945            sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted.");
3946            delete pet;
3947            return;
3948        }
3949
3950        // prepare visual effect for levelup
3951        pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
3952
3953        pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true);
3954                                                            // this enables pet details window (Shift+P)
3955        pet->AIM_Initialize();
3956        pet->InitPetCreateSpells();
3957        pet->SetHealth(pet->GetMaxHealth());
3958
3959        MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
3960
3961        // visual effect for levelup
3962        pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
3963
3964        if(m_caster->GetTypeId() == TYPEID_PLAYER)
3965        {
3966            m_caster->SetPet(pet);
3967            pet->SavePetToDB(PET_SAVE_AS_CURRENT);
3968            ((Player*)m_caster)->PetSpellInitialize();
3969        }
3970    }
3971}
3972
3973void Spell::EffectSummonPet(uint32 i)
3974{
3975    uint32 petentry = m_spellInfo->EffectMiscValue[i];
3976
3977    Pet *OldSummon = m_caster->GetPet();
3978
3979    // if pet requested type already exist
3980    if( OldSummon )
3981    {
3982        if(petentry == 0 || OldSummon->GetEntry() == petentry)
3983        {
3984            // pet in corpse state can't be summoned
3985            if( OldSummon->isDead() )
3986                return;
3987
3988            MapManager::Instance().GetMap(OldSummon->GetMapId(), OldSummon)->Remove((Creature*)OldSummon,false);
3989            OldSummon->SetMapId(m_caster->GetMapId());
3990
3991            float px, py, pz;
3992            m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
3993
3994            OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
3995            MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->Add((Creature*)OldSummon);
3996
3997            if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
3998            {
3999                ((Player*)m_caster)->PetSpellInitialize();
4000            }
4001            return;
4002        }
4003
4004        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4005            ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4006        else
4007            return;
4008    }
4009
4010    Pet* NewSummon = new Pet;
4011    NewSummon->setActive(m_caster->isActive());
4012
4013    // petentry==0 for hunter "call pet" (current pet summoned if any)
4014    if(NewSummon->LoadPetFromDB(m_caster,petentry))
4015    {
4016        if(NewSummon->getPetType()==SUMMON_PET)
4017        {
4018            // Remove Demonic Sacrifice auras (known pet)
4019            Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4020            for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4021            {
4022                if((*itr)->GetModifier()->m_miscvalue==2228)
4023                {
4024                    m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4025                    itr = auraClassScripts.begin();
4026                }
4027                else
4028                    ++itr;
4029            }
4030        }
4031
4032        return;
4033    }
4034
4035    // not error in case fail hunter call pet
4036    if(!petentry)
4037    {
4038        delete NewSummon;
4039        return;
4040    }
4041
4042    CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4043
4044    if(!cInfo)
4045    {
4046        sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4047        delete NewSummon;
4048        return;
4049    }
4050
4051    Map *map = m_caster->GetMap();
4052    uint32 pet_number = objmgr.GeneratePetNumber();
4053    if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number))
4054    {
4055        delete NewSummon;
4056        return;
4057    }
4058
4059    float px, py, pz;
4060    m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4061
4062    NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4063
4064    if(!NewSummon->IsPositionValid())
4065    {
4066        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());
4067        delete NewSummon;
4068        return;
4069    }
4070
4071    uint32 petlevel = m_caster->getLevel();
4072    NewSummon->setPetType(SUMMON_PET);
4073
4074    uint32 faction = m_caster->getFaction();
4075    if(m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->isTotem())
4076    {
4077        Unit* owner = ((Totem*)m_caster)->GetOwner();
4078        if(owner)
4079            faction = owner->getFaction();
4080        NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4081    }
4082
4083    NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
4084    NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
4085    NewSummon->SetUInt32Value(UNIT_NPC_FLAGS , 0);
4086    NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4087    NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
4088    NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
4089    NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,time(NULL));
4090    NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
4091    NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
4092    NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4093
4094    NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4095    // this enables pet details window (Shift+P)
4096
4097    // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4098    NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4099
4100    NewSummon->InitStatsForLevel( petlevel);
4101    NewSummon->InitPetCreateSpells();
4102
4103    if(NewSummon->getPetType()==SUMMON_PET)
4104    {
4105        // Remove Demonic Sacrifice auras (new pet)
4106        Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4107        for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4108        {
4109            if((*itr)->GetModifier()->m_miscvalue==2228)
4110            {
4111                m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4112                itr = auraClassScripts.begin();
4113            }
4114            else
4115                ++itr;
4116        }
4117
4118        // generate new name for summon pet
4119        std::string new_name=objmgr.GeneratePetName(petentry);
4120        if(!new_name.empty())
4121            NewSummon->SetName(new_name);
4122    }
4123    else if(NewSummon->getPetType()==HUNTER_PET)
4124        NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4125
4126    NewSummon->AIM_Initialize();
4127    NewSummon->SetHealth(NewSummon->GetMaxHealth());
4128    NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4129
4130    map->Add((Creature*)NewSummon);
4131
4132    m_caster->SetPet(NewSummon);
4133    sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4134
4135    if(m_caster->GetTypeId() == TYPEID_PLAYER)
4136    {
4137        NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4138        ((Player*)m_caster)->PetSpellInitialize();
4139    }
4140}
4141
4142void Spell::EffectLearnPetSpell(uint32 i)
4143{
4144    if(m_caster->GetTypeId() != TYPEID_PLAYER)
4145        return;
4146
4147    Player *_player = (Player*)m_caster;
4148
4149    Pet *pet = _player->GetPet();
4150    if(!pet)
4151        return;
4152    if(!pet->isAlive())
4153        return;
4154
4155    SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4156    if(!learn_spellproto)
4157        return;
4158
4159    pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id));
4160    pet->learnSpell(learn_spellproto->Id);
4161
4162    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4163    _player->PetSpellInitialize();
4164}
4165
4166void Spell::EffectTaunt(uint32 /*i*/)
4167{
4168    // this effect use before aura Taunt apply for prevent taunt already attacking target
4169    // for spell as marked "non effective at already attacking target"
4170    if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4171    {
4172        if(unitTarget->getVictim()==m_caster)
4173        {
4174            SendCastResult(SPELL_FAILED_DONT_REPORT);
4175            return;
4176        }
4177    }
4178
4179    // Also use this effect to set the taunter's threat to the taunted creature's highest value
4180    if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4181        unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4182}
4183
4184void Spell::EffectWeaponDmg(uint32 i)
4185{
4186    if(!unitTarget)
4187        return;
4188    if(!unitTarget->isAlive())
4189        return;
4190
4191    // multiple weapon dmg effect workaround
4192    // execute only the last weapon damage
4193    // and handle all effects at once
4194    for (int j = 0; j < 3; j++)
4195    {
4196        switch(m_spellInfo->Effect[j])
4197        {
4198            case SPELL_EFFECT_WEAPON_DAMAGE:
4199            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4200            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4201            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4202                if (j < i)                                  // we must calculate only at last weapon effect
4203                    return;
4204            break;
4205        }
4206    }
4207
4208    // some spell specific modifiers
4209    bool customBonusDamagePercentMod = false;
4210    float bonusDamagePercentMod  = 1.0f;                    // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4211    float weaponDamagePercentMod = 1.0f;                    // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4212    float totalDamagePercentMod  = 1.0f;                    // applied to final bonus+weapon damage
4213    bool normalized = false;
4214
4215    int32 spell_bonus = 0;                                  // bonus specific for spell
4216    switch(m_spellInfo->SpellFamilyName)
4217    {
4218        case SPELLFAMILY_WARRIOR:
4219        {
4220            // Whirlwind, single only spell with 2 weapon white damage apply if have
4221            if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4222            {
4223                if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4224                    spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4225            }
4226            // Devastate bonus and sunder armor refresh
4227            else if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508)
4228            {
4229                customBonusDamagePercentMod = true;
4230                bonusDamagePercentMod = 0.0f;               // only applied if auras found
4231
4232                Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE);
4233                for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr)
4234                {
4235                    SpellEntry const *proto = (*itr)->GetSpellProto();
4236                    if(proto->SpellVisual == 406 && proto->SpellIconID == 565)
4237                    {
4238                        int32 duration = GetSpellDuration(proto);
4239                        (*itr)->SetAuraDuration(duration);
4240                        (*itr)->UpdateAuraDuration();
4241                        bonusDamagePercentMod += 1.0f;      // +100%
4242                    }
4243                }
4244            }
4245            break;
4246        }
4247        case SPELLFAMILY_ROGUE:
4248        {
4249            // Ambush
4250            if(m_spellInfo->SpellFamilyFlags & 0x00000200LL)
4251            {
4252                customBonusDamagePercentMod = true;
4253                bonusDamagePercentMod = 2.5f;               // 250%
4254            }
4255            // Mutilate (for each hand)
4256            else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4257            {
4258                bool found = false;
4259                // fast check
4260                if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4261                    found = true;
4262                // full aura scan
4263                else
4264                {
4265                    Unit::AuraMap const& auras = unitTarget->GetAuras();
4266                    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4267                    {
4268                        if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4269                        {
4270                            found = true;
4271                            break;
4272                        }
4273                    }
4274                }
4275
4276                if(found)
4277                    totalDamagePercentMod *= 1.5f;          // 150% if poisoned
4278            }
4279            break;
4280        }
4281        case SPELLFAMILY_PALADIN:
4282        {
4283            // Seal of Command - receive benefit from Spell Damage and Healing
4284            if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4285            {
4286                spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4287                spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4288            }
4289            break;
4290        }
4291        case SPELLFAMILY_SHAMAN:
4292        {
4293            // Skyshatter Harness item set bonus
4294            // Stormstrike
4295            if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4296            {
4297                Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4298                for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4299                {
4300                    // Stormstrike AP Buff
4301                    if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4302                    {
4303                        m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4304                        break;
4305                    }
4306                }
4307            }
4308        }
4309    }
4310
4311    int32 fixed_bonus = 0;
4312    for (int j = 0; j < 3; j++)
4313    {
4314        switch(m_spellInfo->Effect[j])
4315        {
4316            case SPELL_EFFECT_WEAPON_DAMAGE:
4317            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4318                fixed_bonus += CalculateDamage(j,unitTarget);
4319                break;
4320            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4321                fixed_bonus += CalculateDamage(j,unitTarget);
4322                normalized = true;
4323                break;
4324            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4325                weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4326
4327                // applied only to prev.effects fixed damage
4328                if(customBonusDamagePercentMod)
4329                    fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod);
4330                else
4331                    fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4332                break;
4333            default:
4334                break;                                      // not weapon damage effect, just skip
4335        }
4336    }
4337
4338    // non-weapon damage
4339    int32 bonus = spell_bonus + fixed_bonus;
4340
4341    // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4342    if(bonus)
4343    {
4344        UnitMods unitMod;
4345        switch(m_attackType)
4346        {
4347            default:
4348            case BASE_ATTACK:   unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4349            case OFF_ATTACK:    unitMod = UNIT_MOD_DAMAGE_OFFHAND;  break;
4350            case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED;   break;
4351        }
4352
4353        float weapon_total_pct  = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4354        bonus = int32(bonus*weapon_total_pct);
4355    }
4356
4357    // + weapon damage with applied weapon% dmg to base weapon damage in call
4358    bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4359
4360    // total damage
4361    bonus = int32(bonus*totalDamagePercentMod);
4362
4363    // prevent negative damage
4364    uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4365
4366    const uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS;
4367
4368    uint32 hitInfo = 0;
4369    VictimState victimState = VICTIMSTATE_NORMAL;
4370    uint32 blocked_dmg = 0;
4371    uint32 absorbed_dmg = 0;
4372    uint32 resisted_dmg = 0;
4373    CleanDamage cleanDamage =  CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
4374
4375    m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell);
4376
4377    if ((hitInfo & nohitMask) && m_attackType != RANGED_ATTACK)  // not send ranged miss/etc
4378        m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchoolMask, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg);
4379
4380    bool criticalhit = (hitInfo & HITINFO_CRITICALHIT);
4381    m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchoolMask, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit);
4382
4383    if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg))
4384    {
4385        eff_damage -= (absorbed_dmg + resisted_dmg + blocked_dmg);
4386    }
4387    else
4388    {
4389        cleanDamage.damage += eff_damage;
4390        eff_damage = 0;
4391    }
4392
4393    // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation
4394    m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true);
4395
4396    // Hemorrhage
4397    if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4398    {
4399        if(m_caster->GetTypeId()==TYPEID_PLAYER)
4400            ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4401    }
4402    // Mangle (Cat): CP
4403    if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4404    {
4405        if(m_caster->GetTypeId()==TYPEID_PLAYER)
4406            ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4407    }
4408
4409
4410    // take ammo
4411    if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4412    {
4413        Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4414
4415        // wands don't have ammo
4416        if(!pItem  || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4417            return;
4418
4419        if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4420        {
4421            if(pItem->GetMaxStackCount()==1)
4422            {
4423                // decrease durability for non-stackable throw weapon
4424                ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4425            }
4426            else
4427            {
4428                // decrease items amount for stackable throw weapon
4429                uint32 count = 1;
4430                ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4431            }
4432        }
4433        else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4434            ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4435    }
4436}
4437
4438void Spell::EffectThreat(uint32 /*i*/)
4439{
4440    if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4441        return;
4442
4443    if(!unitTarget->CanHaveThreatList())
4444        return;
4445
4446    unitTarget->AddThreat(m_caster, float(damage));
4447}
4448
4449void Spell::EffectHealMaxHealth(uint32 /*i*/)
4450{
4451    if(!unitTarget)
4452        return;
4453    if(!unitTarget->isAlive())
4454        return;
4455
4456    uint32 heal = m_caster->GetMaxHealth();
4457
4458    int32 gain = unitTarget->ModifyHealth(heal);
4459    unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
4460
4461    m_caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, heal);
4462}
4463
4464void Spell::EffectInterruptCast(uint32 /*i*/)
4465{
4466    if(!unitTarget)
4467        return;
4468    if(!unitTarget->isAlive())
4469        return;
4470
4471    // TODO: not all spells that used this effect apply cooldown at school spells
4472    // also exist case: apply cooldown to interrupted cast only and to all spells
4473    for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4474    {
4475        if (unitTarget->m_currentSpells[i])
4476        {
4477            // check if we can interrupt spell
4478            if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4479            {
4480                unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4481                unitTarget->InterruptSpell(i,false);
4482            }
4483        }
4484    }
4485}
4486
4487void Spell::EffectSummonObjectWild(uint32 i)
4488{
4489    uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4490
4491    GameObject* pGameObj = new GameObject;
4492
4493    WorldObject* target = focusObject;
4494    if( !target )
4495        target = m_caster;
4496
4497    float x,y,z;
4498    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4499    {
4500        x = m_targets.m_destX;
4501        y = m_targets.m_destY;
4502        z = m_targets.m_destZ;
4503    }
4504    else
4505        m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4506
4507    Map *map = target->GetMap();
4508
4509    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4510        x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4511    {
4512        delete pGameObj;
4513        return;
4514    }
4515
4516    int32 duration = GetSpellDuration(m_spellInfo);
4517    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4518    pGameObj->SetSpellId(m_spellInfo->Id);
4519
4520    if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP)   // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4521        m_caster->AddGameObject(pGameObj);
4522    map->Add(pGameObj);
4523
4524    if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)  //WS
4525    {
4526        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4527        {
4528            Player *pl = (Player*)m_caster;
4529            BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4530            if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4531            {
4532                 uint32 team = ALLIANCE;
4533
4534                 if(pl->GetTeam() == team)
4535                     team = HORDE;
4536
4537                ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4538            }
4539        }
4540    }
4541
4542    if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)  //EY
4543    {
4544        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4545        {
4546            BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4547            if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4548            {
4549                ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4550            }
4551        }
4552    }
4553
4554    if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4555    {
4556        GameObject* linkedGO = new GameObject;
4557        if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4558            x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4559        {
4560            linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4561            linkedGO->SetSpellId(m_spellInfo->Id);
4562
4563            m_caster->AddGameObject(linkedGO);
4564            map->Add(linkedGO);
4565        }
4566        else
4567        {
4568            delete linkedGO;
4569            linkedGO = NULL;
4570            return;
4571        }
4572    }
4573}
4574
4575void Spell::EffectScriptEffect(uint32 effIndex)
4576{
4577    // TODO: we must implement hunter pet summon at login there (spell 6962)
4578
4579    // by spell id
4580    switch(m_spellInfo->Id)
4581    {
4582        // Bending Shinbone
4583        case 8856:
4584        {
4585            if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4586                return;
4587
4588            uint32 spell_id = 0;
4589            switch(urand(1,5))
4590            {
4591                case 1:  spell_id = 8854; break;
4592                default: spell_id = 8855; break;
4593            }
4594
4595            m_caster->CastSpell(m_caster,spell_id,true,NULL);
4596            return;
4597        }
4598
4599        // Healthstone creating spells
4600        case  6201:
4601        case  6202:
4602        case  5699:
4603        case 11729:
4604        case 11730:
4605        case 27230:
4606        {
4607            uint32 itemtype;
4608            uint32 rank = 0;
4609            Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4610            for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4611            {
4612                if((*i)->GetId() == 18692)
4613                {
4614                    rank = 1;
4615                    break;
4616                }
4617                else if((*i)->GetId() == 18693)
4618                {
4619                    rank = 2;
4620                    break;
4621                }
4622            }
4623
4624            static uint32 const itypes[6][3] = {
4625                { 5512,19004,19005},                        // Minor Healthstone
4626                { 5511,19006,19007},                        // Lesser Healthstone
4627                { 5509,19008,19009},                        // Healthstone
4628                { 5510,19010,19011},                        // Greater Healthstone
4629                { 9421,19012,19013},                        // Major Healthstone
4630                {22103,22104,22105}                         // Master Healthstone
4631            };
4632
4633            switch(m_spellInfo->Id)
4634            {
4635                case  6201: itemtype=itypes[0][rank];break; // Minor Healthstone
4636                case  6202: itemtype=itypes[1][rank];break; // Lesser Healthstone
4637                case  5699: itemtype=itypes[2][rank];break; // Healthstone
4638                case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone
4639                case 11730: itemtype=itypes[4][rank];break; // Major Healthstone
4640                case 27230: itemtype=itypes[5][rank];break; // Master Healthstone
4641                default:
4642                    return;
4643            }
4644            DoCreateItem( effIndex, itemtype );
4645            return;
4646        }
4647        // Brittle Armor - need remove one 24575 Brittle Armor aura
4648        case 24590:
4649            unitTarget->RemoveSingleAuraFromStack(24575, 0);
4650            unitTarget->RemoveSingleAuraFromStack(24575, 1);
4651            return;
4652        // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4653        case 26465:
4654            unitTarget->RemoveSingleAuraFromStack(26464, 0);
4655            return;
4656        // Orb teleport spells
4657        case 25140:
4658        case 25143:
4659        case 25650:
4660        case 25652:
4661        case 29128:
4662        case 29129:
4663        case 35376:
4664        case 35727:
4665        {
4666            if(!unitTarget)
4667                return;
4668
4669            uint32 spellid;
4670            switch(m_spellInfo->Id)
4671            {
4672                case 25140: spellid =  32571; break;
4673                case 25143: spellid =  32572; break;
4674                case 25650: spellid =  30140; break;
4675                case 25652: spellid =  30141; break;
4676                case 29128: spellid =  32568; break;
4677                case 29129: spellid =  32569; break;
4678                case 35376: spellid =  25649; break;
4679                case 35727: spellid =  35730; break;
4680                default:
4681                    return;
4682            }
4683
4684            unitTarget->CastSpell(unitTarget,spellid,false);
4685            return;
4686        }
4687
4688        // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4689        case 22539:
4690        case 22972:
4691        case 22975:
4692        case 22976:
4693        case 22977:
4694        case 22978:
4695        case 22979:
4696        case 22980:
4697        case 22981:
4698        case 22982:
4699        case 22983:
4700        case 22984:
4701        case 22985:
4702        {
4703            if(!unitTarget || !unitTarget->isAlive())
4704                return;
4705
4706            // Onyxia Scale Cloak
4707            if(unitTarget->GetDummyAura(22683))
4708                return;
4709
4710            // Shadow Flame
4711            m_caster->CastSpell(unitTarget, 22682, true);
4712            return;
4713        }
4714        break;
4715
4716        // Summon Black Qiraji Battle Tank
4717        case 26656:
4718        {
4719            if(!unitTarget)
4720                return;
4721
4722            // Prevent stacking of mounts
4723            unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4724
4725            // Two separate mounts depending on area id (allows use both in and out of specific instance)
4726            if (unitTarget->GetAreaId() == 3428)
4727                unitTarget->CastSpell(unitTarget, 25863, false);
4728            else
4729                unitTarget->CastSpell(unitTarget, 26655, false);
4730            break;
4731        }
4732        // Piccolo of the Flaming Fire
4733        case 17512:
4734        {
4735            if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4736                return;
4737            unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4738            break;
4739        }
4740
4741        // Netherbloom
4742        case 28702:
4743        {
4744            if(!unitTarget)
4745                return;
4746            // 25% chance of casting a random buff
4747            if(roll_chance_i(75))
4748                return;
4749
4750            // triggered spells are 28703 to 28707
4751            // Note: some sources say, that there was the possibility of
4752            //       receiving a debuff. However, this seems to be removed by a patch.
4753            const uint32 spellid = 28703;
4754
4755            // don't overwrite an existing aura
4756            for(uint8 i=0; i<5; i++)
4757                if(unitTarget->HasAura(spellid+i, 0))
4758                    return;
4759            unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
4760            break;
4761        }
4762
4763        // Nightmare Vine
4764        case 28720:
4765        {
4766            if(!unitTarget)
4767                return;
4768            // 25% chance of casting Nightmare Pollen
4769            if(roll_chance_i(75))
4770                return;
4771            unitTarget->CastSpell(unitTarget, 28721, true);
4772            break;
4773        }
4774
4775        // Mirren's Drinking Hat
4776        case 29830:
4777        {
4778            uint32 item = 0;
4779            switch ( urand(1,6) )
4780            {
4781                case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager
4782                case 4: case 5:         item = 23585; break;// Stouthammer Lite
4783                case 6:                 item = 23586; break;// Aerie Peak Pale Ale
4784            }
4785            if (item)
4786                DoCreateItem(effIndex,item);
4787            break;
4788        }
4789        // Improved Sprint
4790        case 30918:
4791        {
4792            // Removes snares and roots.
4793            uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4794            Unit::AuraMap& Auras = unitTarget->GetAuras();
4795            for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4796            {
4797                next = iter;
4798                ++next;
4799                Aura *aur = iter->second;
4800                if (!aur->IsPositive())             //only remove negative spells
4801                {
4802                    // check for mechanic mask
4803                    if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4804                    {
4805                        unitTarget->RemoveAurasDueToSpell(aur->GetId());
4806                        if(Auras.empty())
4807                            break;
4808                        else
4809                            next = Auras.begin();
4810                    }
4811                }
4812            }
4813            break;
4814        }
4815
4816        // Goblin Weather Machine
4817        case 46203:
4818        {
4819            if(!unitTarget)
4820                return;
4821
4822            uint32 spellId;
4823            switch(rand()%4)
4824            {
4825                case 0:
4826                    spellId=46740;
4827                    break;
4828                case 1:
4829                    spellId=46739;
4830                    break;
4831                case 2:
4832                    spellId=46738;
4833                    break;
4834                case 3:
4835                    spellId=46736;
4836                    break;
4837            }
4838            unitTarget->CastSpell(unitTarget, spellId, true);
4839            break;
4840        }
4841
4842    }
4843
4844    if(!unitTarget || !unitTarget->isAlive()) // can we remove this check?
4845    {
4846        sLog.outError("Spell %u in EffectScriptEffect does not have unitTarget", m_spellInfo->Id);
4847        return;
4848    }
4849
4850    switch(m_spellInfo->Id)
4851    {
4852        // Dreaming Glory
4853        case 28698: unitTarget->CastSpell(unitTarget, 28694, true); break;
4854        // Needle Spine
4855        case 39835: unitTarget->CastSpell(unitTarget, 39968, true); break;
4856        // Draw Soul
4857        case 40904: unitTarget->CastSpell(m_caster, 40903, true); break;
4858        // Flame Crash
4859        case 41126: unitTarget->CastSpell(unitTarget, 41131, true); break;
4860        case 41931:
4861        {
4862            int bag=19;
4863            int slot=0;
4864            Item* item = NULL;
4865           
4866            while (bag < 256)
4867            {
4868                item = ((Player*)m_caster)->GetItemByPos(bag,slot);
4869                if (item && item->GetEntry() == 38587) break;
4870                slot++;
4871                if (slot == 39)
4872                {
4873                    slot = 0;
4874                    bag++;
4875                }
4876            }
4877            if (bag < 256)
4878            {
4879                if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true);
4880                else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1);
4881                // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen)
4882                m_caster->CastSpell(m_caster,42518,true);
4883                return;
4884            }
4885        }
4886        // Force Cast - Portal Effect: Sunwell Isle
4887        case 44876: unitTarget->CastSpell(unitTarget, 44870, true); break;
4888        //5,000 Gold
4889        case 46642:
4890        {
4891            if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4892                ((Player*)unitTarget)->ModifyMoney(50000000);
4893            break;
4894        }
4895    }
4896
4897    if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
4898    {
4899        switch(m_spellInfo->SpellFamilyFlags)
4900        {
4901            // Judgement
4902            case 0x800000:
4903            {
4904                uint32 spellId2 = 0;
4905
4906                // all seals have aura dummy
4907                Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4908                for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
4909                {
4910                    SpellEntry const *spellInfo = (*itr)->GetSpellProto();
4911
4912                    // search seal (all seals have judgement's aura dummy spell id in 2 effect
4913                    if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 )
4914                        continue;
4915
4916                    // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
4917                    spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1;
4918
4919                    if(spellId2 <= 1)
4920                        continue;
4921
4922                    // found, remove seal
4923                    m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4924
4925                    // Sanctified Judgement
4926                    Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4927                    for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i)
4928                    {
4929                        if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL)
4930                        {
4931                            int32 chance = (*i)->GetModifier()->m_amount;
4932                            if ( roll_chance_i(chance) )
4933                            {
4934                                int32 mana = spellInfo->manaCost;
4935                                if ( Player* modOwner = m_caster->GetSpellModOwner() )
4936                                    modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana);
4937                                mana = int32(mana* 0.8f);
4938                                m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i);
4939                            }
4940                            break;
4941                        }
4942                    }
4943
4944                    break;
4945                }
4946
4947                m_caster->CastSpell(unitTarget,spellId2,true);
4948                return;
4949            }
4950        }
4951    }
4952
4953    // normal DB scripted effect
4954    sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
4955    sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
4956}
4957
4958void Spell::EffectSanctuary(uint32 /*i*/)
4959{
4960    if(!unitTarget)
4961        return;
4962    //unitTarget->CombatStop();
4963
4964    unitTarget->CombatStop();
4965    unitTarget->getHostilRefManager().deleteReferences();   // stop all fighting
4966    // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4967    if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
4968    {
4969        ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4970    }
4971}
4972
4973void Spell::EffectAddComboPoints(uint32 /*i*/)
4974{
4975    if(!unitTarget)
4976        return;
4977
4978    if(m_caster->GetTypeId() != TYPEID_PLAYER)
4979        return;
4980
4981    if(damage <= 0)
4982        return;
4983
4984    ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
4985}
4986
4987void Spell::EffectDuel(uint32 i)
4988{
4989    if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
4990        return;
4991
4992    Player *caster = (Player*)m_caster;
4993    Player *target = (Player*)unitTarget;
4994
4995    // caster or target already have requested duel
4996    if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
4997        return;
4998
4999    // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5000    // Don't have to check the target's map since you cannot challenge someone across maps
5001    if( caster->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530)
5002    {
5003        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
5004        return;
5005    }
5006
5007    AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5008    if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5009    {
5010        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
5011        return;
5012    }
5013
5014    AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5015    if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5016    {
5017        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
5018        return;
5019    }
5020
5021    //CREATE DUEL FLAG OBJECT
5022    GameObject* pGameObj = new GameObject;
5023
5024    uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5025
5026    Map *map = m_caster->GetMap();
5027    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
5028        m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5029        m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5030        m_caster->GetPositionZ(),
5031        m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1))
5032    {
5033        delete pGameObj;
5034        return;
5035    }
5036
5037    pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5038    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5039    int32 duration = GetSpellDuration(m_spellInfo);
5040    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5041    pGameObj->SetSpellId(m_spellInfo->Id);
5042
5043    m_caster->AddGameObject(pGameObj);
5044    map->Add(pGameObj);
5045    //END
5046
5047    // Send request
5048    WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5049    data << pGameObj->GetGUID();
5050    data << caster->GetGUID();
5051    caster->GetSession()->SendPacket(&data);
5052    target->GetSession()->SendPacket(&data);
5053
5054    // create duel-info
5055    DuelInfo *duel   = new DuelInfo;
5056    duel->initiator  = caster;
5057    duel->opponent   = target;
5058    duel->startTime  = 0;
5059    duel->startTimer = 0;
5060    caster->duel     = duel;
5061
5062    DuelInfo *duel2   = new DuelInfo;
5063    duel2->initiator  = caster;
5064    duel2->opponent   = caster;
5065    duel2->startTime  = 0;
5066    duel2->startTimer = 0;
5067    target->duel      = duel2;
5068
5069    caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5070    target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5071}
5072
5073void Spell::EffectStuck(uint32 /*i*/)
5074{
5075    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5076        return;
5077
5078    if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5079        return;
5080
5081    Player* pTarget = (Player*)unitTarget;
5082
5083    sLog.outDebug("Spell Effect: Stuck");
5084    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());
5085
5086    if(pTarget->isInFlight())
5087        return;
5088
5089    // homebind location is loaded always
5090    pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5091
5092    // Stuck spell trigger Hearthstone cooldown
5093    SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5094    if(!spellInfo)
5095        return;
5096    Spell spell(pTarget,spellInfo,true,0);
5097    spell.SendSpellCooldown();
5098}
5099
5100void Spell::EffectSummonPlayer(uint32 /*i*/)
5101{
5102    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5103        return;
5104
5105    // Evil Twin (ignore player summon, but hide this for summoner)
5106    if(unitTarget->GetDummyAura(23445))
5107        return;
5108
5109    float x,y,z;
5110    m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5111
5112    ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5113
5114    WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5115    data << uint64(m_caster->GetGUID());                    // summoner guid
5116    data << uint32(m_caster->GetZoneId());                  // summoner zone
5117    data << uint32(MAX_PLAYER_SUMMON_DELAY*1000);           // auto decline after msecs
5118    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5119}
5120
5121static ScriptInfo generateActivateCommand()
5122{
5123    ScriptInfo si;
5124    si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5125    return si;
5126}
5127
5128void Spell::EffectActivateObject(uint32 effect_idx)
5129{
5130    if(!gameObjTarget)
5131        return;
5132
5133    static ScriptInfo activateCommand = generateActivateCommand();
5134
5135    int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5136
5137    sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5138}
5139
5140void Spell::EffectSummonTotem(uint32 i)
5141{
5142    uint8 slot = 0;
5143    switch(m_spellInfo->EffectMiscValueB[i])
5144    {
5145        case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5146        case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5147        case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5148        case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5149        // Battle standard case
5150        case SUMMON_TYPE_TOTEM:       slot = 254; break;
5151        // jewelery statue case, like totem without slot
5152        case SUMMON_TYPE_GUARDIAN:    slot = 255; break;
5153        default: return;
5154    }
5155
5156    if(slot < MAX_TOTEM)
5157    {
5158        uint64 guid = m_caster->m_TotemSlot[slot];
5159        if(guid != 0)
5160        {
5161            Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5162            if(OldTotem && OldTotem->isTotem())
5163                ((Totem*)OldTotem)->UnSummon();
5164        }
5165    }
5166
5167    uint32 team = 0;
5168    if (m_caster->GetTypeId()==TYPEID_PLAYER)
5169        team = ((Player*)m_caster)->GetTeam();
5170
5171    Totem* pTotem = new Totem;
5172
5173    if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team ))
5174    {
5175        delete pTotem;
5176        return;
5177    }
5178
5179    float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5180
5181    float x,y,z;
5182    m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5183
5184    // totem must be at same Z in case swimming caster and etc.
5185    if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5186        z = m_caster->GetPositionZ();
5187
5188    pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5189
5190    if(slot < MAX_TOTEM)
5191        m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5192
5193    pTotem->SetOwner(m_caster->GetGUID());
5194    pTotem->SetTypeBySummonSpell(m_spellInfo);              // must be after Create call where m_spells initilized
5195
5196    int32 duration=GetSpellDuration(m_spellInfo);
5197    if(Player* modOwner = m_caster->GetSpellModOwner())
5198        modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5199    pTotem->SetDuration(duration);
5200
5201    if (damage)                                             // if not spell info, DB values used
5202    {
5203        pTotem->SetMaxHealth(damage);
5204        pTotem->SetHealth(damage);
5205    }
5206
5207    pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5208    pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5209
5210    pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true);
5211    pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true);
5212
5213    pTotem->Summon(m_caster);
5214
5215    if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5216    {
5217        WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5218        data << uint8(slot);
5219        data << uint64(pTotem->GetGUID());
5220        data << uint32(duration);
5221        data << uint32(m_spellInfo->Id);
5222        ((Player*)m_caster)->SendDirectMessage(&data);
5223    }
5224}
5225
5226void Spell::EffectEnchantHeldItem(uint32 i)
5227{
5228    // this is only item spell effect applied to main-hand weapon of target player (players in area)
5229    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5230        return;
5231
5232    Player* item_owner = (Player*)unitTarget;
5233    Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5234
5235    if(!item )
5236        return;
5237
5238    // must be equipped
5239    if(!item ->IsEquipped())
5240        return;
5241
5242    if (m_spellInfo->EffectMiscValue[i])
5243    {
5244        uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5245        int32 duration = GetSpellDuration(m_spellInfo);          //Try duration index first ..
5246        if(!duration)
5247            duration = m_currentBasePoints[i]+1;            //Base points after ..
5248        if(!duration)
5249            duration = 10;                                  //10 seconds for enchants which don't have listed duration
5250
5251        SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5252        if(!pEnchant)
5253            return;
5254
5255        // Always go to temp enchantment slot
5256        EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5257
5258        // Enchantment will not be applied if a different one already exists
5259        if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5260            return;
5261
5262        // Apply the temporary enchantment
5263        item->SetEnchantment(slot, enchant_id, duration*1000, 0);
5264        item_owner->ApplyEnchantment(item,slot,true);
5265    }
5266}
5267
5268void Spell::EffectDisEnchant(uint32 /*i*/)
5269{
5270    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5271        return;
5272
5273    Player* p_caster = (Player*)m_caster;
5274    if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5275        return;
5276
5277    p_caster->UpdateCraftSkill(m_spellInfo->Id);
5278
5279    ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5280
5281    // item will be removed at disenchanting end
5282}
5283
5284void Spell::EffectInebriate(uint32 /*i*/)
5285{
5286    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5287        return;
5288
5289    Player *player = (Player*)unitTarget;
5290    uint16 currentDrunk = player->GetDrunkValue();
5291    uint16 drunkMod = damage * 256;
5292    if (currentDrunk + drunkMod > 0xFFFF)
5293        currentDrunk = 0xFFFF;
5294    else
5295        currentDrunk += drunkMod;
5296    player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5297}
5298
5299void Spell::EffectFeedPet(uint32 i)
5300{
5301    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5302        return;
5303
5304    Player *_player = (Player*)m_caster;
5305
5306    if(!itemTarget)
5307        return;
5308
5309    Pet *pet = _player->GetPet();
5310    if(!pet)
5311        return;
5312
5313    if(!pet->isAlive())
5314        return;
5315
5316    int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel);
5317    if(benefit <= 0)
5318        return;
5319
5320    uint32 count = 1;
5321    _player->DestroyItemCount(itemTarget,count,true);
5322    // TODO: fix crash when a spell has two effects, both pointed at the same item target
5323
5324    m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5325}
5326
5327void Spell::EffectDismissPet(uint32 /*i*/)
5328{
5329    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5330        return;
5331
5332    Pet* pet = m_caster->GetPet();
5333
5334    // not let dismiss dead pet
5335    if(!pet||!pet->isAlive())
5336        return;
5337
5338    ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5339}
5340
5341void Spell::EffectSummonObject(uint32 i)
5342{
5343    uint32 go_id = m_spellInfo->EffectMiscValue[i];
5344
5345    uint8 slot = 0;
5346    switch(m_spellInfo->Effect[i])
5347    {
5348        case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5349        case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5350        case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5351        case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5352        default: return;
5353    }
5354
5355    uint64 guid = m_caster->m_ObjectSlot[slot];
5356    if(guid != 0)
5357    {
5358        GameObject* obj = NULL;
5359        if( m_caster )
5360            obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5361
5362        if(obj) obj->Delete();
5363        m_caster->m_ObjectSlot[slot] = 0;
5364    }
5365
5366    GameObject* pGameObj = new GameObject;
5367
5368    float rot2 = sin(m_caster->GetOrientation()/2);
5369    float rot3 = cos(m_caster->GetOrientation()/2);
5370
5371    float x,y,z;
5372    // If dest location if present
5373    if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5374    {
5375        x = m_targets.m_destX;
5376        y = m_targets.m_destY;
5377        z = m_targets.m_destZ;
5378    }
5379    // Summon in random point all other units if location present
5380    else
5381        m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5382
5383    Map *map = m_caster->GetMap();
5384    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
5385    {
5386        delete pGameObj;
5387        return;
5388    }
5389
5390    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5391    int32 duration = GetSpellDuration(m_spellInfo);
5392    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5393    pGameObj->SetSpellId(m_spellInfo->Id);
5394    m_caster->AddGameObject(pGameObj);
5395
5396    map->Add(pGameObj);
5397    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5398    data << pGameObj->GetGUID();
5399    m_caster->SendMessageToSet(&data,true);
5400
5401    m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5402}
5403
5404void Spell::EffectResurrect(uint32 i)
5405{
5406    if(!unitTarget)
5407        return;
5408    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5409        return;
5410
5411    if(unitTarget->isAlive())
5412        return;
5413    if(!unitTarget->IsInWorld())
5414        return;
5415
5416    switch (m_spellInfo->Id)
5417    {
5418        // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5419        case 8342:
5420            if (roll_chance_i(67))
5421            {
5422                m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5423                return;
5424            }
5425            break;
5426        // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5427        case 22999:
5428            if (roll_chance_i(50))
5429            {
5430                m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5431                return;
5432            }
5433            break;
5434        default:
5435            break;
5436    }
5437
5438    Player* pTarget = ((Player*)unitTarget);
5439
5440    if(pTarget->isRessurectRequested())       // already have one active request
5441        return;
5442
5443    uint32 health = pTarget->GetMaxHealth() * damage / 100;
5444    uint32 mana   = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5445
5446    pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5447    SendResurrectRequest(pTarget);
5448}
5449
5450void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5451{
5452    if(!unitTarget || !unitTarget->isAlive())
5453        return;
5454
5455    if( unitTarget->m_extraAttacks )
5456        return;
5457
5458    unitTarget->m_extraAttacks = damage;
5459}
5460
5461void Spell::EffectParry(uint32 /*i*/)
5462{
5463    if (unitTarget->GetTypeId() == TYPEID_PLAYER)
5464    {
5465        ((Player*)unitTarget)->SetCanParry(true);
5466    }
5467}
5468
5469void Spell::EffectBlock(uint32 /*i*/)
5470{
5471    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
5472        return;
5473
5474    ((Player*)unitTarget)->SetCanBlock(true);
5475}
5476
5477void Spell::EffectMomentMove(uint32 i)
5478{
5479    if(unitTarget->isInFlight())
5480        return;
5481
5482    if( m_spellInfo->rangeIndex== 1)                        //self range
5483    {
5484        uint32 mapid = m_caster->GetMapId();
5485        float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5486
5487        // before caster
5488        float fx,fy,fz;
5489        unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5490        float ox,oy,oz;
5491        unitTarget->GetPosition(ox,oy,oz);
5492
5493        float fx2,fy2,fz2;                                  // getObjectHitPos overwrite last args in any result case
5494        if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5495        {
5496            fx = fx2;
5497            fy = fy2;
5498            fz = fz2;
5499            unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5500        }
5501
5502        if(unitTarget->GetTypeId() == TYPEID_PLAYER)
5503            ((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));
5504        else
5505            MapManager::Instance().GetMap(mapid, unitTarget)->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
5506    }
5507}
5508
5509void Spell::EffectReputation(uint32 i)
5510{
5511    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5512        return;
5513
5514    Player *_player = (Player*)unitTarget;
5515
5516    int32  rep_change = m_currentBasePoints[i]+1;           // field store reputation change -1
5517
5518    uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5519
5520    FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5521
5522    if(!factionEntry)
5523        return;
5524
5525    _player->ModifyFactionReputation(factionEntry,rep_change);
5526}
5527
5528void Spell::EffectQuestComplete(uint32 i)
5529{
5530    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5531        return;
5532
5533    Player *_player = (Player*)m_caster;
5534
5535    uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5536    _player->AreaExploredOrEventHappens(quest_id);
5537}
5538
5539void Spell::EffectSelfResurrect(uint32 i)
5540{
5541    if(!unitTarget || unitTarget->isAlive())
5542        return;
5543    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5544        return;
5545    if(!unitTarget->IsInWorld())
5546        return;
5547
5548    uint32 health = 0;
5549    uint32 mana = 0;
5550
5551    // flat case
5552    if(damage < 0)
5553    {
5554        health = uint32(-damage);
5555        mana = m_spellInfo->EffectMiscValue[i];
5556    }
5557    // percent case
5558    else
5559    {
5560        health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5561        if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5562            mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5563    }
5564
5565    Player *plr = ((Player*)unitTarget);
5566    plr->ResurrectPlayer(0.0f);
5567
5568    plr->SetHealth( health );
5569    plr->SetPower(POWER_MANA, mana );
5570    plr->SetPower(POWER_RAGE, 0 );
5571    plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5572
5573    plr->SpawnCorpseBones();
5574
5575    plr->SaveToDB();
5576}
5577
5578void Spell::EffectSkinning(uint32 /*i*/)
5579{
5580    if(unitTarget->GetTypeId() != TYPEID_UNIT )
5581        return;
5582    if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5583        return;
5584
5585    Creature* creature = (Creature*) unitTarget;
5586    int32 targetLevel = creature->getLevel();
5587
5588    uint32 skill;
5589    if(creature->GetCreatureInfo()->flag1 & 256)
5590        skill = SKILL_HERBALISM;                            // special case
5591    else if(creature->GetCreatureInfo()->flag1 & 512)
5592        skill = SKILL_MINING;                               // special case
5593    else
5594        skill = SKILL_SKINNING;                             // normal case
5595
5596    ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5597    creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5598
5599    int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5600
5601    int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5602
5603    // Double chances for elites
5604    ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5605}
5606
5607void Spell::EffectCharge(uint32 /*i*/)
5608{
5609    if(!unitTarget || !m_caster)
5610        return;
5611
5612    float x, y, z;
5613    unitTarget->GetContactPoint(m_caster, x, y, z);
5614    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5615        ((Creature *)unitTarget)->StopMoving();
5616
5617    // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5618    m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5619
5620    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5621        MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5622
5623    // not all charge effects used in negative spells
5624    if ( !IsPositiveSpell(m_spellInfo->Id))
5625        m_caster->Attack(unitTarget,true);
5626}
5627
5628void Spell::EffectSummonCritter(uint32 i)
5629{
5630    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5631        return;
5632    Player* player = (Player*)m_caster;
5633
5634    uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5635    if(!pet_entry)
5636        return;
5637
5638    Pet* old_critter = player->GetMiniPet();
5639
5640    // for same pet just despawn
5641    if(old_critter && old_critter->GetEntry() == pet_entry)
5642    {
5643        player->RemoveMiniPet();
5644        return;
5645    }
5646
5647    // despawn old pet before summon new
5648    if(old_critter)
5649        player->RemoveMiniPet();
5650
5651    // summon new pet
5652    Pet* critter = new Pet(MINI_PET);
5653
5654    Map *map = m_caster->GetMap();
5655    uint32 pet_number = objmgr.GeneratePetNumber();
5656    if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),
5657        map, pet_entry, pet_number))
5658    {
5659        sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5660        delete critter;
5661        return;
5662    }
5663
5664    float x,y,z;
5665    // If dest location if present
5666    if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5667    {
5668         x = m_targets.m_destX;
5669         y = m_targets.m_destY;
5670         z = m_targets.m_destZ;
5671     }
5672     // Summon if dest location not present near caster
5673     else
5674         m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5675
5676    critter->Relocate(x,y,z,m_caster->GetOrientation());
5677
5678    if(!critter->IsPositionValid())
5679    {
5680        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());
5681        delete critter;
5682        return;
5683    }
5684
5685    critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
5686    critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID());
5687    critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5688    critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5689
5690    critter->AIM_Initialize();
5691    critter->InitPetCreateSpells();                         // e.g. disgusting oozeling has a create spell as critter...
5692    critter->SetMaxHealth(1);
5693    critter->SetHealth(1);
5694    critter->SetLevel(1);
5695
5696    // set timer for unsummon
5697    int32 duration = GetSpellDuration(m_spellInfo);
5698    if(duration > 0)
5699        critter->SetDuration(duration);
5700
5701    std::string name = player->GetName();
5702    name.append(petTypeSuffix[critter->getPetType()]);
5703    critter->SetName( name );
5704    player->SetMiniPet(critter);
5705
5706    map->Add((Creature*)critter);
5707}
5708
5709void Spell::EffectKnockBack(uint32 i)
5710{
5711    if(!unitTarget || !m_caster)
5712        return;
5713
5714    // Effect only works on players
5715    if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5716        return;
5717
5718    float vsin = sin(m_caster->GetAngle(unitTarget));
5719    float vcos = cos(m_caster->GetAngle(unitTarget));
5720
5721    WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5722    data.append(unitTarget->GetPackGUID());
5723    data << uint32(0);                                      // Sequence
5724    data << float(vcos);                                    // x direction
5725    data << float(vsin);                                    // y direction
5726    data << float(m_spellInfo->EffectMiscValue[i])/10;      // Horizontal speed
5727    data << float(damage/-10);                              // Z Movement speed (vertical)
5728
5729    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5730}
5731
5732void Spell::EffectSendTaxi(uint32 i)
5733{
5734    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5735        return;
5736
5737    TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5738    if(!entry)
5739        return;
5740
5741    std::vector<uint32> nodes;
5742
5743    nodes.resize(2);
5744    nodes[0] = entry->from;
5745    nodes[1] = entry->to;
5746
5747    uint32 mountid = 0;
5748    switch(m_spellInfo->Id)
5749    {
5750        case 31606:       //Stormcrow Amulet
5751            mountid = 17447;
5752            break;
5753        case 45071:      //Quest - Sunwell Daily - Dead Scar Bombing Run
5754        case 45113:      //Quest - Sunwell Daily - Ship Bombing Run
5755        case 45353:      //Quest - Sunwell Daily - Ship Bombing Run Return
5756            mountid = 22840;
5757            break;
5758        case 34905:      //Stealth Flight
5759            mountid = 6851;
5760            break;
5761    }
5762
5763    ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
5764
5765}
5766
5767void Spell::EffectPlayerPull(uint32 i)
5768{
5769    if(!unitTarget || !m_caster)
5770        return;
5771
5772    // Effect only works on players
5773    if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5774        return;
5775
5776    float vsin = sin(unitTarget->GetAngle(m_caster));
5777    float vcos = cos(unitTarget->GetAngle(m_caster));
5778
5779    WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5780    data.append(unitTarget->GetPackGUID());
5781    data << uint32(0);                                      // Sequence
5782    data << float(vcos);                                    // x direction
5783    data << float(vsin);                                    // y direction
5784                                                            // Horizontal speed
5785    data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
5786    data << float(m_spellInfo->EffectMiscValue[i])/-10;     // Z Movement speed
5787
5788    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5789}
5790
5791void Spell::EffectDispelMechanic(uint32 i)
5792{
5793    if(!unitTarget)
5794        return;
5795
5796    uint32 mechanic = m_spellInfo->EffectMiscValue[i];
5797
5798    Unit::AuraMap& Auras = unitTarget->GetAuras();
5799    for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
5800    {
5801        next = iter;
5802        ++next;
5803        SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
5804        if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
5805        {
5806            unitTarget->RemoveAurasDueToSpell(spell->Id);
5807            if(Auras.empty())
5808                break;
5809            else
5810                next = Auras.begin();
5811        }
5812    }
5813    return;
5814}
5815
5816void Spell::EffectSummonDeadPet(uint32 /*i*/)
5817{
5818    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5819        return;
5820    Player *_player = (Player*)m_caster;
5821    Pet *pet = _player->GetPet();
5822    if(!pet)
5823        return;
5824    if(pet->isAlive())
5825        return;
5826    if(damage < 0)
5827        return;
5828    pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
5829    pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5830    pet->setDeathState( ALIVE );
5831    pet->clearUnitState(UNIT_STAT_ALL_STATE);
5832    pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
5833
5834    pet->AIM_Initialize();
5835
5836    _player->PetSpellInitialize();
5837    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
5838}
5839
5840void Spell::EffectDestroyAllTotems(uint32 /*i*/)
5841{
5842    float mana = 0;
5843    for(int slot = 0;  slot < MAX_TOTEM; ++slot)
5844    {
5845        if(!m_caster->m_TotemSlot[slot])
5846            continue;
5847
5848        Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
5849        if(totem && totem->isTotem())
5850        {
5851            uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
5852            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
5853            if(spellInfo)
5854                mana += spellInfo->manaCost * damage / 100;
5855            ((Totem*)totem)->UnSummon();
5856        }
5857    }
5858
5859    int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
5860    m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
5861}
5862
5863void Spell::EffectDurabilityDamage(uint32 i)
5864{
5865    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5866        return;
5867
5868    int32 slot = m_spellInfo->EffectMiscValue[i];
5869
5870    // FIXME: some spells effects have value -1/-2
5871    // Possibly its mean -1 all player equipped items and -2 all items
5872    if(slot < 0)
5873    {
5874        ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
5875        return;
5876    }
5877
5878    // invalid slot value
5879    if(slot >= INVENTORY_SLOT_BAG_END)
5880        return;
5881
5882    if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5883        ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
5884}
5885
5886void Spell::EffectDurabilityDamagePCT(uint32 i)
5887{
5888    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5889        return;
5890
5891    int32 slot = m_spellInfo->EffectMiscValue[i];
5892
5893    // FIXME: some spells effects have value -1/-2
5894    // Possibly its mean -1 all player equipped items and -2 all items
5895    if(slot < 0)
5896    {
5897        ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
5898        return;
5899    }
5900
5901    // invalid slot value
5902    if(slot >= INVENTORY_SLOT_BAG_END)
5903        return;
5904
5905    if(damage <= 0)
5906        return;
5907
5908    if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5909        ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
5910}
5911
5912void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
5913{
5914    if(!unitTarget)
5915        return;
5916
5917    unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
5918}
5919
5920void Spell::EffectTransmitted(uint32 effIndex)
5921{
5922    uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
5923
5924    GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
5925
5926    if (!goinfo)
5927    {
5928        sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
5929        return;
5930    }
5931
5932    float fx,fy,fz;
5933
5934    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5935    {
5936        fx = m_targets.m_destX;
5937        fy = m_targets.m_destY;
5938        fz = m_targets.m_destZ;
5939    }
5940    //FIXME: this can be better check for most objects but still hack
5941    else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
5942    {
5943        float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
5944        m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5945    }
5946    else
5947    {
5948        float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5949        float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5950        float dis = rand_norm() * (max_dis - min_dis) + min_dis;
5951
5952        m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5953    }
5954
5955    Map *cMap = m_caster->GetMap();
5956
5957    if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
5958    {
5959        if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
5960        { // but this is not proper, we really need to ignore not materialized objects
5961            SendCastResult(SPELL_FAILED_NOT_HERE);
5962            SendChannelUpdate(0);
5963            return;
5964        }
5965
5966        // replace by water level in this case
5967        fz = cMap->GetWaterLevel(fx,fy);
5968    }
5969    // if gameobject is summoning object, it should be spawned right on caster's position
5970    else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
5971    {
5972        m_caster->GetPosition(fx,fy,fz);
5973    }
5974
5975    GameObject* pGameObj = new GameObject;
5976
5977    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
5978        fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
5979    {
5980        delete pGameObj;
5981        return;
5982    }
5983
5984    int32 duration = GetSpellDuration(m_spellInfo);
5985
5986    switch(goinfo->type)
5987    {
5988        case GAMEOBJECT_TYPE_FISHINGNODE:
5989        {
5990            m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
5991                                                            // Orientation3
5992            pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 );
5993                                                            // Orientation4
5994            pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 );
5995            m_caster->AddGameObject(pGameObj);              // will removed at spell cancel
5996
5997            // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
5998            // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
5999            int32 lastSec;
6000            switch(urand(0, 3))
6001            {
6002                case 0: lastSec =  3; break;
6003                case 1: lastSec =  7; break;
6004                case 2: lastSec = 13; break;
6005                case 3: lastSec = 17; break;
6006            }
6007
6008            duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000;
6009            break;
6010        }
6011        case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6012        {
6013            if(m_caster->GetTypeId()==TYPEID_PLAYER)
6014            {
6015                pGameObj->AddUniqueUse((Player*)m_caster);
6016                m_caster->AddGameObject(pGameObj);          // will removed at spell cancel
6017            }
6018            break;
6019        }
6020        case GAMEOBJECT_TYPE_FISHINGHOLE:
6021        case GAMEOBJECT_TYPE_CHEST:
6022        default:
6023        {
6024            break;
6025        }
6026    }
6027
6028    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6029
6030    pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6031
6032    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6033    pGameObj->SetSpellId(m_spellInfo->Id);
6034
6035    DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6036    //m_caster->AddGameObject(pGameObj);
6037    //m_ObjToDel.push_back(pGameObj);
6038
6039    cMap->Add(pGameObj);
6040
6041    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6042    data << uint64(pGameObj->GetGUID());
6043    m_caster->SendMessageToSet(&data,true);
6044
6045    if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6046    {
6047        GameObject* linkedGO = new GameObject;
6048        if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6049            fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6050        {
6051            linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6052            linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6053            linkedGO->SetSpellId(m_spellInfo->Id);
6054            linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6055
6056            MapManager::Instance().GetMap(linkedGO->GetMapId(), linkedGO)->Add(linkedGO);
6057        }
6058        else
6059        {
6060            delete linkedGO;
6061            linkedGO = NULL;
6062            return;
6063        }
6064    }
6065}
6066
6067void Spell::EffectProspecting(uint32 /*i*/)
6068{
6069    if(m_caster->GetTypeId() != TYPEID_PLAYER)
6070        return;
6071
6072    Player* p_caster = (Player*)m_caster;
6073    if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6074        return;
6075
6076    if(itemTarget->GetCount() < 5)
6077        return;
6078
6079    if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6080    {
6081        uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6082        uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6083        p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6084    }
6085
6086    ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6087}
6088
6089void Spell::EffectSkill(uint32 /*i*/)
6090{
6091    sLog.outDebug("WORLD: SkillEFFECT");
6092}
6093
6094void Spell::EffectSummonDemon(uint32 i)
6095{
6096    float px = m_targets.m_destX;
6097    float py = m_targets.m_destY;
6098    float pz = m_targets.m_destZ;
6099
6100    Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000);
6101    if (!Charmed)
6102        return;
6103
6104    // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6105    Charmed->SetLevel(m_caster->getLevel());
6106
6107    // TODO: Add damage/mana/hp according to level
6108
6109    if (m_spellInfo->EffectMiscValue[i] == 89)              // Inferno summon
6110    {
6111        // Enslave demon effect, without mana cost and cooldown
6112        m_caster->CastSpell(Charmed, 20882, true);          // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6113
6114        // Inferno effect
6115        Charmed->CastSpell(Charmed, 22703, true, 0);
6116    }
6117}
6118
6119/* There is currently no need for this effect. We handle it in BattleGround.cpp
6120   If we would handle the resurrection here, the spiritguide would instantly disappear as the
6121   player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6122   This is why we use a half sec delay between the visual effect and the resurrection itself */
6123void Spell::EffectSpiritHeal(uint32 /*i*/)
6124{
6125    /*
6126    if(!unitTarget || unitTarget->isAlive())
6127        return;
6128    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6129        return;
6130    if(!unitTarget->IsInWorld())
6131        return;
6132
6133    //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6134    //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6135    ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6136    ((Player*)unitTarget)->SpawnCorpseBones();
6137    */
6138}
6139
6140// remove insignia spell effect
6141void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6142{
6143    sLog.outDebug("Effect: SkinPlayerCorpse");
6144    if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6145        return;
6146
6147    ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6148}
6149
6150void Spell::EffectStealBeneficialBuff(uint32 i)
6151{
6152    sLog.outDebug("Effect: StealBeneficialBuff");
6153
6154    if(!unitTarget || unitTarget==m_caster)                 // can't steal from self
6155        return;
6156
6157    std::vector <Aura *> steal_list;
6158    // Create dispel mask by dispel type
6159    uint32 dispelMask  = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6160    Unit::AuraMap const& auras = unitTarget->GetAuras();
6161    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6162    {
6163        Aura *aur = (*itr).second;
6164        if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6165        {
6166            // Need check for passive? this
6167            if (aur->IsPositive() && !aur->IsPassive())
6168                steal_list.push_back(aur);
6169        }
6170    }
6171    // Ok if exist some buffs for dispel try dispel it
6172    if (!steal_list.empty())
6173    {
6174        std::list < std::pair<uint32,uint64> > success_list;
6175        int32 list_size = steal_list.size();
6176        // Dispell N = damage buffs (or while exist buffs for dispel)
6177        for (int32 count=0; count < damage && list_size > 0; ++count)
6178        {
6179            // Random select buff for dispel
6180            Aura *aur = steal_list[urand(0, list_size-1)];
6181            // Not use chance for steal
6182            // TODO possible need do it
6183            success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6184
6185            // Remove buff from list for prevent doubles
6186            for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6187            {
6188                Aura *stealed = *j;
6189                if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6190                {
6191                    j = steal_list.erase(j);
6192                    --list_size;
6193                }
6194                else
6195                    ++j;
6196            }
6197        }
6198        // Really try steal and send log
6199        if (!success_list.empty())
6200        {
6201            int32 count = success_list.size();
6202            WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6203            data.append(unitTarget->GetPackGUID());  // Victim GUID
6204            data.append(m_caster->GetPackGUID());    // Caster GUID
6205            data << uint32(m_spellInfo->Id);         // Dispell spell id
6206            data << uint8(0);                        // not used
6207            data << uint32(count);                   // count
6208            for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6209            {
6210                SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6211                data << uint32(spellInfo->Id);       // Spell Id
6212                data << uint8(0);                    // 0 - steals !=0 transfers
6213                unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6214            }
6215            m_caster->SendMessageToSet(&data, true);
6216        }
6217    }
6218}
6219
6220void Spell::EffectKillCredit(uint32 i)
6221{
6222    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6223        return;
6224
6225    ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0);
6226}
6227
6228void Spell::EffectQuestFail(uint32 i)
6229{
6230    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6231        return;
6232
6233    ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6234}
Note: See TracBrowser for help on using the browser.