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

Revision 130, 241.9 kB (checked in by yumileroy, 17 years ago)

[svn] Add new function SelectUnit? and SelectUnitList? to select target or targets with check "isPlayer" and "isWithinDist". Also add target type SELECT_TARGET_NEAREST and SELECT_TARGET_FARTHEST.
SpellEffect? Fix for 40802,29364,43723,41931. Patch provided by WarHead?.
Update script of Fathom Lord. Patch provided by Blaymoira.

Original author: megamage
Date: 2008-10-28 16:28:42-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    if (unitTarget->GetTypeId() == TYPEID_PLAYER)
3444        ((Player*)unitTarget)->SetCanDualWield(true);
3445}
3446
3447void Spell::EffectPull(uint32 /*i*/)
3448{
3449    // TODO: create a proper pull towards distract spell center for distract
3450    sLog.outDebug("WORLD: Spell Effect DUMMY");
3451}
3452
3453void Spell::EffectDistract(uint32 /*i*/)
3454{
3455    // Check for possible target
3456    if (!unitTarget || unitTarget->isInCombat())
3457        return;
3458
3459    // target must be OK to do this
3460    if( unitTarget->hasUnitState(UNIT_STAT_CONFUSED | UNIT_STAT_STUNNED | UNIT_STAT_FLEEING ) )
3461        return;
3462
3463    float angle = unitTarget->GetAngle(m_targets.m_destX, m_targets.m_destY);
3464
3465    if ( unitTarget->GetTypeId() == TYPEID_PLAYER )
3466    {
3467        // For players just turn them
3468        WorldPacket data;
3469        ((Player*)unitTarget)->BuildTeleportAckMsg(&data, unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle);
3470        ((Player*)unitTarget)->GetSession()->SendPacket( &data );
3471        ((Player*)unitTarget)->SetPosition(unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), angle, false);
3472    }
3473    else
3474    {
3475        // Set creature Distracted, Stop it, And turn it
3476        unitTarget->SetOrientation(angle);
3477        unitTarget->StopMoving();
3478        unitTarget->GetMotionMaster()->MoveDistract(damage*1000);
3479    }
3480}
3481
3482void Spell::EffectPickPocket(uint32 /*i*/)
3483{
3484    if( m_caster->GetTypeId() != TYPEID_PLAYER )
3485        return;
3486
3487    // victim must be creature and attackable
3488    if( !unitTarget || unitTarget->GetTypeId() != TYPEID_UNIT || m_caster->IsFriendlyTo(unitTarget) )
3489        return;
3490
3491    // victim have to be alive and humanoid or undead
3492    if( unitTarget->isAlive() && (unitTarget->GetCreatureTypeMask() &CREATURE_TYPEMASK_HUMANOID_OR_UNDEAD) != 0)
3493    {
3494        int32 chance = 10 + int32(m_caster->getLevel()) - int32(unitTarget->getLevel());
3495
3496        if (chance > irand(0, 19))
3497        {
3498            // Stealing successful
3499            //sLog.outDebug("Sending loot from pickpocket");
3500            ((Player*)m_caster)->SendLoot(unitTarget->GetGUID(),LOOT_PICKPOCKETING);
3501        }
3502        else
3503        {
3504            // Reveal action + get attack
3505            m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
3506            if (((Creature*)unitTarget)->AI())
3507                ((Creature*)unitTarget)->AI()->AttackStart(m_caster);
3508        }
3509    }
3510}
3511
3512void Spell::EffectAddFarsight(uint32 i)
3513{
3514    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3515    int32 duration = GetSpellDuration(m_spellInfo);
3516    DynamicObject* dynObj = new DynamicObject;
3517    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))
3518    {
3519        delete dynObj;
3520        return;
3521    }
3522    dynObj->SetUInt32Value(OBJECT_FIELD_TYPE, 65);
3523    dynObj->SetUInt32Value(DYNAMICOBJECT_BYTES, 0x80000002);
3524    m_caster->AddDynObject(dynObj);
3525    MapManager::Instance().GetMap(dynObj->GetMapId(), dynObj)->Add(dynObj);
3526    m_caster->SetUInt64Value(PLAYER_FARSIGHT, dynObj->GetGUID());
3527}
3528
3529void Spell::EffectSummonWild(uint32 i)
3530{
3531    uint32 creature_entry = m_spellInfo->EffectMiscValue[i];
3532    if(!creature_entry)
3533        return;
3534
3535    uint32 level = m_caster->getLevel();
3536
3537    // level of creature summoned using engineering item based at engineering skill level
3538    if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3539    {
3540        ItemPrototype const *proto = m_CastItem->GetProto();
3541        if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3542        {
3543            uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3544            if(skill202)
3545            {
3546                level = skill202/5;
3547            }
3548        }
3549    }
3550
3551    // select center of summon position
3552    float center_x = m_targets.m_destX;
3553    float center_y = m_targets.m_destY;
3554    float center_z = m_targets.m_destZ;
3555
3556    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3557
3558    int32 amount = damage > 0 ? damage : 1;
3559
3560    for(int32 count = 0; count < amount; ++count)
3561    {
3562        float px, py, pz;
3563        // If dest location if present
3564        if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3565        {
3566            // Summon 1 unit in dest location
3567            if (count == 0)
3568            {
3569                px = m_targets.m_destX;
3570                py = m_targets.m_destY;
3571                pz = m_targets.m_destZ;
3572            }
3573            // Summon in random point all other units if location present
3574            else
3575                m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3576        }
3577        // Summon if dest location not present near caster
3578        else
3579            m_caster->GetClosePoint(px,py,pz,3.0f);
3580
3581        int32 duration = GetSpellDuration(m_spellInfo);
3582
3583        TempSummonType summonType = (duration == 0) ? TEMPSUMMON_DEAD_DESPAWN : TEMPSUMMON_TIMED_DESPAWN;
3584
3585        if(m_originalCaster)
3586            m_originalCaster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3587        else
3588            m_caster->SummonCreature(creature_entry,px,py,pz,m_caster->GetOrientation(),summonType,duration);
3589    }
3590}
3591
3592void Spell::EffectSummonGuardian(uint32 i)
3593{
3594    uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
3595    if(!pet_entry)
3596        return;
3597
3598    // Jewelery statue case (totem like)
3599    if(m_spellInfo->SpellIconID==2056)
3600    {
3601        EffectSummonTotem(i);
3602        return;
3603    }
3604
3605    // set timer for unsummon
3606    int32 duration = GetSpellDuration(m_spellInfo);
3607
3608    // Search old Guardian only for players (if casted spell not have duration or cooldown)
3609    // FIXME: some guardians have control spell applied and controlled by player and anyway player can't summon in this time
3610    //        so this code hack in fact
3611    if( m_caster->GetTypeId() == TYPEID_PLAYER && (duration <= 0 || GetSpellRecoveryTime(m_spellInfo)==0) )
3612        if(((Player*)m_caster)->HasGuardianWithEntry(pet_entry))
3613            return;                                         // find old guardian, ignore summon
3614
3615    // in another case summon new
3616    uint32 level = m_caster->getLevel();
3617
3618    // level of pet summoned using engineering item based at engineering skill level
3619    if(m_caster->GetTypeId()==TYPEID_PLAYER && m_CastItem)
3620    {
3621        ItemPrototype const *proto = m_CastItem->GetProto();
3622        if(proto && proto->RequiredSkill == SKILL_ENGINERING)
3623        {
3624            uint16 skill202 = ((Player*)m_caster)->GetSkillValue(SKILL_ENGINERING);
3625            if(skill202)
3626            {
3627                level = skill202/5;
3628            }
3629        }
3630    }
3631
3632    // select center of summon position
3633    float center_x = m_targets.m_destX;
3634    float center_y = m_targets.m_destY;
3635    float center_z = m_targets.m_destZ;
3636
3637    float radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3638
3639    int32 amount = damage > 0 ? damage : 1;
3640
3641    for(int32 count = 0; count < amount; ++count)
3642    {
3643        Pet* spawnCreature = new Pet(GUARDIAN_PET);
3644        spawnCreature->setActive(m_caster->isActive());
3645
3646        Map *map = m_caster->GetMap();
3647        uint32 pet_number = objmgr.GeneratePetNumber();
3648        if(!spawnCreature->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map,m_spellInfo->EffectMiscValue[i], pet_number))
3649        {
3650            sLog.outError("no such creature entry %u",m_spellInfo->EffectMiscValue[i]);
3651            delete spawnCreature;
3652            return;
3653        }
3654
3655        float px, py, pz;
3656        // If dest location if present
3657        if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
3658        {
3659            // Summon 1 unit in dest location
3660            if (count == 0)
3661            {
3662                px = m_targets.m_destX;
3663                py = m_targets.m_destY;
3664                pz = m_targets.m_destZ;
3665            }
3666            // Summon in random point all other units if location present
3667            else
3668                m_caster->GetRandomPoint(center_x,center_y,center_z,radius,px,py,pz);
3669        }
3670        // Summon if dest location not present near caster
3671        else
3672            m_caster->GetClosePoint(px,py,pz,spawnCreature->GetObjectSize());
3673
3674        spawnCreature->Relocate(px,py,pz,m_caster->GetOrientation());
3675
3676        if(!spawnCreature->IsPositionValid())
3677        {
3678            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());
3679            delete spawnCreature;
3680            return;
3681        }
3682
3683        if(duration > 0)
3684            spawnCreature->SetDuration(duration);
3685
3686        spawnCreature->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
3687        spawnCreature->setPowerType(POWER_MANA);
3688        spawnCreature->SetUInt32Value(UNIT_NPC_FLAGS , 0);
3689        spawnCreature->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3690        spawnCreature->SetUInt32Value(UNIT_FIELD_FLAGS,0);
3691        spawnCreature->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
3692        spawnCreature->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,0);
3693        spawnCreature->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
3694        spawnCreature->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3695
3696        spawnCreature->InitStatsForLevel(level);
3697        spawnCreature->GetCharmInfo()->SetPetNumber(pet_number, false);
3698
3699        spawnCreature->AIM_Initialize();
3700
3701        if(m_caster->GetTypeId()==TYPEID_PLAYER)
3702            ((Player*)m_caster)->AddGuardian(spawnCreature);
3703
3704        map->Add((Creature*)spawnCreature);
3705    }
3706}
3707
3708void Spell::EffectTeleUnitsFaceCaster(uint32 i)
3709{
3710    if(!unitTarget)
3711        return;
3712
3713    if(unitTarget->isInFlight())
3714        return;
3715
3716    uint32 mapid = m_caster->GetMapId();
3717    float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3718
3719    float fx,fy,fz;
3720    m_caster->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
3721
3722    if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3723        ((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));
3724    else
3725        MapManager::Instance().GetMap(mapid, m_caster)->CreatureRelocation((Creature*)m_caster, fx, fy, fz, -m_caster->GetOrientation());
3726}
3727
3728void Spell::EffectLearnSkill(uint32 i)
3729{
3730    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3731        return;
3732
3733    if(damage < 0)
3734        return;
3735
3736    uint32 skillid =  m_spellInfo->EffectMiscValue[i];
3737    uint16 skillval = ((Player*)unitTarget)->GetPureSkillValue(skillid);
3738    ((Player*)unitTarget)->SetSkill(skillid, skillval?skillval:1, damage*75);
3739}
3740
3741void Spell::EffectAddHonor(uint32 /*i*/)
3742{
3743    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3744        return;
3745
3746    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());
3747
3748    // TODO: find formula for honor reward based on player's level!
3749
3750    // now fixed only for level 70 players:
3751    if (((Player*)unitTarget)->getLevel() == 70)
3752        ((Player*)unitTarget)->RewardHonor(NULL, 1, this->damage);
3753}
3754
3755void Spell::EffectTradeSkill(uint32 /*i*/)
3756{
3757    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
3758        return;
3759    // uint32 skillid =  m_spellInfo->EffectMiscValue[i];
3760    // uint16 skillmax = ((Player*)unitTarget)->(skillid);
3761    // ((Player*)unitTarget)->SetSkill(skillid,skillval?skillval:1,skillmax+75);
3762}
3763
3764void Spell::EffectEnchantItemPerm(uint32 i)
3765{
3766    if(m_caster->GetTypeId() != TYPEID_PLAYER)
3767        return;
3768    if (!itemTarget)
3769        return;
3770
3771    Player* p_caster = (Player*)m_caster;
3772
3773    p_caster->UpdateCraftSkill(m_spellInfo->Id);
3774
3775    if (m_spellInfo->EffectMiscValue[i])
3776    {
3777        uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3778
3779        SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3780        if(!pEnchant)
3781            return;
3782
3783        // item can be in trade slot and have owner diff. from caster
3784        Player* item_owner = itemTarget->GetOwner();
3785        if(!item_owner)
3786            return;
3787
3788        if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3789            sLog.outCommand("GM %s (Account: %u) enchanting(perm): %s (Entry: %d) for player: %s (Account: %u)",
3790                p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3791                itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3792                item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3793
3794        // remove old enchanting before applying new if equipped
3795        item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,false);
3796
3797        itemTarget->SetEnchantment(PERM_ENCHANTMENT_SLOT, enchant_id, 0, 0);
3798
3799        // add new enchanting if equipped
3800        item_owner->ApplyEnchantment(itemTarget,PERM_ENCHANTMENT_SLOT,true);
3801    }
3802}
3803
3804void Spell::EffectEnchantItemTmp(uint32 i)
3805{
3806    if(m_caster->GetTypeId() != TYPEID_PLAYER)
3807        return;
3808
3809    Player* p_caster = (Player*)m_caster;
3810
3811    if(!itemTarget)
3812        return;
3813
3814    uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
3815
3816    // Shaman Rockbiter Weapon
3817    if(i==0 && m_spellInfo->Effect[1]==SPELL_EFFECT_DUMMY)
3818    {
3819        int32 enchnting_damage = m_currentBasePoints[1]+1;
3820
3821        // enchanting id selected by calculated damage-per-sec stored in Effect[1] base value
3822        // with already applied percent bonus from Elemental Weapons talent
3823        // Note: damage calculated (correctly) with rounding int32(float(v)) but
3824        // RW enchantments applied damage int32(float(v)+0.5), this create  0..1 difference sometime
3825        switch(enchnting_damage)
3826        {
3827            // Rank 1
3828            case  2: enchant_id =   29; break;              //  0% [ 7% ==  2, 14% == 2, 20% == 2]
3829            // Rank 2
3830            case  4: enchant_id =    6; break;              //  0% [ 7% ==  4, 14% == 4]
3831            case  5: enchant_id = 3025; break;              // 20%
3832            // Rank 3
3833            case  6: enchant_id =    1; break;              //  0% [ 7% ==  6, 14% == 6]
3834            case  7: enchant_id = 3027; break;              // 20%
3835            // Rank 4
3836            case  9: enchant_id = 3032; break;              //  0% [ 7% ==  6]
3837            case 10: enchant_id =  503; break;              // 14%
3838            case 11: enchant_id = 3031; break;              // 20%
3839            // Rank 5
3840            case 15: enchant_id = 3035; break;              // 0%
3841            case 16: enchant_id = 1663; break;              // 7%
3842            case 17: enchant_id = 3033; break;              // 14%
3843            case 18: enchant_id = 3034; break;              // 20%
3844            // Rank 6
3845            case 28: enchant_id = 3038; break;              // 0%
3846            case 29: enchant_id =  683; break;              // 7%
3847            case 31: enchant_id = 3036; break;              // 14%
3848            case 33: enchant_id = 3037; break;              // 20%
3849            // Rank 7
3850            case 40: enchant_id = 3041; break;              // 0%
3851            case 42: enchant_id = 1664; break;              // 7%
3852            case 45: enchant_id = 3039; break;              // 14%
3853            case 48: enchant_id = 3040; break;              // 20%
3854            // Rank 8
3855            case 49: enchant_id = 3044; break;              // 0%
3856            case 52: enchant_id = 2632; break;              // 7%
3857            case 55: enchant_id = 3042; break;              // 14%
3858            case 58: enchant_id = 3043; break;              // 20%
3859            // Rank 9
3860            case 62: enchant_id = 2633; break;              // 0%
3861            case 66: enchant_id = 3018; break;              // 7%
3862            case 70: enchant_id = 3019; break;              // 14%
3863            case 74: enchant_id = 3020; break;              // 20%
3864            default:
3865                sLog.outError("Spell::EffectEnchantItemTmp: Damage %u not handled in S'RW",enchnting_damage);
3866                return;
3867        }
3868    }
3869
3870    if (!enchant_id)
3871    {
3872        sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have 0 as enchanting id",m_spellInfo->Id,i);
3873        return;
3874    }
3875
3876    SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
3877    if(!pEnchant)
3878    {
3879        sLog.outError("Spell %u Effect %u (SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY) have not existed enchanting id %u ",m_spellInfo->Id,i,enchant_id);
3880        return;
3881    }
3882
3883    // select enchantment duration
3884    uint32 duration;
3885
3886    // rogue family enchantments exception by duration
3887    if(m_spellInfo->Id==38615)
3888        duration = 1800;                                    // 30 mins
3889    // other rogue family enchantments always 1 hour (some have spell damage=0, but some have wrong data in EffBasePoints)
3890    else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE)
3891        duration = 3600;                                    // 1 hour
3892    // shaman family enchantments
3893    else if(m_spellInfo->SpellFamilyName==SPELLFAMILY_SHAMAN)
3894        duration = 1800;                                    // 30 mins
3895    // other cases with this SpellVisual already selected
3896    else if(m_spellInfo->SpellVisual==215)
3897        duration = 1800;                                    // 30 mins
3898    // some fishing pole bonuses
3899    else if(m_spellInfo->SpellVisual==563)
3900        duration = 600;                                     // 10 mins
3901    // shaman rockbiter enchantments
3902    else if(m_spellInfo->SpellVisual==0)
3903        duration = 1800;                                    // 30 mins
3904    else if(m_spellInfo->Id==29702)
3905        duration = 300;                                     // 5 mins
3906    else if(m_spellInfo->Id==37360)
3907        duration = 300;                                     // 5 mins
3908    // default case
3909    else
3910        duration = 3600;                                    // 1 hour
3911
3912    // item can be in trade slot and have owner diff. from caster
3913    Player* item_owner = itemTarget->GetOwner();
3914    if(!item_owner)
3915        return;
3916
3917    if(item_owner!=p_caster && p_caster->GetSession()->GetSecurity() > SEC_PLAYER && sWorld.getConfig(CONFIG_GM_LOG_TRADE) )
3918        sLog.outCommand("GM %s (Account: %u) enchanting(temp): %s (Entry: %d) for player: %s (Account: %u)",
3919            p_caster->GetName(),p_caster->GetSession()->GetAccountId(),
3920            itemTarget->GetProto()->Name1,itemTarget->GetEntry(),
3921            item_owner->GetName(),item_owner->GetSession()->GetAccountId());
3922
3923    // remove old enchanting before applying new if equipped
3924    item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,false);
3925
3926    itemTarget->SetEnchantment(TEMP_ENCHANTMENT_SLOT, enchant_id, duration*1000, 0);
3927
3928    // add new enchanting if equipped
3929    item_owner->ApplyEnchantment(itemTarget,TEMP_ENCHANTMENT_SLOT,true);
3930}
3931
3932void Spell::EffectTameCreature(uint32 /*i*/)
3933{
3934    if(m_caster->GetPetGUID())
3935        return;
3936
3937    if(!unitTarget)
3938        return;
3939
3940    if(unitTarget->GetTypeId() == TYPEID_PLAYER)
3941        return;
3942
3943    Creature* creatureTarget = (Creature*)unitTarget;
3944
3945    if(creatureTarget->isPet())
3946        return;
3947
3948    if(m_caster->getClass() == CLASS_HUNTER)
3949    {
3950        // cast finish successfully
3951        //SendChannelUpdate(0);
3952        finish();
3953
3954        Pet* pet = new Pet(HUNTER_PET);
3955
3956        if(!pet->CreateBaseAtCreature(creatureTarget))
3957        {
3958            delete pet;
3959            return;
3960        }
3961
3962        creatureTarget->setDeathState(JUST_DIED);
3963        creatureTarget->RemoveCorpse();
3964        creatureTarget->SetHealth(0);                       // just for nice GM-mode view
3965
3966        pet->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
3967        pet->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
3968        pet->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
3969        pet->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
3970
3971        if(!pet->InitStatsForLevel(creatureTarget->getLevel()))
3972        {
3973            sLog.outError("ERROR: InitStatsForLevel() in EffectTameCreature failed! Pet deleted.");
3974            delete pet;
3975            return;
3976        }
3977
3978        // prepare visual effect for levelup
3979        pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel()-1);
3980
3981        pet->GetCharmInfo()->SetPetNumber(objmgr.GeneratePetNumber(), true);
3982                                                            // this enables pet details window (Shift+P)
3983        pet->AIM_Initialize();
3984        pet->InitPetCreateSpells();
3985        pet->SetHealth(pet->GetMaxHealth());
3986
3987        MapManager::Instance().GetMap(pet->GetMapId(), pet)->Add((Creature*)pet);
3988
3989        // visual effect for levelup
3990        pet->SetUInt32Value(UNIT_FIELD_LEVEL,creatureTarget->getLevel());
3991
3992        if(m_caster->GetTypeId() == TYPEID_PLAYER)
3993        {
3994            m_caster->SetPet(pet);
3995            pet->SavePetToDB(PET_SAVE_AS_CURRENT);
3996            ((Player*)m_caster)->PetSpellInitialize();
3997        }
3998    }
3999}
4000
4001void Spell::EffectSummonPet(uint32 i)
4002{
4003    uint32 petentry = m_spellInfo->EffectMiscValue[i];
4004
4005    Pet *OldSummon = m_caster->GetPet();
4006
4007    // if pet requested type already exist
4008    if( OldSummon )
4009    {
4010        if(petentry == 0 || OldSummon->GetEntry() == petentry)
4011        {
4012            // pet in corpse state can't be summoned
4013            if( OldSummon->isDead() )
4014                return;
4015
4016            MapManager::Instance().GetMap(OldSummon->GetMapId(), OldSummon)->Remove((Creature*)OldSummon,false);
4017            OldSummon->SetMapId(m_caster->GetMapId());
4018
4019            float px, py, pz;
4020            m_caster->GetClosePoint(px, py, pz, OldSummon->GetObjectSize());
4021
4022            OldSummon->Relocate(px, py, pz, OldSummon->GetOrientation());
4023            MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->Add((Creature*)OldSummon);
4024
4025            if(m_caster->GetTypeId() == TYPEID_PLAYER && OldSummon->isControlled() )
4026            {
4027                ((Player*)m_caster)->PetSpellInitialize();
4028            }
4029            return;
4030        }
4031
4032        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4033            ((Player*)m_caster)->RemovePet(OldSummon,(OldSummon->getPetType()==HUNTER_PET ? PET_SAVE_AS_DELETED : PET_SAVE_NOT_IN_SLOT),false);
4034        else
4035            return;
4036    }
4037
4038    Pet* NewSummon = new Pet;
4039    NewSummon->setActive(m_caster->isActive());
4040
4041    // petentry==0 for hunter "call pet" (current pet summoned if any)
4042    if(NewSummon->LoadPetFromDB(m_caster,petentry))
4043    {
4044        if(NewSummon->getPetType()==SUMMON_PET)
4045        {
4046            // Remove Demonic Sacrifice auras (known pet)
4047            Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4048            for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4049            {
4050                if((*itr)->GetModifier()->m_miscvalue==2228)
4051                {
4052                    m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4053                    itr = auraClassScripts.begin();
4054                }
4055                else
4056                    ++itr;
4057            }
4058        }
4059
4060        return;
4061    }
4062
4063    // not error in case fail hunter call pet
4064    if(!petentry)
4065    {
4066        delete NewSummon;
4067        return;
4068    }
4069
4070    CreatureInfo const* cInfo = sCreatureStorage.LookupEntry<CreatureInfo>(petentry);
4071
4072    if(!cInfo)
4073    {
4074        sLog.outError("EffectSummonPet: creature entry %u not found.",petentry);
4075        delete NewSummon;
4076        return;
4077    }
4078
4079    Map *map = m_caster->GetMap();
4080    uint32 pet_number = objmgr.GeneratePetNumber();
4081    if(!NewSummon->Create(objmgr.GenerateLowGuid(HIGHGUID_PET), map, petentry, pet_number))
4082    {
4083        delete NewSummon;
4084        return;
4085    }
4086
4087    float px, py, pz;
4088    m_caster->GetClosePoint(px, py, pz, NewSummon->GetObjectSize());
4089
4090    NewSummon->Relocate(px, py, pz, m_caster->GetOrientation());
4091
4092    if(!NewSummon->IsPositionValid())
4093    {
4094        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());
4095        delete NewSummon;
4096        return;
4097    }
4098
4099    uint32 petlevel = m_caster->getLevel();
4100    NewSummon->setPetType(SUMMON_PET);
4101
4102    uint32 faction = m_caster->getFaction();
4103    if(m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->isTotem())
4104    {
4105        Unit* owner = ((Totem*)m_caster)->GetOwner();
4106        if(owner)
4107            faction = owner->getFaction();
4108        NewSummon->GetCharmInfo()->SetReactState(REACT_AGGRESSIVE);
4109    }
4110
4111    NewSummon->SetUInt64Value(UNIT_FIELD_SUMMONEDBY, m_caster->GetGUID());
4112    NewSummon->SetUInt64Value(UNIT_FIELD_CREATEDBY, m_caster->GetGUID());
4113    NewSummon->SetUInt32Value(UNIT_NPC_FLAGS , 0);
4114    NewSummon->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE, faction);
4115    NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_0,2048);
4116    NewSummon->SetUInt32Value(UNIT_FIELD_BYTES_1,0);
4117    NewSummon->SetUInt32Value(UNIT_FIELD_PET_NAME_TIMESTAMP,time(NULL));
4118    NewSummon->SetUInt32Value(UNIT_FIELD_PETEXPERIENCE,0);
4119    NewSummon->SetUInt32Value(UNIT_FIELD_PETNEXTLEVELEXP,1000);
4120    NewSummon->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
4121
4122    NewSummon->GetCharmInfo()->SetPetNumber(pet_number, true);
4123    // this enables pet details window (Shift+P)
4124
4125    // this enables popup window (pet dismiss, cancel), hunter pet additional flags set later
4126    NewSummon->SetUInt32Value(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
4127
4128    NewSummon->InitStatsForLevel( petlevel);
4129    NewSummon->InitPetCreateSpells();
4130
4131    if(NewSummon->getPetType()==SUMMON_PET)
4132    {
4133        // Remove Demonic Sacrifice auras (new pet)
4134        Unit::AuraList const& auraClassScripts = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4135        for(Unit::AuraList::const_iterator itr = auraClassScripts.begin();itr!=auraClassScripts.end();)
4136        {
4137            if((*itr)->GetModifier()->m_miscvalue==2228)
4138            {
4139                m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4140                itr = auraClassScripts.begin();
4141            }
4142            else
4143                ++itr;
4144        }
4145
4146        // generate new name for summon pet
4147        std::string new_name=objmgr.GeneratePetName(petentry);
4148        if(!new_name.empty())
4149            NewSummon->SetName(new_name);
4150    }
4151    else if(NewSummon->getPetType()==HUNTER_PET)
4152        NewSummon->SetByteValue(UNIT_FIELD_BYTES_2, 2, UNIT_RENAME_NOT_ALLOWED);
4153
4154    NewSummon->AIM_Initialize();
4155    NewSummon->SetHealth(NewSummon->GetMaxHealth());
4156    NewSummon->SetPower(POWER_MANA, NewSummon->GetMaxPower(POWER_MANA));
4157
4158    map->Add((Creature*)NewSummon);
4159
4160    m_caster->SetPet(NewSummon);
4161    sLog.outDebug("New Pet has guid %u", NewSummon->GetGUIDLow());
4162
4163    if(m_caster->GetTypeId() == TYPEID_PLAYER)
4164    {
4165        NewSummon->SavePetToDB(PET_SAVE_AS_CURRENT);
4166        ((Player*)m_caster)->PetSpellInitialize();
4167    }
4168}
4169
4170void Spell::EffectLearnPetSpell(uint32 i)
4171{
4172    if(m_caster->GetTypeId() != TYPEID_PLAYER)
4173        return;
4174
4175    Player *_player = (Player*)m_caster;
4176
4177    Pet *pet = _player->GetPet();
4178    if(!pet)
4179        return;
4180    if(!pet->isAlive())
4181        return;
4182
4183    SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4184    if(!learn_spellproto)
4185        return;
4186
4187    pet->SetTP(pet->m_TrainingPoints - pet->GetTPForSpell(learn_spellproto->Id));
4188    pet->learnSpell(learn_spellproto->Id);
4189
4190    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
4191    _player->PetSpellInitialize();
4192}
4193
4194void Spell::EffectTaunt(uint32 /*i*/)
4195{
4196    // this effect use before aura Taunt apply for prevent taunt already attacking target
4197    // for spell as marked "non effective at already attacking target"
4198    if(unitTarget && unitTarget->GetTypeId() != TYPEID_PLAYER)
4199    {
4200        if(unitTarget->getVictim()==m_caster)
4201        {
4202            SendCastResult(SPELL_FAILED_DONT_REPORT);
4203            return;
4204        }
4205    }
4206
4207    // Also use this effect to set the taunter's threat to the taunted creature's highest value
4208    if(unitTarget->CanHaveThreatList() && unitTarget->getThreatManager().getCurrentVictim())
4209        unitTarget->getThreatManager().addThreat(m_caster,unitTarget->getThreatManager().getCurrentVictim()->getThreat());
4210}
4211
4212void Spell::EffectWeaponDmg(uint32 i)
4213{
4214    if(!unitTarget)
4215        return;
4216    if(!unitTarget->isAlive())
4217        return;
4218
4219    // multiple weapon dmg effect workaround
4220    // execute only the last weapon damage
4221    // and handle all effects at once
4222    for (int j = 0; j < 3; j++)
4223    {
4224        switch(m_spellInfo->Effect[j])
4225        {
4226            case SPELL_EFFECT_WEAPON_DAMAGE:
4227            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4228            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4229            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4230                if (j < i)                                  // we must calculate only at last weapon effect
4231                    return;
4232            break;
4233        }
4234    }
4235
4236    // some spell specific modifiers
4237    bool customBonusDamagePercentMod = false;
4238    float bonusDamagePercentMod  = 1.0f;                    // applied to fixed effect damage bonus if set customBonusDamagePercentMod
4239    float weaponDamagePercentMod = 1.0f;                    // applied to weapon damage (and to fixed effect damage bonus if customBonusDamagePercentMod not set
4240    float totalDamagePercentMod  = 1.0f;                    // applied to final bonus+weapon damage
4241    bool normalized = false;
4242
4243    int32 spell_bonus = 0;                                  // bonus specific for spell
4244    switch(m_spellInfo->SpellFamilyName)
4245    {
4246        case SPELLFAMILY_WARRIOR:
4247        {
4248            // Whirlwind, single only spell with 2 weapon white damage apply if have
4249            if(m_caster->GetTypeId()==TYPEID_PLAYER && (m_spellInfo->SpellFamilyFlags & 0x00000400000000LL))
4250            {
4251                if(((Player*)m_caster)->GetWeaponForAttack(OFF_ATTACK,true))
4252                    spell_bonus += m_caster->CalculateDamage (OFF_ATTACK, normalized);
4253            }
4254            // Devastate bonus and sunder armor refresh
4255            else if(m_spellInfo->SpellVisual == 671 && m_spellInfo->SpellIconID == 1508)
4256            {
4257                customBonusDamagePercentMod = true;
4258                bonusDamagePercentMod = 0.0f;               // only applied if auras found
4259
4260                Unit::AuraList const& list = unitTarget->GetAurasByType(SPELL_AURA_MOD_RESISTANCE);
4261                for(Unit::AuraList::const_iterator itr=list.begin();itr!=list.end();++itr)
4262                {
4263                    SpellEntry const *proto = (*itr)->GetSpellProto();
4264                    if(proto->SpellVisual == 406 && proto->SpellIconID == 565)
4265                    {
4266                        int32 duration = GetSpellDuration(proto);
4267                        (*itr)->SetAuraDuration(duration);
4268                        (*itr)->UpdateAuraDuration();
4269                        bonusDamagePercentMod += 1.0f;      // +100%
4270                    }
4271                }
4272            }
4273            break;
4274        }
4275        case SPELLFAMILY_ROGUE:
4276        {
4277            // Ambush
4278            if(m_spellInfo->SpellFamilyFlags & 0x00000200LL)
4279            {
4280                customBonusDamagePercentMod = true;
4281                bonusDamagePercentMod = 2.5f;               // 250%
4282            }
4283            // Mutilate (for each hand)
4284            else if(m_spellInfo->SpellFamilyFlags & 0x600000000LL)
4285            {
4286                bool found = false;
4287                // fast check
4288                if(unitTarget->HasAuraState(AURA_STATE_DEADLY_POISON))
4289                    found = true;
4290                // full aura scan
4291                else
4292                {
4293                    Unit::AuraMap const& auras = unitTarget->GetAuras();
4294                    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
4295                    {
4296                        if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
4297                        {
4298                            found = true;
4299                            break;
4300                        }
4301                    }
4302                }
4303
4304                if(found)
4305                    totalDamagePercentMod *= 1.5f;          // 150% if poisoned
4306            }
4307            break;
4308        }
4309        case SPELLFAMILY_PALADIN:
4310        {
4311            // Seal of Command - receive benefit from Spell Damage and Healing
4312            if(m_spellInfo->SpellFamilyFlags & 0x00000002000000LL)
4313            {
4314                spell_bonus += int32(0.20f*m_caster->SpellBaseDamageBonus(GetSpellSchoolMask(m_spellInfo)));
4315                spell_bonus += int32(0.29f*m_caster->SpellBaseDamageBonusForVictim(GetSpellSchoolMask(m_spellInfo), unitTarget));
4316            }
4317            break;
4318        }
4319        case SPELLFAMILY_SHAMAN:
4320        {
4321            // Skyshatter Harness item set bonus
4322            // Stormstrike
4323            if(m_spellInfo->SpellFamilyFlags & 0x001000000000LL)
4324            {
4325                Unit::AuraList const& m_OverrideClassScript = m_caster->GetAurasByType(SPELL_AURA_OVERRIDE_CLASS_SCRIPTS);
4326                for(Unit::AuraList::const_iterator i = m_OverrideClassScript.begin(); i != m_OverrideClassScript.end(); ++i)
4327                {
4328                    // Stormstrike AP Buff
4329                    if ( (*i)->GetModifier()->m_miscvalue == 5634 )
4330                    {
4331                        m_caster->CastSpell(m_caster,38430,true,NULL,*i);
4332                        break;
4333                    }
4334                }
4335            }
4336        }
4337    }
4338
4339    int32 fixed_bonus = 0;
4340    for (int j = 0; j < 3; j++)
4341    {
4342        switch(m_spellInfo->Effect[j])
4343        {
4344            case SPELL_EFFECT_WEAPON_DAMAGE:
4345            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4346                fixed_bonus += CalculateDamage(j,unitTarget);
4347                break;
4348            case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
4349                fixed_bonus += CalculateDamage(j,unitTarget);
4350                normalized = true;
4351                break;
4352            case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
4353                weaponDamagePercentMod *= float(CalculateDamage(j,unitTarget)) / 100.0f;
4354
4355                // applied only to prev.effects fixed damage
4356                if(customBonusDamagePercentMod)
4357                    fixed_bonus = int32(fixed_bonus*bonusDamagePercentMod);
4358                else
4359                    fixed_bonus = int32(fixed_bonus*weaponDamagePercentMod);
4360                break;
4361            default:
4362                break;                                      // not weapon damage effect, just skip
4363        }
4364    }
4365
4366    // non-weapon damage
4367    int32 bonus = spell_bonus + fixed_bonus;
4368
4369    // apply to non-weapon bonus weapon total pct effect, weapon total flat effect included in weapon damage
4370    if(bonus)
4371    {
4372        UnitMods unitMod;
4373        switch(m_attackType)
4374        {
4375            default:
4376            case BASE_ATTACK:   unitMod = UNIT_MOD_DAMAGE_MAINHAND; break;
4377            case OFF_ATTACK:    unitMod = UNIT_MOD_DAMAGE_OFFHAND;  break;
4378            case RANGED_ATTACK: unitMod = UNIT_MOD_DAMAGE_RANGED;   break;
4379        }
4380
4381        float weapon_total_pct  = m_caster->GetModifierValue(unitMod, TOTAL_PCT);
4382        bonus = int32(bonus*weapon_total_pct);
4383    }
4384
4385    // + weapon damage with applied weapon% dmg to base weapon damage in call
4386    bonus += int32(m_caster->CalculateDamage(m_attackType, normalized)*weaponDamagePercentMod);
4387
4388    // total damage
4389    bonus = int32(bonus*totalDamagePercentMod);
4390
4391    // prevent negative damage
4392    uint32 eff_damage = uint32(bonus > 0 ? bonus : 0);
4393
4394    const uint32 nohitMask = HITINFO_ABSORB | HITINFO_RESIST | HITINFO_MISS;
4395
4396    uint32 hitInfo = 0;
4397    VictimState victimState = VICTIMSTATE_NORMAL;
4398    uint32 blocked_dmg = 0;
4399    uint32 absorbed_dmg = 0;
4400    uint32 resisted_dmg = 0;
4401    CleanDamage cleanDamage =  CleanDamage(0, BASE_ATTACK, MELEE_HIT_NORMAL );
4402
4403    m_caster->DoAttackDamage(unitTarget, &eff_damage, &cleanDamage, &blocked_dmg, m_spellSchoolMask, &hitInfo, &victimState, &absorbed_dmg, &resisted_dmg, m_attackType, m_spellInfo, m_IsTriggeredSpell);
4404
4405    if ((hitInfo & nohitMask) && m_attackType != RANGED_ATTACK)  // not send ranged miss/etc
4406        m_caster->SendAttackStateUpdate(hitInfo & nohitMask, unitTarget, 1, m_spellSchoolMask, eff_damage, absorbed_dmg, resisted_dmg, VICTIMSTATE_NORMAL, blocked_dmg);
4407
4408    bool criticalhit = (hitInfo & HITINFO_CRITICALHIT);
4409    m_caster->SendSpellNonMeleeDamageLog(unitTarget, m_spellInfo->Id, eff_damage, m_spellSchoolMask, absorbed_dmg, resisted_dmg, false, blocked_dmg, criticalhit);
4410
4411    if (eff_damage > (absorbed_dmg + resisted_dmg + blocked_dmg))
4412    {
4413        eff_damage -= (absorbed_dmg + resisted_dmg + blocked_dmg);
4414    }
4415    else
4416    {
4417        cleanDamage.damage += eff_damage;
4418        eff_damage = 0;
4419    }
4420
4421    // SPELL_SCHOOL_NORMAL use for weapon-like threat and rage calculation
4422    m_caster->DealDamage(unitTarget, eff_damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, true);
4423
4424    // Hemorrhage
4425    if(m_spellInfo->SpellFamilyName==SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & 0x2000000))
4426    {
4427        if(m_caster->GetTypeId()==TYPEID_PLAYER)
4428            ((Player*)m_caster)->AddComboPoints(unitTarget, 1);
4429    }
4430    // Mangle (Cat): CP
4431    if(m_spellInfo->SpellFamilyName==SPELLFAMILY_DRUID && (m_spellInfo->SpellFamilyFlags==0x0000040000000000LL))
4432    {
4433        if(m_caster->GetTypeId()==TYPEID_PLAYER)
4434            ((Player*)m_caster)->AddComboPoints(unitTarget,1);
4435    }
4436
4437
4438    // take ammo
4439    if(m_attackType == RANGED_ATTACK && m_caster->GetTypeId() == TYPEID_PLAYER)
4440    {
4441        Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
4442
4443        // wands don't have ammo
4444        if(!pItem  || pItem->IsBroken() || pItem->GetProto()->SubClass==ITEM_SUBCLASS_WEAPON_WAND)
4445            return;
4446
4447        if( pItem->GetProto()->InventoryType == INVTYPE_THROWN )
4448        {
4449            if(pItem->GetMaxStackCount()==1)
4450            {
4451                // decrease durability for non-stackable throw weapon
4452                ((Player*)m_caster)->DurabilityPointLossForEquipSlot(EQUIPMENT_SLOT_RANGED);
4453            }
4454            else
4455            {
4456                // decrease items amount for stackable throw weapon
4457                uint32 count = 1;
4458                ((Player*)m_caster)->DestroyItemCount( pItem, count, true);
4459            }
4460        }
4461        else if(uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID))
4462            ((Player*)m_caster)->DestroyItemCount(ammo, 1, true);
4463    }
4464}
4465
4466void Spell::EffectThreat(uint32 /*i*/)
4467{
4468    if(!unitTarget || !unitTarget->isAlive() || !m_caster->isAlive())
4469        return;
4470
4471    if(!unitTarget->CanHaveThreatList())
4472        return;
4473
4474    unitTarget->AddThreat(m_caster, float(damage));
4475}
4476
4477void Spell::EffectHealMaxHealth(uint32 /*i*/)
4478{
4479    if(!unitTarget)
4480        return;
4481    if(!unitTarget->isAlive())
4482        return;
4483
4484    uint32 heal = m_caster->GetMaxHealth();
4485
4486    int32 gain = unitTarget->ModifyHealth(heal);
4487    unitTarget->getHostilRefManager().threatAssist(m_caster, float(gain) * 0.5f, m_spellInfo);
4488
4489    m_caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, heal);
4490}
4491
4492void Spell::EffectInterruptCast(uint32 /*i*/)
4493{
4494    if(!unitTarget)
4495        return;
4496    if(!unitTarget->isAlive())
4497        return;
4498
4499    // TODO: not all spells that used this effect apply cooldown at school spells
4500    // also exist case: apply cooldown to interrupted cast only and to all spells
4501    for (uint32 i = CURRENT_FIRST_NON_MELEE_SPELL; i < CURRENT_MAX_SPELL; i++)
4502    {
4503        if (unitTarget->m_currentSpells[i])
4504        {
4505            // check if we can interrupt spell
4506            if ( unitTarget->m_currentSpells[i]->m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT && unitTarget->m_currentSpells[i]->m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE )
4507            {
4508                unitTarget->ProhibitSpellScholl(GetSpellSchoolMask(unitTarget->m_currentSpells[i]->m_spellInfo), GetSpellDuration(m_spellInfo));
4509                unitTarget->InterruptSpell(i,false);
4510            }
4511        }
4512    }
4513}
4514
4515void Spell::EffectSummonObjectWild(uint32 i)
4516{
4517    uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
4518
4519    GameObject* pGameObj = new GameObject;
4520
4521    WorldObject* target = focusObject;
4522    if( !target )
4523        target = m_caster;
4524
4525    float x,y,z;
4526    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
4527    {
4528        x = m_targets.m_destX;
4529        y = m_targets.m_destY;
4530        z = m_targets.m_destZ;
4531    }
4532    else
4533        m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
4534
4535    Map *map = target->GetMap();
4536
4537    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
4538        x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4539    {
4540        delete pGameObj;
4541        return;
4542    }
4543
4544    int32 duration = GetSpellDuration(m_spellInfo);
4545    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4546    pGameObj->SetSpellId(m_spellInfo->Id);
4547
4548    if(pGameObj->GetGoType() != GAMEOBJECT_TYPE_FLAGDROP)   // make dropped flag clickable for other players (not set owner guid (created by) for this)...
4549        m_caster->AddGameObject(pGameObj);
4550    map->Add(pGameObj);
4551
4552    if(pGameObj->GetMapId() == 489 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)  //WS
4553    {
4554        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4555        {
4556            Player *pl = (Player*)m_caster;
4557            BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4558            if(bg && bg->GetTypeID()==BATTLEGROUND_WS && bg->GetStatus() == STATUS_IN_PROGRESS)
4559            {
4560                 uint32 team = ALLIANCE;
4561
4562                 if(pl->GetTeam() == team)
4563                     team = HORDE;
4564
4565                ((BattleGroundWS*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID(),team);
4566            }
4567        }
4568    }
4569
4570    if(pGameObj->GetMapId() == 566 && pGameObj->GetGoType() == GAMEOBJECT_TYPE_FLAGDROP)  //EY
4571    {
4572        if(m_caster->GetTypeId() == TYPEID_PLAYER)
4573        {
4574            BattleGround* bg = ((Player *)m_caster)->GetBattleGround();
4575            if(bg && bg->GetTypeID()==BATTLEGROUND_EY && bg->GetStatus() == STATUS_IN_PROGRESS)
4576            {
4577                ((BattleGroundEY*)bg)->SetDroppedFlagGUID(pGameObj->GetGUID());
4578            }
4579        }
4580    }
4581
4582    if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
4583    {
4584        GameObject* linkedGO = new GameObject;
4585        if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, map,
4586            x, y, z, target->GetOrientation(), 0, 0, 0, 0, 100, 1))
4587        {
4588            linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
4589            linkedGO->SetSpellId(m_spellInfo->Id);
4590
4591            m_caster->AddGameObject(linkedGO);
4592            map->Add(linkedGO);
4593        }
4594        else
4595        {
4596            delete linkedGO;
4597            linkedGO = NULL;
4598            return;
4599        }
4600    }
4601}
4602
4603void Spell::EffectScriptEffect(uint32 effIndex)
4604{
4605    // TODO: we must implement hunter pet summon at login there (spell 6962)
4606
4607    // by spell id
4608    switch(m_spellInfo->Id)
4609    {
4610        // Bending Shinbone
4611        case 8856:
4612        {
4613            if(!itemTarget && m_caster->GetTypeId()!=TYPEID_PLAYER)
4614                return;
4615
4616            uint32 spell_id = 0;
4617            switch(urand(1,5))
4618            {
4619                case 1:  spell_id = 8854; break;
4620                default: spell_id = 8855; break;
4621            }
4622
4623            m_caster->CastSpell(m_caster,spell_id,true,NULL);
4624            return;
4625        }
4626
4627        // Healthstone creating spells
4628        case  6201:
4629        case  6202:
4630        case  5699:
4631        case 11729:
4632        case 11730:
4633        case 27230:
4634        {
4635            uint32 itemtype;
4636            uint32 rank = 0;
4637            Unit::AuraList const& mDummyAuras = unitTarget->GetAurasByType(SPELL_AURA_DUMMY);
4638            for(Unit::AuraList::const_iterator i = mDummyAuras.begin();i != mDummyAuras.end(); ++i)
4639            {
4640                if((*i)->GetId() == 18692)
4641                {
4642                    rank = 1;
4643                    break;
4644                }
4645                else if((*i)->GetId() == 18693)
4646                {
4647                    rank = 2;
4648                    break;
4649                }
4650            }
4651
4652            static uint32 const itypes[6][3] = {
4653                { 5512,19004,19005},                        // Minor Healthstone
4654                { 5511,19006,19007},                        // Lesser Healthstone
4655                { 5509,19008,19009},                        // Healthstone
4656                { 5510,19010,19011},                        // Greater Healthstone
4657                { 9421,19012,19013},                        // Major Healthstone
4658                {22103,22104,22105}                         // Master Healthstone
4659            };
4660
4661            switch(m_spellInfo->Id)
4662            {
4663                case  6201: itemtype=itypes[0][rank];break; // Minor Healthstone
4664                case  6202: itemtype=itypes[1][rank];break; // Lesser Healthstone
4665                case  5699: itemtype=itypes[2][rank];break; // Healthstone
4666                case 11729: itemtype=itypes[3][rank];break; // Greater Healthstone
4667                case 11730: itemtype=itypes[4][rank];break; // Major Healthstone
4668                case 27230: itemtype=itypes[5][rank];break; // Master Healthstone
4669                default:
4670                    return;
4671            }
4672            DoCreateItem( effIndex, itemtype );
4673            return;
4674        }
4675        // Brittle Armor - need remove one 24575 Brittle Armor aura
4676        case 24590:
4677            unitTarget->RemoveSingleAuraFromStack(24575, 0);
4678            unitTarget->RemoveSingleAuraFromStack(24575, 1);
4679            return;
4680        // Mercurial Shield - need remove one 26464 Mercurial Shield aura
4681        case 26465:
4682            unitTarget->RemoveSingleAuraFromStack(26464, 0);
4683            return;
4684        // Orb teleport spells
4685        case 25140:
4686        case 25143:
4687        case 25650:
4688        case 25652:
4689        case 29128:
4690        case 29129:
4691        case 35376:
4692        case 35727:
4693        {
4694            if(!unitTarget)
4695                return;
4696
4697            uint32 spellid;
4698            switch(m_spellInfo->Id)
4699            {
4700                case 25140: spellid =  32571; break;
4701                case 25143: spellid =  32572; break;
4702                case 25650: spellid =  30140; break;
4703                case 25652: spellid =  30141; break;
4704                case 29128: spellid =  32568; break;
4705                case 29129: spellid =  32569; break;
4706                case 35376: spellid =  25649; break;
4707                case 35727: spellid =  35730; break;
4708                default:
4709                    return;
4710            }
4711
4712            unitTarget->CastSpell(unitTarget,spellid,false);
4713            return;
4714        }
4715
4716        // Shadow Flame (All script effects, not just end ones to prevent player from dodging the last triggered spell)
4717        case 22539:
4718        case 22972:
4719        case 22975:
4720        case 22976:
4721        case 22977:
4722        case 22978:
4723        case 22979:
4724        case 22980:
4725        case 22981:
4726        case 22982:
4727        case 22983:
4728        case 22984:
4729        case 22985:
4730        {
4731            if(!unitTarget || !unitTarget->isAlive())
4732                return;
4733
4734            // Onyxia Scale Cloak
4735            if(unitTarget->GetDummyAura(22683))
4736                return;
4737
4738            // Shadow Flame
4739            m_caster->CastSpell(unitTarget, 22682, true);
4740            return;
4741        }
4742        break;
4743
4744        // Summon Black Qiraji Battle Tank
4745        case 26656:
4746        {
4747            if(!unitTarget)
4748                return;
4749
4750            // Prevent stacking of mounts
4751            unitTarget->RemoveSpellsCausingAura(SPELL_AURA_MOUNTED);
4752
4753            // Two separate mounts depending on area id (allows use both in and out of specific instance)
4754            if (unitTarget->GetAreaId() == 3428)
4755                unitTarget->CastSpell(unitTarget, 25863, false);
4756            else
4757                unitTarget->CastSpell(unitTarget, 26655, false);
4758            break;
4759        }
4760        // Piccolo of the Flaming Fire
4761        case 17512:
4762        {
4763            if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
4764                return;
4765            unitTarget->HandleEmoteCommand(EMOTE_STATE_DANCE);
4766            break;
4767        }
4768
4769        // Netherbloom
4770        case 28702:
4771        {
4772            if(!unitTarget)
4773                return;
4774            // 25% chance of casting a random buff
4775            if(roll_chance_i(75))
4776                return;
4777
4778            // triggered spells are 28703 to 28707
4779            // Note: some sources say, that there was the possibility of
4780            //       receiving a debuff. However, this seems to be removed by a patch.
4781            const uint32 spellid = 28703;
4782
4783            // don't overwrite an existing aura
4784            for(uint8 i=0; i<5; i++)
4785                if(unitTarget->HasAura(spellid+i, 0))
4786                    return;
4787            unitTarget->CastSpell(unitTarget, spellid+urand(0, 4), true);
4788            break;
4789        }
4790
4791        // Nightmare Vine
4792        case 28720:
4793        {
4794            if(!unitTarget)
4795                return;
4796            // 25% chance of casting Nightmare Pollen
4797            if(roll_chance_i(75))
4798                return;
4799            unitTarget->CastSpell(unitTarget, 28721, true);
4800            break;
4801        }
4802
4803        // Mirren's Drinking Hat
4804        case 29830:
4805        {
4806            uint32 item = 0;
4807            switch ( urand(1,6) )
4808            {
4809                case 1: case 2: case 3: item = 23584; break;// Loch Modan Lager
4810                case 4: case 5:         item = 23585; break;// Stouthammer Lite
4811                case 6:                 item = 23586; break;// Aerie Peak Pale Ale
4812            }
4813            if (item)
4814                DoCreateItem(effIndex,item);
4815            break;
4816        }
4817        // Improved Sprint
4818        case 30918:
4819        {
4820            // Removes snares and roots.
4821            uint32 mechanic_mask = (1<<MECHANIC_ROOT) | (1<<MECHANIC_SNARE);
4822            Unit::AuraMap& Auras = unitTarget->GetAuras();
4823            for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
4824            {
4825                next = iter;
4826                ++next;
4827                Aura *aur = iter->second;
4828                if (!aur->IsPositive())             //only remove negative spells
4829                {
4830                    // check for mechanic mask
4831                    if(GetSpellMechanicMask(aur->GetSpellProto(), aur->GetEffIndex()) & mechanic_mask)
4832                    {
4833                        unitTarget->RemoveAurasDueToSpell(aur->GetId());
4834                        if(Auras.empty())
4835                            break;
4836                        else
4837                            next = Auras.begin();
4838                    }
4839                }
4840            }
4841            break;
4842        }
4843
4844        // Goblin Weather Machine
4845        case 46203:
4846        {
4847            if(!unitTarget)
4848                return;
4849
4850            uint32 spellId;
4851            switch(rand()%4)
4852            {
4853                case 0:
4854                    spellId=46740;
4855                    break;
4856                case 1:
4857                    spellId=46739;
4858                    break;
4859                case 2:
4860                    spellId=46738;
4861                    break;
4862                case 3:
4863                    spellId=46736;
4864                    break;
4865            }
4866            unitTarget->CastSpell(unitTarget, spellId, true);
4867            break;
4868        }
4869
4870    }
4871
4872    if(!unitTarget || !unitTarget->isAlive()) // can we remove this check?
4873    {
4874        sLog.outError("Spell %u in EffectScriptEffect does not have unitTarget", m_spellInfo->Id);
4875        return;
4876    }
4877
4878    switch(m_spellInfo->Id)
4879    {
4880        // Dreaming Glory
4881        case 28698: unitTarget->CastSpell(unitTarget, 28694, true); break;
4882        // Needle Spine
4883        case 39835: unitTarget->CastSpell(unitTarget, 39968, true); break;
4884        // Draw Soul
4885        case 40904: unitTarget->CastSpell(m_caster, 40903, true); break;
4886        // Flame Crash
4887        case 41126: unitTarget->CastSpell(unitTarget, 41131, true); break;
4888        case 41931:
4889        {
4890            int bag=19;
4891            int slot=0;
4892            Item* item = NULL;
4893           
4894            while (bag < 256)
4895            {
4896                item = ((Player*)m_caster)->GetItemByPos(bag,slot);
4897                if (item && item->GetEntry() == 38587) break;
4898                slot++;
4899                if (slot == 39)
4900                {
4901                    slot = 0;
4902                    bag++;
4903                }
4904            }
4905            if (bag < 256)
4906            {
4907                if (((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount() == 1) ((Player*)m_caster)->RemoveItem(bag,slot,true);
4908                else ((Player*)m_caster)->GetItemByPos(bag,slot)->SetCount(((Player*)m_caster)->GetItemByPos(bag,slot)->GetCount()-1);
4909                // Spell 42518 (Braufest - Gratisprobe des Braufest herstellen)
4910                m_caster->CastSpell(m_caster,42518,true);
4911                return;
4912            }
4913        }
4914        // Force Cast - Portal Effect: Sunwell Isle
4915        case 44876: unitTarget->CastSpell(unitTarget, 44870, true); break;
4916        //5,000 Gold
4917        case 46642:
4918        {
4919            if(unitTarget->GetTypeId() == TYPEID_PLAYER)
4920                ((Player*)unitTarget)->ModifyMoney(50000000);
4921            break;
4922        }
4923    }
4924
4925    if( m_spellInfo->SpellFamilyName == SPELLFAMILY_PALADIN )
4926    {
4927        switch(m_spellInfo->SpellFamilyFlags)
4928        {
4929            // Judgement
4930            case 0x800000:
4931            {
4932                uint32 spellId2 = 0;
4933
4934                // all seals have aura dummy
4935                Unit::AuraList const& m_dummyAuras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4936                for(Unit::AuraList::const_iterator itr = m_dummyAuras.begin(); itr != m_dummyAuras.end(); ++itr)
4937                {
4938                    SpellEntry const *spellInfo = (*itr)->GetSpellProto();
4939
4940                    // search seal (all seals have judgement's aura dummy spell id in 2 effect
4941                    if ( !spellInfo || !IsSealSpell((*itr)->GetSpellProto()) || (*itr)->GetEffIndex() != 2 )
4942                        continue;
4943
4944                    // must be calculated base at raw base points in spell proto, GetModifier()->m_value for S.Righteousness modified by SPELLMOD_DAMAGE
4945                    spellId2 = (*itr)->GetSpellProto()->EffectBasePoints[2]+1;
4946
4947                    if(spellId2 <= 1)
4948                        continue;
4949
4950                    // found, remove seal
4951                    m_caster->RemoveAurasDueToSpell((*itr)->GetId());
4952
4953                    // Sanctified Judgement
4954                    Unit::AuraList const& m_auras = m_caster->GetAurasByType(SPELL_AURA_DUMMY);
4955                    for(Unit::AuraList::const_iterator i = m_auras.begin(); i != m_auras.end(); ++i)
4956                    {
4957                        if ((*i)->GetSpellProto()->SpellIconID == 205 && (*i)->GetSpellProto()->Attributes == 0x01D0LL)
4958                        {
4959                            int32 chance = (*i)->GetModifier()->m_amount;
4960                            if ( roll_chance_i(chance) )
4961                            {
4962                                int32 mana = spellInfo->manaCost;
4963                                if ( Player* modOwner = m_caster->GetSpellModOwner() )
4964                                    modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COST, mana);
4965                                mana = int32(mana* 0.8f);
4966                                m_caster->CastCustomSpell(m_caster,31930,&mana,NULL,NULL,true,NULL,*i);
4967                            }
4968                            break;
4969                        }
4970                    }
4971
4972                    break;
4973                }
4974
4975                m_caster->CastSpell(unitTarget,spellId2,true);
4976                return;
4977            }
4978        }
4979    }
4980
4981    // normal DB scripted effect
4982    sLog.outDebug("Spell ScriptStart spellid %u in EffectScriptEffect ", m_spellInfo->Id);
4983    sWorld.ScriptsStart(sSpellScripts, m_spellInfo->Id, m_caster, unitTarget);
4984}
4985
4986void Spell::EffectSanctuary(uint32 /*i*/)
4987{
4988    if(!unitTarget)
4989        return;
4990    //unitTarget->CombatStop();
4991
4992    unitTarget->CombatStop();
4993    unitTarget->getHostilRefManager().deleteReferences();   // stop all fighting
4994    // Vanish allows to remove all threat and cast regular stealth so other spells can be used
4995    if(m_spellInfo->SpellFamilyName == SPELLFAMILY_ROGUE && (m_spellInfo->SpellFamilyFlags & SPELLFAMILYFLAG_ROGUE_VANISH))
4996    {
4997        ((Player *)m_caster)->RemoveSpellsCausingAura(SPELL_AURA_MOD_ROOT);
4998    }
4999}
5000
5001void Spell::EffectAddComboPoints(uint32 /*i*/)
5002{
5003    if(!unitTarget)
5004        return;
5005
5006    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5007        return;
5008
5009    if(damage <= 0)
5010        return;
5011
5012    ((Player*)m_caster)->AddComboPoints(unitTarget, damage);
5013}
5014
5015void Spell::EffectDuel(uint32 i)
5016{
5017    if(!m_caster || !unitTarget || m_caster->GetTypeId() != TYPEID_PLAYER || unitTarget->GetTypeId() != TYPEID_PLAYER)
5018        return;
5019
5020    Player *caster = (Player*)m_caster;
5021    Player *target = (Player*)unitTarget;
5022
5023    // caster or target already have requested duel
5024    if( caster->duel || target->duel || !target->GetSocial() || target->GetSocial()->HasIgnore(caster->GetGUIDLow()) )
5025        return;
5026
5027    // Players can only fight a duel with each other outside (=not inside dungeons and not in capital cities)
5028    // Don't have to check the target's map since you cannot challenge someone across maps
5029    if( caster->GetMapId() != 0 && caster->GetMapId() != 1 && caster->GetMapId() != 530)
5030    {
5031        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
5032        return;
5033    }
5034
5035    AreaTableEntry const* casterAreaEntry = GetAreaEntryByAreaID(caster->GetZoneId());
5036    if(casterAreaEntry && (casterAreaEntry->flags & AREA_FLAG_CAPITAL) )
5037    {
5038        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
5039        return;
5040    }
5041
5042    AreaTableEntry const* targetAreaEntry = GetAreaEntryByAreaID(target->GetZoneId());
5043    if(targetAreaEntry && (targetAreaEntry->flags & AREA_FLAG_CAPITAL) )
5044    {
5045        SendCastResult(SPELL_FAILED_NO_DUELING);            // Dueling isn't allowed here
5046        return;
5047    }
5048
5049    //CREATE DUEL FLAG OBJECT
5050    GameObject* pGameObj = new GameObject;
5051
5052    uint32 gameobject_id = m_spellInfo->EffectMiscValue[i];
5053
5054    Map *map = m_caster->GetMap();
5055    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), gameobject_id, map,
5056        m_caster->GetPositionX()+(unitTarget->GetPositionX()-m_caster->GetPositionX())/2 ,
5057        m_caster->GetPositionY()+(unitTarget->GetPositionY()-m_caster->GetPositionY())/2 ,
5058        m_caster->GetPositionZ(),
5059        m_caster->GetOrientation(), 0, 0, 0, 0, 0, 1))
5060    {
5061        delete pGameObj;
5062        return;
5063    }
5064
5065    pGameObj->SetUInt32Value(GAMEOBJECT_FACTION, m_caster->getFaction() );
5066    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel()+1 );
5067    int32 duration = GetSpellDuration(m_spellInfo);
5068    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5069    pGameObj->SetSpellId(m_spellInfo->Id);
5070
5071    m_caster->AddGameObject(pGameObj);
5072    map->Add(pGameObj);
5073    //END
5074
5075    // Send request
5076    WorldPacket data(SMSG_DUEL_REQUESTED, 16);
5077    data << pGameObj->GetGUID();
5078    data << caster->GetGUID();
5079    caster->GetSession()->SendPacket(&data);
5080    target->GetSession()->SendPacket(&data);
5081
5082    // create duel-info
5083    DuelInfo *duel   = new DuelInfo;
5084    duel->initiator  = caster;
5085    duel->opponent   = target;
5086    duel->startTime  = 0;
5087    duel->startTimer = 0;
5088    caster->duel     = duel;
5089
5090    DuelInfo *duel2   = new DuelInfo;
5091    duel2->initiator  = caster;
5092    duel2->opponent   = caster;
5093    duel2->startTime  = 0;
5094    duel2->startTimer = 0;
5095    target->duel      = duel2;
5096
5097    caster->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5098    target->SetUInt64Value(PLAYER_DUEL_ARBITER,pGameObj->GetGUID());
5099}
5100
5101void Spell::EffectStuck(uint32 /*i*/)
5102{
5103    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5104        return;
5105
5106    if(!sWorld.getConfig(CONFIG_CAST_UNSTUCK))
5107        return;
5108
5109    Player* pTarget = (Player*)unitTarget;
5110
5111    sLog.outDebug("Spell Effect: Stuck");
5112    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());
5113
5114    if(pTarget->isInFlight())
5115        return;
5116
5117    // homebind location is loaded always
5118    pTarget->TeleportTo(pTarget->m_homebindMapId,pTarget->m_homebindX,pTarget->m_homebindY,pTarget->m_homebindZ,pTarget->GetOrientation(), (unitTarget==m_caster ? TELE_TO_SPELL : 0));
5119
5120    // Stuck spell trigger Hearthstone cooldown
5121    SpellEntry const *spellInfo = sSpellStore.LookupEntry(8690);
5122    if(!spellInfo)
5123        return;
5124    Spell spell(pTarget,spellInfo,true,0);
5125    spell.SendSpellCooldown();
5126}
5127
5128void Spell::EffectSummonPlayer(uint32 /*i*/)
5129{
5130    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5131        return;
5132
5133    // Evil Twin (ignore player summon, but hide this for summoner)
5134    if(unitTarget->GetDummyAura(23445))
5135        return;
5136
5137    float x,y,z;
5138    m_caster->GetClosePoint(x,y,z,unitTarget->GetObjectSize());
5139
5140    ((Player*)unitTarget)->SetSummonPoint(m_caster->GetMapId(),x,y,z);
5141
5142    WorldPacket data(SMSG_SUMMON_REQUEST, 8+4+4);
5143    data << uint64(m_caster->GetGUID());                    // summoner guid
5144    data << uint32(m_caster->GetZoneId());                  // summoner zone
5145    data << uint32(MAX_PLAYER_SUMMON_DELAY*1000);           // auto decline after msecs
5146    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5147}
5148
5149static ScriptInfo generateActivateCommand()
5150{
5151    ScriptInfo si;
5152    si.command = SCRIPT_COMMAND_ACTIVATE_OBJECT;
5153    return si;
5154}
5155
5156void Spell::EffectActivateObject(uint32 effect_idx)
5157{
5158    if(!gameObjTarget)
5159        return;
5160
5161    static ScriptInfo activateCommand = generateActivateCommand();
5162
5163    int32 delay_secs = m_spellInfo->EffectMiscValue[effect_idx];
5164
5165    sWorld.ScriptCommandStart(activateCommand, delay_secs, m_caster, gameObjTarget);
5166}
5167
5168void Spell::EffectSummonTotem(uint32 i)
5169{
5170    uint8 slot = 0;
5171    switch(m_spellInfo->EffectMiscValueB[i])
5172    {
5173        case SUMMON_TYPE_TOTEM_SLOT1: slot = 0; break;
5174        case SUMMON_TYPE_TOTEM_SLOT2: slot = 1; break;
5175        case SUMMON_TYPE_TOTEM_SLOT3: slot = 2; break;
5176        case SUMMON_TYPE_TOTEM_SLOT4: slot = 3; break;
5177        // Battle standard case
5178        case SUMMON_TYPE_TOTEM:       slot = 254; break;
5179        // jewelery statue case, like totem without slot
5180        case SUMMON_TYPE_GUARDIAN:    slot = 255; break;
5181        default: return;
5182    }
5183
5184    if(slot < MAX_TOTEM)
5185    {
5186        uint64 guid = m_caster->m_TotemSlot[slot];
5187        if(guid != 0)
5188        {
5189            Creature *OldTotem = ObjectAccessor::GetCreature(*m_caster, guid);
5190            if(OldTotem && OldTotem->isTotem())
5191                ((Totem*)OldTotem)->UnSummon();
5192        }
5193    }
5194
5195    uint32 team = 0;
5196    if (m_caster->GetTypeId()==TYPEID_PLAYER)
5197        team = ((Player*)m_caster)->GetTeam();
5198
5199    Totem* pTotem = new Totem;
5200
5201    if(!pTotem->Create(objmgr.GenerateLowGuid(HIGHGUID_UNIT), m_caster->GetMap(), m_spellInfo->EffectMiscValue[i], team ))
5202    {
5203        delete pTotem;
5204        return;
5205    }
5206
5207    float angle = slot < MAX_TOTEM ? M_PI/MAX_TOTEM - (slot*2*M_PI/MAX_TOTEM) : 0;
5208
5209    float x,y,z;
5210    m_caster->GetClosePoint(x,y,z,pTotem->GetObjectSize(),2.0f,angle);
5211
5212    // totem must be at same Z in case swimming caster and etc.
5213    if( fabs( z - m_caster->GetPositionZ() ) > 5 )
5214        z = m_caster->GetPositionZ();
5215
5216    pTotem->Relocate(x, y, z, m_caster->GetOrientation());
5217
5218    if(slot < MAX_TOTEM)
5219        m_caster->m_TotemSlot[slot] = pTotem->GetGUID();
5220
5221    pTotem->SetOwner(m_caster->GetGUID());
5222    pTotem->SetTypeBySummonSpell(m_spellInfo);              // must be after Create call where m_spells initilized
5223
5224    int32 duration=GetSpellDuration(m_spellInfo);
5225    if(Player* modOwner = m_caster->GetSpellModOwner())
5226        modOwner->ApplySpellMod(m_spellInfo->Id,SPELLMOD_DURATION, duration);
5227    pTotem->SetDuration(duration);
5228
5229    if (damage)                                             // if not spell info, DB values used
5230    {
5231        pTotem->SetMaxHealth(damage);
5232        pTotem->SetHealth(damage);
5233    }
5234
5235    pTotem->SetUInt32Value(UNIT_CREATED_BY_SPELL,m_spellInfo->Id);
5236    pTotem->SetFlag(UNIT_FIELD_FLAGS,UNIT_FLAG_PVP_ATTACKABLE);
5237
5238    pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_MOD_FEAR,true);
5239    pTotem->ApplySpellImmune(m_spellInfo->Id,IMMUNITY_STATE,SPELL_AURA_TRANSFORM,true);
5240
5241    pTotem->Summon(m_caster);
5242
5243    if(slot < MAX_TOTEM && m_caster->GetTypeId() == TYPEID_PLAYER)
5244    {
5245        WorldPacket data(SMSG_TOTEM_CREATED, 1+8+4+4);
5246        data << uint8(slot);
5247        data << uint64(pTotem->GetGUID());
5248        data << uint32(duration);
5249        data << uint32(m_spellInfo->Id);
5250        ((Player*)m_caster)->SendDirectMessage(&data);
5251    }
5252}
5253
5254void Spell::EffectEnchantHeldItem(uint32 i)
5255{
5256    // this is only item spell effect applied to main-hand weapon of target player (players in area)
5257    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5258        return;
5259
5260    Player* item_owner = (Player*)unitTarget;
5261    Item* item = item_owner->GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
5262
5263    if(!item )
5264        return;
5265
5266    // must be equipped
5267    if(!item ->IsEquipped())
5268        return;
5269
5270    if (m_spellInfo->EffectMiscValue[i])
5271    {
5272        uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
5273        int32 duration = GetSpellDuration(m_spellInfo);          //Try duration index first ..
5274        if(!duration)
5275            duration = m_currentBasePoints[i]+1;            //Base points after ..
5276        if(!duration)
5277            duration = 10;                                  //10 seconds for enchants which don't have listed duration
5278
5279        SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
5280        if(!pEnchant)
5281            return;
5282
5283        // Always go to temp enchantment slot
5284        EnchantmentSlot slot = TEMP_ENCHANTMENT_SLOT;
5285
5286        // Enchantment will not be applied if a different one already exists
5287        if(item->GetEnchantmentId(slot) && item->GetEnchantmentId(slot) != enchant_id)
5288            return;
5289
5290        // Apply the temporary enchantment
5291        item->SetEnchantment(slot, enchant_id, duration*1000, 0);
5292        item_owner->ApplyEnchantment(item,slot,true);
5293    }
5294}
5295
5296void Spell::EffectDisEnchant(uint32 /*i*/)
5297{
5298    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5299        return;
5300
5301    Player* p_caster = (Player*)m_caster;
5302    if(!itemTarget || !itemTarget->GetProto()->DisenchantID)
5303        return;
5304
5305    p_caster->UpdateCraftSkill(m_spellInfo->Id);
5306
5307    ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(),LOOT_DISENCHANTING);
5308
5309    // item will be removed at disenchanting end
5310}
5311
5312void Spell::EffectInebriate(uint32 /*i*/)
5313{
5314    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5315        return;
5316
5317    Player *player = (Player*)unitTarget;
5318    uint16 currentDrunk = player->GetDrunkValue();
5319    uint16 drunkMod = damage * 256;
5320    if (currentDrunk + drunkMod > 0xFFFF)
5321        currentDrunk = 0xFFFF;
5322    else
5323        currentDrunk += drunkMod;
5324    player->SetDrunkValue(currentDrunk, m_CastItem?m_CastItem->GetEntry():0);
5325}
5326
5327void Spell::EffectFeedPet(uint32 i)
5328{
5329    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5330        return;
5331
5332    Player *_player = (Player*)m_caster;
5333
5334    if(!itemTarget)
5335        return;
5336
5337    Pet *pet = _player->GetPet();
5338    if(!pet)
5339        return;
5340
5341    if(!pet->isAlive())
5342        return;
5343
5344    int32 benefit = pet->GetCurrentFoodBenefitLevel(itemTarget->GetProto()->ItemLevel);
5345    if(benefit <= 0)
5346        return;
5347
5348    uint32 count = 1;
5349    _player->DestroyItemCount(itemTarget,count,true);
5350    // TODO: fix crash when a spell has two effects, both pointed at the same item target
5351
5352    m_caster->CastCustomSpell(m_caster,m_spellInfo->EffectTriggerSpell[i],&benefit,NULL,NULL,true);
5353}
5354
5355void Spell::EffectDismissPet(uint32 /*i*/)
5356{
5357    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5358        return;
5359
5360    Pet* pet = m_caster->GetPet();
5361
5362    // not let dismiss dead pet
5363    if(!pet||!pet->isAlive())
5364        return;
5365
5366    ((Player*)m_caster)->RemovePet(pet,PET_SAVE_NOT_IN_SLOT);
5367}
5368
5369void Spell::EffectSummonObject(uint32 i)
5370{
5371    uint32 go_id = m_spellInfo->EffectMiscValue[i];
5372
5373    uint8 slot = 0;
5374    switch(m_spellInfo->Effect[i])
5375    {
5376        case SPELL_EFFECT_SUMMON_OBJECT_SLOT1: slot = 0; break;
5377        case SPELL_EFFECT_SUMMON_OBJECT_SLOT2: slot = 1; break;
5378        case SPELL_EFFECT_SUMMON_OBJECT_SLOT3: slot = 2; break;
5379        case SPELL_EFFECT_SUMMON_OBJECT_SLOT4: slot = 3; break;
5380        default: return;
5381    }
5382
5383    uint64 guid = m_caster->m_ObjectSlot[slot];
5384    if(guid != 0)
5385    {
5386        GameObject* obj = NULL;
5387        if( m_caster )
5388            obj = ObjectAccessor::GetGameObject(*m_caster, guid);
5389
5390        if(obj) obj->Delete();
5391        m_caster->m_ObjectSlot[slot] = 0;
5392    }
5393
5394    GameObject* pGameObj = new GameObject;
5395
5396    float rot2 = sin(m_caster->GetOrientation()/2);
5397    float rot3 = cos(m_caster->GetOrientation()/2);
5398
5399    float x,y,z;
5400    // If dest location if present
5401    if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5402    {
5403        x = m_targets.m_destX;
5404        y = m_targets.m_destY;
5405        z = m_targets.m_destZ;
5406    }
5407    // Summon in random point all other units if location present
5408    else
5409        m_caster->GetClosePoint(x,y,z,DEFAULT_WORLD_OBJECT_SIZE);
5410
5411    Map *map = m_caster->GetMap();
5412    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), go_id, map, x, y, z, m_caster->GetOrientation(), 0, 0, rot2, rot3, 0, 1))
5413    {
5414        delete pGameObj;
5415        return;
5416    }
5417
5418    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL,m_caster->getLevel());
5419    int32 duration = GetSpellDuration(m_spellInfo);
5420    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
5421    pGameObj->SetSpellId(m_spellInfo->Id);
5422    m_caster->AddGameObject(pGameObj);
5423
5424    map->Add(pGameObj);
5425    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
5426    data << pGameObj->GetGUID();
5427    m_caster->SendMessageToSet(&data,true);
5428
5429    m_caster->m_ObjectSlot[slot] = pGameObj->GetGUID();
5430}
5431
5432void Spell::EffectResurrect(uint32 i)
5433{
5434    if(!unitTarget)
5435        return;
5436    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5437        return;
5438
5439    if(unitTarget->isAlive())
5440        return;
5441    if(!unitTarget->IsInWorld())
5442        return;
5443
5444    switch (m_spellInfo->Id)
5445    {
5446        // Defibrillate (Goblin Jumper Cables) have 33% chance on success
5447        case 8342:
5448            if (roll_chance_i(67))
5449            {
5450                m_caster->CastSpell(m_caster, 8338, true, m_CastItem);
5451                return;
5452            }
5453            break;
5454        // Defibrillate (Goblin Jumper Cables XL) have 50% chance on success
5455        case 22999:
5456            if (roll_chance_i(50))
5457            {
5458                m_caster->CastSpell(m_caster, 23055, true, m_CastItem);
5459                return;
5460            }
5461            break;
5462        default:
5463            break;
5464    }
5465
5466    Player* pTarget = ((Player*)unitTarget);
5467
5468    if(pTarget->isRessurectRequested())       // already have one active request
5469        return;
5470
5471    uint32 health = pTarget->GetMaxHealth() * damage / 100;
5472    uint32 mana   = pTarget->GetMaxPower(POWER_MANA) * damage / 100;
5473
5474    pTarget->setResurrectRequestData(m_caster->GetGUID(), m_caster->GetMapId(), m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ(), health, mana);
5475    SendResurrectRequest(pTarget);
5476}
5477
5478void Spell::EffectAddExtraAttacks(uint32 /*i*/)
5479{
5480    if(!unitTarget || !unitTarget->isAlive())
5481        return;
5482
5483    if( unitTarget->m_extraAttacks )
5484        return;
5485
5486    unitTarget->m_extraAttacks = damage;
5487}
5488
5489void Spell::EffectParry(uint32 /*i*/)
5490{
5491    if (unitTarget->GetTypeId() == TYPEID_PLAYER)
5492    {
5493        ((Player*)unitTarget)->SetCanParry(true);
5494    }
5495}
5496
5497void Spell::EffectBlock(uint32 /*i*/)
5498{
5499    if (unitTarget->GetTypeId() != TYPEID_PLAYER)
5500        return;
5501
5502    ((Player*)unitTarget)->SetCanBlock(true);
5503}
5504
5505void Spell::EffectMomentMove(uint32 i)
5506{
5507    if(unitTarget->isInFlight())
5508        return;
5509
5510    if( m_spellInfo->rangeIndex== 1)                        //self range
5511    {
5512        uint32 mapid = m_caster->GetMapId();
5513        float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
5514
5515        // before caster
5516        float fx,fy,fz;
5517        unitTarget->GetClosePoint(fx,fy,fz,unitTarget->GetObjectSize(),dis);
5518        float ox,oy,oz;
5519        unitTarget->GetPosition(ox,oy,oz);
5520
5521        float fx2,fy2,fz2;                                  // getObjectHitPos overwrite last args in any result case
5522        if(VMAP::VMapFactory::createOrGetVMapManager()->getObjectHitPos(mapid, ox,oy,oz+0.5, fx,fy,oz+0.5,fx2,fy2,fz2, -0.5))
5523        {
5524            fx = fx2;
5525            fy = fy2;
5526            fz = fz2;
5527            unitTarget->UpdateGroundPositionZ(fx,fy,fz);
5528        }
5529
5530        if(unitTarget->GetTypeId() == TYPEID_PLAYER)
5531            ((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));
5532        else
5533            MapManager::Instance().GetMap(mapid, unitTarget)->CreatureRelocation((Creature*)unitTarget, fx, fy, fz, unitTarget->GetOrientation());
5534    }
5535}
5536
5537void Spell::EffectReputation(uint32 i)
5538{
5539    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5540        return;
5541
5542    Player *_player = (Player*)unitTarget;
5543
5544    int32  rep_change = m_currentBasePoints[i]+1;           // field store reputation change -1
5545
5546    uint32 faction_id = m_spellInfo->EffectMiscValue[i];
5547
5548    FactionEntry const* factionEntry = sFactionStore.LookupEntry(faction_id);
5549
5550    if(!factionEntry)
5551        return;
5552
5553    _player->ModifyFactionReputation(factionEntry,rep_change);
5554}
5555
5556void Spell::EffectQuestComplete(uint32 i)
5557{
5558    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5559        return;
5560
5561    Player *_player = (Player*)m_caster;
5562
5563    uint32 quest_id = m_spellInfo->EffectMiscValue[i];
5564    _player->AreaExploredOrEventHappens(quest_id);
5565}
5566
5567void Spell::EffectSelfResurrect(uint32 i)
5568{
5569    if(!unitTarget || unitTarget->isAlive())
5570        return;
5571    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5572        return;
5573    if(!unitTarget->IsInWorld())
5574        return;
5575
5576    uint32 health = 0;
5577    uint32 mana = 0;
5578
5579    // flat case
5580    if(damage < 0)
5581    {
5582        health = uint32(-damage);
5583        mana = m_spellInfo->EffectMiscValue[i];
5584    }
5585    // percent case
5586    else
5587    {
5588        health = uint32(damage/100.0f*unitTarget->GetMaxHealth());
5589        if(unitTarget->GetMaxPower(POWER_MANA) > 0)
5590            mana = uint32(damage/100.0f*unitTarget->GetMaxPower(POWER_MANA));
5591    }
5592
5593    Player *plr = ((Player*)unitTarget);
5594    plr->ResurrectPlayer(0.0f);
5595
5596    plr->SetHealth( health );
5597    plr->SetPower(POWER_MANA, mana );
5598    plr->SetPower(POWER_RAGE, 0 );
5599    plr->SetPower(POWER_ENERGY, plr->GetMaxPower(POWER_ENERGY) );
5600
5601    plr->SpawnCorpseBones();
5602
5603    plr->SaveToDB();
5604}
5605
5606void Spell::EffectSkinning(uint32 /*i*/)
5607{
5608    if(unitTarget->GetTypeId() != TYPEID_UNIT )
5609        return;
5610    if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
5611        return;
5612
5613    Creature* creature = (Creature*) unitTarget;
5614    int32 targetLevel = creature->getLevel();
5615
5616    uint32 skill;
5617    if(creature->GetCreatureInfo()->flag1 & 256)
5618        skill = SKILL_HERBALISM;                            // special case
5619    else if(creature->GetCreatureInfo()->flag1 & 512)
5620        skill = SKILL_MINING;                               // special case
5621    else
5622        skill = SKILL_SKINNING;                             // normal case
5623
5624    ((Player*)m_caster)->SendLoot(creature->GetGUID(),LOOT_SKINNING);
5625    creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5626
5627    int32 reqValue = targetLevel < 10 ? 0 : targetLevel < 20 ? (targetLevel-10)*10 : targetLevel*5;
5628
5629    int32 skillValue = ((Player*)m_caster)->GetPureSkillValue(skill);
5630
5631    // Double chances for elites
5632    ((Player*)m_caster)->UpdateGatherSkill(skill, skillValue, reqValue, creature->isElite() ? 2 : 1 );
5633}
5634
5635void Spell::EffectCharge(uint32 /*i*/)
5636{
5637    if(!unitTarget || !m_caster)
5638        return;
5639
5640    float x, y, z;
5641    unitTarget->GetContactPoint(m_caster, x, y, z);
5642    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
5643        ((Creature *)unitTarget)->StopMoving();
5644
5645    // Only send MOVEMENTFLAG_WALK_MODE, client has strange issues with other move flags
5646    m_caster->SendMonsterMove(x, y, z, 0, MOVEMENTFLAG_WALK_MODE, 1);
5647
5648    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5649        MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster)->CreatureRelocation((Creature*)m_caster,x,y,z,m_caster->GetOrientation());
5650
5651    // not all charge effects used in negative spells
5652    if ( !IsPositiveSpell(m_spellInfo->Id))
5653        m_caster->Attack(unitTarget,true);
5654}
5655
5656void Spell::EffectSummonCritter(uint32 i)
5657{
5658    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5659        return;
5660    Player* player = (Player*)m_caster;
5661
5662    uint32 pet_entry = m_spellInfo->EffectMiscValue[i];
5663    if(!pet_entry)
5664        return;
5665
5666    Pet* old_critter = player->GetMiniPet();
5667
5668    // for same pet just despawn
5669    if(old_critter && old_critter->GetEntry() == pet_entry)
5670    {
5671        player->RemoveMiniPet();
5672        return;
5673    }
5674
5675    // despawn old pet before summon new
5676    if(old_critter)
5677        player->RemoveMiniPet();
5678
5679    // summon new pet
5680    Pet* critter = new Pet(MINI_PET);
5681
5682    Map *map = m_caster->GetMap();
5683    uint32 pet_number = objmgr.GeneratePetNumber();
5684    if(!critter->Create(objmgr.GenerateLowGuid(HIGHGUID_PET),
5685        map, pet_entry, pet_number))
5686    {
5687        sLog.outError("Spell::EffectSummonCritter, spellid %u: no such creature entry %u", m_spellInfo->Id, pet_entry);
5688        delete critter;
5689        return;
5690    }
5691
5692    float x,y,z;
5693    // If dest location if present
5694    if (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5695    {
5696         x = m_targets.m_destX;
5697         y = m_targets.m_destY;
5698         z = m_targets.m_destZ;
5699     }
5700     // Summon if dest location not present near caster
5701     else
5702         m_caster->GetClosePoint(x,y,z,critter->GetObjectSize());
5703
5704    critter->Relocate(x,y,z,m_caster->GetOrientation());
5705
5706    if(!critter->IsPositionValid())
5707    {
5708        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());
5709        delete critter;
5710        return;
5711    }
5712
5713    critter->SetUInt64Value(UNIT_FIELD_SUMMONEDBY,m_caster->GetGUID());
5714    critter->SetUInt64Value(UNIT_FIELD_CREATEDBY,m_caster->GetGUID());
5715    critter->SetUInt32Value(UNIT_FIELD_FACTIONTEMPLATE,m_caster->getFaction());
5716    critter->SetUInt32Value(UNIT_CREATED_BY_SPELL, m_spellInfo->Id);
5717
5718    critter->AIM_Initialize();
5719    critter->InitPetCreateSpells();                         // e.g. disgusting oozeling has a create spell as critter...
5720    critter->SetMaxHealth(1);
5721    critter->SetHealth(1);
5722    critter->SetLevel(1);
5723
5724    // set timer for unsummon
5725    int32 duration = GetSpellDuration(m_spellInfo);
5726    if(duration > 0)
5727        critter->SetDuration(duration);
5728
5729    std::string name = player->GetName();
5730    name.append(petTypeSuffix[critter->getPetType()]);
5731    critter->SetName( name );
5732    player->SetMiniPet(critter);
5733
5734    map->Add((Creature*)critter);
5735}
5736
5737void Spell::EffectKnockBack(uint32 i)
5738{
5739    if(!unitTarget || !m_caster)
5740        return;
5741
5742    // Effect only works on players
5743    if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5744        return;
5745
5746    float vsin = sin(m_caster->GetAngle(unitTarget));
5747    float vcos = cos(m_caster->GetAngle(unitTarget));
5748
5749    WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5750    data.append(unitTarget->GetPackGUID());
5751    data << uint32(0);                                      // Sequence
5752    data << float(vcos);                                    // x direction
5753    data << float(vsin);                                    // y direction
5754    data << float(m_spellInfo->EffectMiscValue[i])/10;      // Horizontal speed
5755    data << float(damage/-10);                              // Z Movement speed (vertical)
5756
5757    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5758}
5759
5760void Spell::EffectSendTaxi(uint32 i)
5761{
5762    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5763        return;
5764
5765    TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(m_spellInfo->EffectMiscValue[i]);
5766    if(!entry)
5767        return;
5768
5769    std::vector<uint32> nodes;
5770
5771    nodes.resize(2);
5772    nodes[0] = entry->from;
5773    nodes[1] = entry->to;
5774
5775    uint32 mountid = 0;
5776    switch(m_spellInfo->Id)
5777    {
5778        case 31606:       //Stormcrow Amulet
5779            mountid = 17447;
5780            break;
5781        case 45071:      //Quest - Sunwell Daily - Dead Scar Bombing Run
5782        case 45113:      //Quest - Sunwell Daily - Ship Bombing Run
5783        case 45353:      //Quest - Sunwell Daily - Ship Bombing Run Return
5784            mountid = 22840;
5785            break;
5786        case 34905:      //Stealth Flight
5787            mountid = 6851;
5788            break;
5789    }
5790
5791    ((Player*)unitTarget)->ActivateTaxiPathTo(nodes,mountid);
5792
5793}
5794
5795void Spell::EffectPlayerPull(uint32 i)
5796{
5797    if(!unitTarget || !m_caster)
5798        return;
5799
5800    // Effect only works on players
5801    if(unitTarget->GetTypeId()!=TYPEID_PLAYER)
5802        return;
5803
5804    float vsin = sin(unitTarget->GetAngle(m_caster));
5805    float vcos = cos(unitTarget->GetAngle(m_caster));
5806
5807    WorldPacket data(SMSG_MOVE_KNOCK_BACK, (8+4+4+4+4+4));
5808    data.append(unitTarget->GetPackGUID());
5809    data << uint32(0);                                      // Sequence
5810    data << float(vcos);                                    // x direction
5811    data << float(vsin);                                    // y direction
5812                                                            // Horizontal speed
5813    data << float(damage ? damage : unitTarget->GetDistance2d(m_caster));
5814    data << float(m_spellInfo->EffectMiscValue[i])/-10;     // Z Movement speed
5815
5816    ((Player*)unitTarget)->GetSession()->SendPacket(&data);
5817}
5818
5819void Spell::EffectDispelMechanic(uint32 i)
5820{
5821    if(!unitTarget)
5822        return;
5823
5824    uint32 mechanic = m_spellInfo->EffectMiscValue[i];
5825
5826    Unit::AuraMap& Auras = unitTarget->GetAuras();
5827    for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
5828    {
5829        next = iter;
5830        ++next;
5831        SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
5832        if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
5833        {
5834            unitTarget->RemoveAurasDueToSpell(spell->Id);
5835            if(Auras.empty())
5836                break;
5837            else
5838                next = Auras.begin();
5839        }
5840    }
5841    return;
5842}
5843
5844void Spell::EffectSummonDeadPet(uint32 /*i*/)
5845{
5846    if(m_caster->GetTypeId() != TYPEID_PLAYER)
5847        return;
5848    Player *_player = (Player*)m_caster;
5849    Pet *pet = _player->GetPet();
5850    if(!pet)
5851        return;
5852    if(pet->isAlive())
5853        return;
5854    if(damage < 0)
5855        return;
5856    pet->SetUInt32Value(UNIT_DYNAMIC_FLAGS, 0);
5857    pet->RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE);
5858    pet->setDeathState( ALIVE );
5859    pet->clearUnitState(UNIT_STAT_ALL_STATE);
5860    pet->SetHealth( uint32(pet->GetMaxHealth()*(float(damage)/100)));
5861
5862    pet->AIM_Initialize();
5863
5864    _player->PetSpellInitialize();
5865    pet->SavePetToDB(PET_SAVE_AS_CURRENT);
5866}
5867
5868void Spell::EffectDestroyAllTotems(uint32 /*i*/)
5869{
5870    float mana = 0;
5871    for(int slot = 0;  slot < MAX_TOTEM; ++slot)
5872    {
5873        if(!m_caster->m_TotemSlot[slot])
5874            continue;
5875
5876        Creature* totem = ObjectAccessor::GetCreature(*m_caster,m_caster->m_TotemSlot[slot]);
5877        if(totem && totem->isTotem())
5878        {
5879            uint32 spell_id = totem->GetUInt32Value(UNIT_CREATED_BY_SPELL);
5880            SpellEntry const* spellInfo = sSpellStore.LookupEntry(spell_id);
5881            if(spellInfo)
5882                mana += spellInfo->manaCost * damage / 100;
5883            ((Totem*)totem)->UnSummon();
5884        }
5885    }
5886
5887    int32 gain = m_caster->ModifyPower(POWER_MANA,int32(mana));
5888    m_caster->SendEnergizeSpellLog(m_caster, m_spellInfo->Id, gain, POWER_MANA);
5889}
5890
5891void Spell::EffectDurabilityDamage(uint32 i)
5892{
5893    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5894        return;
5895
5896    int32 slot = m_spellInfo->EffectMiscValue[i];
5897
5898    // FIXME: some spells effects have value -1/-2
5899    // Possibly its mean -1 all player equipped items and -2 all items
5900    if(slot < 0)
5901    {
5902        ((Player*)unitTarget)->DurabilityPointsLossAll(damage,(slot < -1));
5903        return;
5904    }
5905
5906    // invalid slot value
5907    if(slot >= INVENTORY_SLOT_BAG_END)
5908        return;
5909
5910    if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5911        ((Player*)unitTarget)->DurabilityPointsLoss(item,damage);
5912}
5913
5914void Spell::EffectDurabilityDamagePCT(uint32 i)
5915{
5916    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
5917        return;
5918
5919    int32 slot = m_spellInfo->EffectMiscValue[i];
5920
5921    // FIXME: some spells effects have value -1/-2
5922    // Possibly its mean -1 all player equipped items and -2 all items
5923    if(slot < 0)
5924    {
5925        ((Player*)unitTarget)->DurabilityLossAll(double(damage)/100.0f,(slot < -1));
5926        return;
5927    }
5928
5929    // invalid slot value
5930    if(slot >= INVENTORY_SLOT_BAG_END)
5931        return;
5932
5933    if(damage <= 0)
5934        return;
5935
5936    if(Item* item = ((Player*)unitTarget)->GetItemByPos(INVENTORY_SLOT_BAG_0,slot))
5937        ((Player*)unitTarget)->DurabilityLoss(item,double(damage)/100.0f);
5938}
5939
5940void Spell::EffectModifyThreatPercent(uint32 /*effIndex*/)
5941{
5942    if(!unitTarget)
5943        return;
5944
5945    unitTarget->getThreatManager().modifyThreatPercent(m_caster, damage);
5946}
5947
5948void Spell::EffectTransmitted(uint32 effIndex)
5949{
5950    uint32 name_id = m_spellInfo->EffectMiscValue[effIndex];
5951
5952    GameObjectInfo const* goinfo = objmgr.GetGameObjectInfo(name_id);
5953
5954    if (!goinfo)
5955    {
5956        sLog.outErrorDb("Gameobject (Entry: %u) not exist and not created at spell (ID: %u) cast",name_id, m_spellInfo->Id);
5957        return;
5958    }
5959
5960    float fx,fy,fz;
5961
5962    if(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION)
5963    {
5964        fx = m_targets.m_destX;
5965        fy = m_targets.m_destY;
5966        fz = m_targets.m_destZ;
5967    }
5968    //FIXME: this can be better check for most objects but still hack
5969    else if(m_spellInfo->EffectRadiusIndex[effIndex] && m_spellInfo->speed==0)
5970    {
5971        float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[effIndex]));
5972        m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5973    }
5974    else
5975    {
5976        float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5977        float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
5978        float dis = rand_norm() * (max_dis - min_dis) + min_dis;
5979
5980        m_caster->GetClosePoint(fx,fy,fz,DEFAULT_WORLD_OBJECT_SIZE, dis);
5981    }
5982
5983    Map *cMap = m_caster->GetMap();
5984
5985    if(goinfo->type==GAMEOBJECT_TYPE_FISHINGNODE)
5986    {
5987        if ( !cMap->IsInWater(fx,fy,fz-0.5f)) // Hack to prevent fishing bobber from failing to land on fishing hole
5988        { // but this is not proper, we really need to ignore not materialized objects
5989            SendCastResult(SPELL_FAILED_NOT_HERE);
5990            SendChannelUpdate(0);
5991            return;
5992        }
5993
5994        // replace by water level in this case
5995        fz = cMap->GetWaterLevel(fx,fy);
5996    }
5997    // if gameobject is summoning object, it should be spawned right on caster's position
5998    else if(goinfo->type==GAMEOBJECT_TYPE_SUMMONING_RITUAL)
5999    {
6000        m_caster->GetPosition(fx,fy,fz);
6001    }
6002
6003    GameObject* pGameObj = new GameObject;
6004
6005    if(!pGameObj->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), name_id, cMap,
6006        fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6007    {
6008        delete pGameObj;
6009        return;
6010    }
6011
6012    int32 duration = GetSpellDuration(m_spellInfo);
6013
6014    switch(goinfo->type)
6015    {
6016        case GAMEOBJECT_TYPE_FISHINGNODE:
6017        {
6018            m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,pGameObj->GetGUID());
6019                                                            // Orientation3
6020            pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 2, 0.88431775569915771 );
6021                                                            // Orientation4
6022            pGameObj->SetFloatValue(GAMEOBJECT_ROTATION + 3, -0.4668855369091033 );
6023            m_caster->AddGameObject(pGameObj);              // will removed at spell cancel
6024
6025            // end time of range when possible catch fish (FISHING_BOBBER_READY_TIME..GetDuration(m_spellInfo))
6026            // start time == fish-FISHING_BOBBER_READY_TIME (0..GetDuration(m_spellInfo)-FISHING_BOBBER_READY_TIME)
6027            int32 lastSec;
6028            switch(urand(0, 3))
6029            {
6030                case 0: lastSec =  3; break;
6031                case 1: lastSec =  7; break;
6032                case 2: lastSec = 13; break;
6033                case 3: lastSec = 17; break;
6034            }
6035
6036            duration = duration - lastSec*1000 + FISHING_BOBBER_READY_TIME*1000;
6037            break;
6038        }
6039        case GAMEOBJECT_TYPE_SUMMONING_RITUAL:
6040        {
6041            if(m_caster->GetTypeId()==TYPEID_PLAYER)
6042            {
6043                pGameObj->AddUniqueUse((Player*)m_caster);
6044                m_caster->AddGameObject(pGameObj);          // will removed at spell cancel
6045            }
6046            break;
6047        }
6048        case GAMEOBJECT_TYPE_FISHINGHOLE:
6049        case GAMEOBJECT_TYPE_CHEST:
6050        default:
6051        {
6052            break;
6053        }
6054    }
6055
6056    pGameObj->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6057
6058    pGameObj->SetOwnerGUID(m_caster->GetGUID() );
6059
6060    pGameObj->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6061    pGameObj->SetSpellId(m_spellInfo->Id);
6062
6063    DEBUG_LOG("AddObject at SpellEfects.cpp EffectTransmitted\n");
6064    //m_caster->AddGameObject(pGameObj);
6065    //m_ObjToDel.push_back(pGameObj);
6066
6067    cMap->Add(pGameObj);
6068
6069    WorldPacket data(SMSG_GAMEOBJECT_SPAWN_ANIM_OBSOLETE, 8);
6070    data << uint64(pGameObj->GetGUID());
6071    m_caster->SendMessageToSet(&data,true);
6072
6073    if(uint32 linkedEntry = pGameObj->GetLinkedGameObjectEntry())
6074    {
6075        GameObject* linkedGO = new GameObject;
6076        if(linkedGO->Create(objmgr.GenerateLowGuid(HIGHGUID_GAMEOBJECT), linkedEntry, cMap,
6077            fx, fy, fz, m_caster->GetOrientation(), 0, 0, 0, 0, 100, 1))
6078        {
6079            linkedGO->SetRespawnTime(duration > 0 ? duration/1000 : 0);
6080            linkedGO->SetUInt32Value(GAMEOBJECT_LEVEL, m_caster->getLevel() );
6081            linkedGO->SetSpellId(m_spellInfo->Id);
6082            linkedGO->SetOwnerGUID(m_caster->GetGUID() );
6083
6084            MapManager::Instance().GetMap(linkedGO->GetMapId(), linkedGO)->Add(linkedGO);
6085        }
6086        else
6087        {
6088            delete linkedGO;
6089            linkedGO = NULL;
6090            return;
6091        }
6092    }
6093}
6094
6095void Spell::EffectProspecting(uint32 /*i*/)
6096{
6097    if(m_caster->GetTypeId() != TYPEID_PLAYER)
6098        return;
6099
6100    Player* p_caster = (Player*)m_caster;
6101    if(!itemTarget || !(itemTarget->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP))
6102        return;
6103
6104    if(itemTarget->GetCount() < 5)
6105        return;
6106
6107    if( sWorld.getConfig(CONFIG_SKILL_PROSPECTING))
6108    {
6109        uint32 SkillValue = p_caster->GetPureSkillValue(SKILL_JEWELCRAFTING);
6110        uint32 reqSkillValue = itemTarget->GetProto()->RequiredSkillRank;
6111        p_caster->UpdateGatherSkill(SKILL_JEWELCRAFTING, SkillValue, reqSkillValue);
6112    }
6113
6114    ((Player*)m_caster)->SendLoot(itemTarget->GetGUID(), LOOT_PROSPECTING);
6115}
6116
6117void Spell::EffectSkill(uint32 /*i*/)
6118{
6119    sLog.outDebug("WORLD: SkillEFFECT");
6120}
6121
6122void Spell::EffectSummonDemon(uint32 i)
6123{
6124    float px = m_targets.m_destX;
6125    float py = m_targets.m_destY;
6126    float pz = m_targets.m_destZ;
6127
6128    Creature* Charmed = m_caster->SummonCreature(m_spellInfo->EffectMiscValue[i], px, py, pz, m_caster->GetOrientation(),TEMPSUMMON_TIMED_OR_DEAD_DESPAWN,3600000);
6129    if (!Charmed)
6130        return;
6131
6132    // might not always work correctly, maybe the creature that dies from CoD casts the effect on itself and is therefore the caster?
6133    Charmed->SetLevel(m_caster->getLevel());
6134
6135    // TODO: Add damage/mana/hp according to level
6136
6137    if (m_spellInfo->EffectMiscValue[i] == 89)              // Inferno summon
6138    {
6139        // Enslave demon effect, without mana cost and cooldown
6140        m_caster->CastSpell(Charmed, 20882, true);          // FIXME: enslave does not scale with level, level 62+ minions cannot be enslaved
6141
6142        // Inferno effect
6143        Charmed->CastSpell(Charmed, 22703, true, 0);
6144    }
6145}
6146
6147/* There is currently no need for this effect. We handle it in BattleGround.cpp
6148   If we would handle the resurrection here, the spiritguide would instantly disappear as the
6149   player revives, and so we wouldn't see the spirit heal visual effect on the npc.
6150   This is why we use a half sec delay between the visual effect and the resurrection itself */
6151void Spell::EffectSpiritHeal(uint32 /*i*/)
6152{
6153    /*
6154    if(!unitTarget || unitTarget->isAlive())
6155        return;
6156    if(unitTarget->GetTypeId() != TYPEID_PLAYER)
6157        return;
6158    if(!unitTarget->IsInWorld())
6159        return;
6160
6161    //m_spellInfo->EffectBasePoints[i]; == 99 (percent?)
6162    //((Player*)unitTarget)->setResurrect(m_caster->GetGUID(), unitTarget->GetPositionX(), unitTarget->GetPositionY(), unitTarget->GetPositionZ(), unitTarget->GetMaxHealth(), unitTarget->GetMaxPower(POWER_MANA));
6163    ((Player*)unitTarget)->ResurrectPlayer(1.0f);
6164    ((Player*)unitTarget)->SpawnCorpseBones();
6165    */
6166}
6167
6168// remove insignia spell effect
6169void Spell::EffectSkinPlayerCorpse(uint32 /*i*/)
6170{
6171    sLog.outDebug("Effect: SkinPlayerCorpse");
6172    if ( (m_caster->GetTypeId() != TYPEID_PLAYER) || (unitTarget->GetTypeId() != TYPEID_PLAYER) || (unitTarget->isAlive()) )
6173        return;
6174
6175    ((Player*)unitTarget)->RemovedInsignia( (Player*)m_caster );
6176}
6177
6178void Spell::EffectStealBeneficialBuff(uint32 i)
6179{
6180    sLog.outDebug("Effect: StealBeneficialBuff");
6181
6182    if(!unitTarget || unitTarget==m_caster)                 // can't steal from self
6183        return;
6184
6185    std::vector <Aura *> steal_list;
6186    // Create dispel mask by dispel type
6187    uint32 dispelMask  = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[i]) );
6188    Unit::AuraMap const& auras = unitTarget->GetAuras();
6189    for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6190    {
6191        Aura *aur = (*itr).second;
6192        if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
6193        {
6194            // Need check for passive? this
6195            if (aur->IsPositive() && !aur->IsPassive())
6196                steal_list.push_back(aur);
6197        }
6198    }
6199    // Ok if exist some buffs for dispel try dispel it
6200    if (!steal_list.empty())
6201    {
6202        std::list < std::pair<uint32,uint64> > success_list;
6203        int32 list_size = steal_list.size();
6204        // Dispell N = damage buffs (or while exist buffs for dispel)
6205        for (int32 count=0; count < damage && list_size > 0; ++count)
6206        {
6207            // Random select buff for dispel
6208            Aura *aur = steal_list[urand(0, list_size-1)];
6209            // Not use chance for steal
6210            // TODO possible need do it
6211            success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
6212
6213            // Remove buff from list for prevent doubles
6214            for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
6215            {
6216                Aura *stealed = *j;
6217                if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
6218                {
6219                    j = steal_list.erase(j);
6220                    --list_size;
6221                }
6222                else
6223                    ++j;
6224            }
6225        }
6226        // Really try steal and send log
6227        if (!success_list.empty())
6228        {
6229            int32 count = success_list.size();
6230            WorldPacket data(SMSG_SPELLSTEALLOG, 8+8+4+1+4+count*5);
6231            data.append(unitTarget->GetPackGUID());  // Victim GUID
6232            data.append(m_caster->GetPackGUID());    // Caster GUID
6233            data << uint32(m_spellInfo->Id);         // Dispell spell id
6234            data << uint8(0);                        // not used
6235            data << uint32(count);                   // count
6236            for (std::list<std::pair<uint32,uint64> >::iterator j = success_list.begin(); j != success_list.end(); ++j)
6237            {
6238                SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
6239                data << uint32(spellInfo->Id);       // Spell Id
6240                data << uint8(0);                    // 0 - steals !=0 transfers
6241                unitTarget->RemoveAurasDueToSpellBySteal(spellInfo->Id, j->second, m_caster);
6242            }
6243            m_caster->SendMessageToSet(&data, true);
6244        }
6245    }
6246}
6247
6248void Spell::EffectKillCredit(uint32 i)
6249{
6250    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6251        return;
6252
6253    ((Player*)unitTarget)->KilledMonster(m_spellInfo->EffectMiscValue[i], 0);
6254}
6255
6256void Spell::EffectQuestFail(uint32 i)
6257{
6258    if(!unitTarget || unitTarget->GetTypeId() != TYPEID_PLAYER)
6259        return;
6260
6261    ((Player*)unitTarget)->FailQuest(m_spellInfo->EffectMiscValue[i]);
6262}
Note: See TracBrowser for help on using the browser.