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

Revision 174, 239.8 kB (checked in by yumileroy, 17 years ago)

[svn] Implemented player on player and player on creature possession:
* Implemented packet and vision forwarding through possessed units
* Added new OnPossess? script call alerting scripts on when possession is applied/removed
* Moved fall damage and fall under map calculations into the Player class
* Added new PossessedAI that is applied only while possession on creature is active
* Implemented summon possessed spell effect
* Fixed Eyes of the Beast

Original author: gvcoman
Date: 2008-11-05 20:51:05-06:00

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