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

Revision 126, 236.6 kB (checked in by yumileroy, 17 years ago)

[svn] * Fixed startup error flood if creature model id is 0
* Fixed totems using proper model ids broken after recent change
* Set pet grid activity state to that of caster upon summoning
* Fix a possible crash in ObjectAccessor?
note to self: don't commit anything without 3 days testing. ever. after this one ofc.

Original author: w12x
Date: 2008-10-27 15:28:04-05:00

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