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

Revision 233, 243.2 kB (checked in by yumileroy, 17 years ago)

[svn] * Reimplemented packet/update forwarding in more generic way
* Implemented far sight spells (Far Sight, Eagle Eye, etc) at unlimited range and properly forward packets
* Implemented bind vision spells (Mind Vision, etc) to forward packets at unlimited distance
* Implemented Sentry Totem (both vision switching/forwarding and alerting)
* Other misc possession fixes
* Added .bindsight and .unbindsight commands

Please test out the above spells (including Mind Control) and report any issues on the forums.

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