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

Revision 44, 238.8 kB (checked in by yumileroy, 17 years ago)

[svn] * Merge Temp dev SVN with Assembla.
* Changes include:

  • Implementation of w12x's Outdoor PvP and Game Event Systems.
  • Temporary removal of IRC Chat Bot (until infinite loop when disabled is fixed).
  • All mangos -> trinity (to convert your mangos_string table, please run mangos_string_to_trinity_string.sql).
  • Improved Config cleanup.
  • And many more changes.

Original author: Seline
Date: 2008-10-14 11:57:03-05:00

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