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

Revision 246, 244.1 kB (checked in by yumileroy, 17 years ago)

*Fix Gruul's shatter effect damage. Patch provided by _krz.

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