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

Revision 178, 239.9 kB (checked in by yumileroy, 17 years ago)

[svn] Rewrite canSeeOrDetect function.
Minor change on trigger creatures.
Remove some unused hacks in scripts.

Original author: megamage
Date: 2008-11-06 10:27:58-06:00

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