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

Revision 136, 242.0 kB (checked in by yumileroy, 17 years ago)

[svn] Provide creature dual wield support.
Update glancing damage formula.
Do not daze creatures when other creatures attack from the back (need to find a better way).
Fix the damage calculation of +damage aura.

Original author: megamage
Date: 2008-10-29 20:00:21-05:00

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