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

Revision 18, 244.4 kB (checked in by yumileroy, 17 years ago)

[svn] * Little fix in RandomMovementGenerator?
* Updated to 6731 and 680

Original author: Neo2003
Date: 2008-10-06 04:48:59-05:00

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