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

Revision 240, 243.3 kB (checked in by yumileroy, 17 years ago)

[svn] Added missing includes.

Original author: w12x
Date: 2008-11-15 15:11:31-06:00

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