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

Revision 213, 240.0 kB (checked in by yumileroy, 17 years ago)

[svn] Fix some aura_interrupt_flag to correctly remove auras.
Add interrupt_flag_unattackable. Source: mangos forum. Adapted by F636y623.
Add function CombatStart?().

Original author: megamage
Date: 2008-11-11 17:49:51-06:00

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