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

Revision 221, 240.1 kB (checked in by yumileroy, 17 years ago)

[svn] Fix a bug that players cannot hear others talking.
Provide script support for type 10 gameobject.
Add some missing script sql.

Original author: megamage
Date: 2008-11-12 16:21:08-06:00

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