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

Revision 160, 240.2 kB (checked in by yumileroy, 17 years ago)

[svn] Update black temple boss 1, 2 script.

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