root/trunk/src/game/Spell.cpp @ 140

Revision 140, 195.3 kB (checked in by yumileroy, 17 years ago)

[svn] Set target in combat even if spell does not hit target.
Call AI function only when spell hits target.
Move combat check from dealdamge to attackerstateupdate to remove redundant check.

Original author: megamage
Date: 2008-10-31 14:00:49-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
4 * Copyright (C) 2008 Trinity <http://www.trinitycore.org/>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21#include "Common.h"
22#include "Database/DatabaseEnv.h"
23#include "WorldPacket.h"
24#include "WorldSession.h"
25#include "GridNotifiers.h"
26#include "GridNotifiersImpl.h"
27#include "Opcodes.h"
28#include "Log.h"
29#include "UpdateMask.h"
30#include "World.h"
31#include "ObjectMgr.h"
32#include "SpellMgr.h"
33#include "Player.h"
34#include "Pet.h"
35#include "Unit.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 "CellImpl.h"
44#include "Policies/SingletonImp.h"
45#include "SharedDefines.h"
46#include "Tools.h"
47#include "LootMgr.h"
48#include "VMapFactory.h"
49#include "BattleGround.h"
50#include "Util.h"
51
52#define SPELL_CHANNEL_UPDATE_INTERVAL 1000
53
54extern pEffect SpellEffects[TOTAL_SPELL_EFFECTS];
55
56bool IsQuestTameSpell(uint32 spellId)
57{
58    SpellEntry const *spellproto = sSpellStore.LookupEntry(spellId);
59    if (!spellproto) return false;
60
61    return spellproto->Effect[0] == SPELL_EFFECT_THREAT
62        && spellproto->Effect[1] == SPELL_EFFECT_APPLY_AURA && spellproto->EffectApplyAuraName[1] == SPELL_AURA_DUMMY;
63}
64
65SpellCastTargets::SpellCastTargets()
66{
67    m_unitTarget = NULL;
68    m_itemTarget = NULL;
69    m_GOTarget   = NULL;
70
71    m_unitTargetGUID   = 0;
72    m_GOTargetGUID     = 0;
73    m_CorpseTargetGUID = 0;
74    m_itemTargetGUID   = 0;
75    m_itemTargetEntry  = 0;
76
77    m_srcX = m_srcY = m_srcZ = m_destX = m_destY = m_destZ = 0;
78    m_hasDest = false;
79    m_strTarget = "";
80    m_targetMask = 0;
81}
82
83SpellCastTargets::~SpellCastTargets()
84{
85}
86
87void SpellCastTargets::setUnitTarget(Unit *target)
88{
89    if (!target)
90        return;
91
92    m_unitTarget = target;
93    m_unitTargetGUID = target->GetGUID();
94    m_targetMask |= TARGET_FLAG_UNIT;
95}
96
97void SpellCastTargets::setDestination(float x, float y, float z, bool send)
98{
99    m_destX = x;
100    m_destY = y;
101    m_destZ = z;
102    m_hasDest = true;
103    if(send)
104        m_targetMask |= TARGET_FLAG_DEST_LOCATION;
105}
106
107void SpellCastTargets::setDestination(Unit *target, bool send)
108{
109    if(!target)
110        return;
111
112    m_destX = target->GetPositionX();
113    m_destY = target->GetPositionY();
114    m_destZ = target->GetPositionZ();
115    m_hasDest = true;
116    if(send)
117        m_targetMask |= TARGET_FLAG_DEST_LOCATION;
118}
119
120void SpellCastTargets::setGOTarget(GameObject *target)
121{
122    m_GOTarget = target;
123    m_GOTargetGUID = target->GetGUID();
124    //    m_targetMask |= TARGET_FLAG_OBJECT;
125}
126
127void SpellCastTargets::setItemTarget(Item* item)
128{
129    if(!item)
130        return;
131
132    m_itemTarget = item;
133    m_itemTargetGUID = item->GetGUID();
134    m_itemTargetEntry = item->GetEntry();
135    m_targetMask |= TARGET_FLAG_ITEM;
136}
137
138void SpellCastTargets::setCorpseTarget(Corpse* corpse)
139{
140    m_CorpseTargetGUID = corpse->GetGUID();
141}
142
143void SpellCastTargets::Update(Unit* caster)
144{
145    m_GOTarget   = m_GOTargetGUID ? ObjectAccessor::GetGameObject(*caster,m_GOTargetGUID) : NULL;
146    m_unitTarget = m_unitTargetGUID ?
147        ( m_unitTargetGUID==caster->GetGUID() ? caster : ObjectAccessor::GetUnit(*caster, m_unitTargetGUID) ) :
148    NULL;
149
150    m_itemTarget = NULL;
151    if(caster->GetTypeId()==TYPEID_PLAYER)
152    {
153        if(m_targetMask & TARGET_FLAG_ITEM)
154            m_itemTarget = ((Player*)caster)->GetItemByGuid(m_itemTargetGUID);
155        else
156        {
157            Player* pTrader = ((Player*)caster)->GetTrader();
158            if(pTrader && m_itemTargetGUID < TRADE_SLOT_COUNT)
159                m_itemTarget = pTrader->GetItemByPos(pTrader->GetItemPosByTradeSlot(m_itemTargetGUID));
160        }
161        if(m_itemTarget)
162            m_itemTargetEntry = m_itemTarget->GetEntry();
163    }
164}
165
166bool SpellCastTargets::read ( WorldPacket * data, Unit *caster )
167{
168    if(data->rpos()+4 > data->size())
169        return false;
170
171    *data >> m_targetMask;
172
173    if(m_targetMask == TARGET_FLAG_SELF)
174    {
175        //m_destX = caster->GetPositionX();
176        //m_destY = caster->GetPositionY();
177        //m_destZ = caster->GetPositionZ();
178        m_unitTarget = caster;
179        m_unitTargetGUID = caster->GetGUID();
180        return true;
181    }
182    // TARGET_FLAG_UNK2 is used for non-combat pets, maybe other?
183    if( m_targetMask & (TARGET_FLAG_UNIT|TARGET_FLAG_UNK2) )
184        if(!readGUID(*data, m_unitTargetGUID))
185            return false;
186
187    if( m_targetMask & ( TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK ))
188        if(!readGUID(*data, m_GOTargetGUID))
189            return false;
190
191    if(( m_targetMask & ( TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM )) && caster->GetTypeId() == TYPEID_PLAYER)
192        if(!readGUID(*data, m_itemTargetGUID))
193            return false;
194
195    /*if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION )
196    {
197        if(data->rpos()+4+4+4 > data->size())
198            return false;
199
200        *data >> m_srcX >> m_srcY >> m_srcZ;
201        if(!Trinity::IsValidMapCoord(m_srcX, m_srcY, m_srcZ))
202            return false;
203    }*/
204
205    if( m_targetMask & (TARGET_FLAG_SOURCE_LOCATION | TARGET_FLAG_DEST_LOCATION) )
206    {
207        if(data->rpos()+4+4+4 > data->size())
208            return false;
209
210        *data >> m_destX >> m_destY >> m_destZ;
211        m_hasDest = true;
212        if(!Trinity::IsValidMapCoord(m_destX, m_destY, m_destZ))
213            return false;
214    }
215
216    if( m_targetMask & TARGET_FLAG_STRING )
217    {
218        if(data->rpos()+1 > data->size())
219            return false;
220
221        *data >> m_strTarget;
222    }
223
224    if( m_targetMask & (TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE ) )
225        if(!readGUID(*data, m_CorpseTargetGUID))
226            return false;
227
228    // find real units/GOs
229    Update(caster);
230    return true;
231}
232
233void SpellCastTargets::write ( WorldPacket * data )
234{
235    *data << uint32(m_targetMask);
236
237    if( m_targetMask & ( TARGET_FLAG_UNIT | TARGET_FLAG_PVP_CORPSE | TARGET_FLAG_OBJECT | TARGET_FLAG_CORPSE | TARGET_FLAG_UNK2 ) )
238    {
239        if(m_targetMask & TARGET_FLAG_UNIT)
240        {
241            if(m_unitTarget)
242                data->append(m_unitTarget->GetPackGUID());
243            else
244                *data << uint8(0);
245        }
246        else if( m_targetMask & ( TARGET_FLAG_OBJECT | TARGET_FLAG_OBJECT_UNK ) )
247        {
248            if(m_GOTarget)
249                data->append(m_GOTarget->GetPackGUID());
250            else
251                *data << uint8(0);
252        }
253        else if( m_targetMask & ( TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE ) )
254            data->appendPackGUID(m_CorpseTargetGUID);
255        else
256            *data << uint8(0);
257    }
258
259    if( m_targetMask & ( TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM ) )
260    {
261        if(m_itemTarget)
262            data->append(m_itemTarget->GetPackGUID());
263        else
264            *data << uint8(0);
265    }
266
267    if( m_targetMask & TARGET_FLAG_SOURCE_LOCATION )
268        *data << m_srcX << m_srcY << m_srcZ;
269
270    if( m_targetMask & TARGET_FLAG_DEST_LOCATION )
271        *data << m_destX << m_destY << m_destZ;
272
273    if( m_targetMask & TARGET_FLAG_STRING )
274        *data << m_strTarget;
275}
276
277Spell::Spell( Unit* Caster, SpellEntry const *info, bool triggered, uint64 originalCasterGUID, Spell** triggeringContainer )
278{
279    ASSERT( Caster != NULL && info != NULL );
280    ASSERT( info == sSpellStore.LookupEntry( info->Id ) && "`info` must be pointer to sSpellStore element");
281
282    m_spellInfo = info;
283    m_caster = Caster;
284    m_selfContainer = NULL;
285    m_triggeringContainer = triggeringContainer;
286    m_magnetPair.first = false;
287    m_magnetPair.second = NULL;
288    m_deletable = true;
289    m_delayAtDamageCount = 0;
290
291    m_applyMultiplierMask = 0;
292
293    // Get data for type of attack
294    switch (m_spellInfo->DmgClass)
295    {
296        case SPELL_DAMAGE_CLASS_MELEE:
297            if (m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_OFFHAND)
298                m_attackType = OFF_ATTACK;
299            else
300                m_attackType = BASE_ATTACK;
301            break;
302        case SPELL_DAMAGE_CLASS_RANGED:
303            m_attackType = RANGED_ATTACK;
304            break;
305        default:
306                                                            // Wands
307            if (m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_REQ_WAND)
308                m_attackType = RANGED_ATTACK;
309            else
310                m_attackType = BASE_ATTACK;
311            break;
312    }
313
314    m_spellSchoolMask = GetSpellSchoolMask(info);           // Can be override for some spell (wand shoot for example)
315
316    if(m_attackType == RANGED_ATTACK)
317    {
318        // wand case
319        if((m_caster->getClassMask() & CLASSMASK_WAND_USERS) != 0 && m_caster->GetTypeId()==TYPEID_PLAYER)
320        {
321            if(Item* pItem = ((Player*)m_caster)->GetWeaponForAttack(RANGED_ATTACK))
322                m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetProto()->Damage->DamageType);
323        }
324    }
325
326    if(originalCasterGUID)
327        m_originalCasterGUID = originalCasterGUID;
328    else
329        m_originalCasterGUID = m_caster->GetGUID();
330
331    if(m_originalCasterGUID==m_caster->GetGUID())
332        m_originalCaster = m_caster;
333    else
334    {
335        m_originalCaster = ObjectAccessor::GetUnit(*m_caster,m_originalCasterGUID);
336        if(m_originalCaster && !m_originalCaster->IsInWorld()) m_originalCaster = NULL;
337    }
338
339    for(int i=0; i <3; ++i)
340        m_currentBasePoints[i] = m_spellInfo->EffectBasePoints[i];
341
342    m_spellState = SPELL_STATE_NULL;
343
344    m_castPositionX = m_castPositionY = m_castPositionZ = 0;
345    m_TriggerSpells.clear();
346    m_IsTriggeredSpell = triggered;
347    //m_AreaAura = false;
348    m_CastItem = NULL;
349
350    unitTarget = NULL;
351    itemTarget = NULL;
352    gameObjTarget = NULL;
353    focusObject = NULL;
354    m_cast_count = 0;
355    m_triggeredByAuraSpell  = NULL;
356
357    //Auto Shot & Shoot
358    if( m_spellInfo->AttributesEx2 == 0x000020 && !triggered )
359        m_autoRepeat = true;
360    else
361        m_autoRepeat = false;
362
363    m_powerCost = 0;                                        // setup to correct value in Spell::prepare, don't must be used before.
364    m_casttime = 0;                                         // setup to correct value in Spell::prepare, don't must be used before.
365    m_timer = 0;                                            // will set to castime in preper
366
367    m_needAliveTargetMask = 0;
368
369    // determine reflection
370    m_canReflect = false;
371
372    if(m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC && (m_spellInfo->AttributesEx2 & 0x4)==0)
373    {
374        for(int j=0;j<3;j++)
375        {
376            if (m_spellInfo->Effect[j]==0)
377                continue;
378
379            if(!IsPositiveTarget(m_spellInfo->EffectImplicitTargetA[j],m_spellInfo->EffectImplicitTargetB[j]))
380                m_canReflect = true;
381            else
382                m_canReflect = (m_spellInfo->AttributesEx & (1<<7)) ? true : false;
383
384            if(m_canReflect)
385                continue;
386            else
387                break;
388        }
389    }
390
391    CleanupTargetList();
392}
393
394Spell::~Spell()
395{
396}
397
398void Spell::FillTargetMap()
399{
400    // TODO: ADD the correct target FILLS!!!!!!
401
402    for(uint32 i=0;i<3;i++)
403    {
404        // not call for empty effect.
405        // Also some spells use not used effect targets for store targets for dummy effect in triggered spells
406        if(m_spellInfo->Effect[i]==0)
407            continue;
408
409        // TODO: find a way so this is not needed?
410        // for area auras always add caster as target (needed for totems for example)
411        if(IsAreaAuraEffect(m_spellInfo->Effect[i]))
412            AddUnitTarget(m_caster, i);
413
414        std::list<Unit*> tmpUnitMap;
415
416        // Note: this hack with search required until GO casting not implemented
417        // environment damage spells already have around enemies targeting but this not help in case not existed GO casting support
418        // currently each enemy selected explicitly and self cast damage
419        if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_ALL_AROUND_CASTER
420            && m_spellInfo->EffectImplicitTargetB[i]==TARGET_ALL_ENEMY_IN_AREA
421            && m_spellInfo->Effect[i]==SPELL_EFFECT_ENVIRONMENTAL_DAMAGE)
422        {
423            tmpUnitMap.push_back(m_targets.getUnitTarget());
424        }
425        else
426        {
427            SetTargetMap(i,m_spellInfo->EffectImplicitTargetA[i],tmpUnitMap);
428            SetTargetMap(i,m_spellInfo->EffectImplicitTargetB[i],tmpUnitMap);
429        }
430
431        if(m_targets.HasDest())
432        {
433            switch(m_spellInfo->Effect[i])
434            {
435                case SPELL_EFFECT_SUMMON:
436                case SPELL_EFFECT_SUMMON_WILD:
437                case SPELL_EFFECT_SUMMON_GUARDIAN:
438                case SPELL_EFFECT_SUMMON_PET:
439                case SPELL_EFFECT_SUMMON_POSSESSED:
440                case SPELL_EFFECT_SUMMON_TOTEM:
441                case SPELL_EFFECT_SUMMON_OBJECT_WILD:
442                case SPELL_EFFECT_SUMMON_TOTEM_SLOT1:
443                case SPELL_EFFECT_SUMMON_TOTEM_SLOT2:
444                case SPELL_EFFECT_SUMMON_TOTEM_SLOT3:
445                case SPELL_EFFECT_SUMMON_TOTEM_SLOT4:
446                case SPELL_EFFECT_SUMMON_CRITTER:
447                case SPELL_EFFECT_SUMMON_OBJECT_SLOT1:
448                case SPELL_EFFECT_SUMMON_OBJECT_SLOT2:
449                case SPELL_EFFECT_SUMMON_OBJECT_SLOT3:
450                case SPELL_EFFECT_SUMMON_OBJECT_SLOT4:
451                case SPELL_EFFECT_SUMMON_DEAD_PET:
452                case SPELL_EFFECT_SUMMON_DEMON:
453                {
454                    tmpUnitMap.push_back(m_caster);
455                    break;
456                }
457            }
458        }
459
460        if(!m_spellInfo->EffectImplicitTargetA[i])
461        {
462            switch(m_spellInfo->Effect[i])
463            {
464                case SPELL_EFFECT_PARRY:
465                case SPELL_EFFECT_BLOCK:
466                case SPELL_EFFECT_SKILL: // always with dummy 3 as A
467                case SPELL_EFFECT_LEARN_SPELL:
468                    tmpUnitMap.push_back(m_caster);
469                    break;
470            }
471        }
472
473        if(tmpUnitMap.empty())
474        {
475            /*if( m_spellInfo->EffectImplicitTargetA[i]==TARGET_SCRIPT ||
476                m_spellInfo->EffectImplicitTargetB[i]==TARGET_SCRIPT ||
477                m_spellInfo->EffectImplicitTargetA[i]==TARGET_SCRIPT_COORDINATES ||
478                m_spellInfo->EffectImplicitTargetB[i]==TARGET_SCRIPT_COORDINATES )
479            {
480                if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
481                    continue;
482            }*/
483
484            // add here custom effects that need default target.
485            // FOR EVERY TARGET TYPE THERE IS A DIFFERENT FILL!!
486            switch(m_spellInfo->Effect[i])
487            {
488                case SPELL_EFFECT_DUMMY:
489                {
490                    switch(m_spellInfo->Id)
491                    {
492                        case 20577:                         // Cannibalize
493                        {
494                            // non-standard target selection
495                            SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
496                            float max_range = GetSpellMaxRange(srange);
497
498                            CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
499                            Cell cell(p);
500                            cell.data.Part.reserved = ALL_DISTRICT;
501                            cell.SetNoCreate();
502
503                            WorldObject* result = NULL;
504
505                            Trinity::CannibalizeObjectCheck u_check(m_caster, max_range);
506                            Trinity::WorldObjectSearcher<Trinity::CannibalizeObjectCheck > searcher(result, u_check);
507
508                            TypeContainerVisitor<Trinity::WorldObjectSearcher<Trinity::CannibalizeObjectCheck >, GridTypeMapContainer > grid_searcher(searcher);
509                            CellLock<GridReadGuard> cell_lock(cell, p);
510                            cell_lock->Visit(cell_lock, grid_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
511
512                            if(!result)
513                            {
514                                TypeContainerVisitor<Trinity::WorldObjectSearcher<Trinity::CannibalizeObjectCheck >, WorldTypeMapContainer > world_searcher(searcher);
515                                cell_lock->Visit(cell_lock, world_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
516                            }
517
518                            if(result)
519                            {
520                                switch(result->GetTypeId())
521                                {
522                                    case TYPEID_UNIT:
523                                    case TYPEID_PLAYER:
524                                        tmpUnitMap.push_back((Unit*)result);
525                                        break;
526                                    case TYPEID_CORPSE:
527                                        m_targets.setCorpseTarget((Corpse*)result);
528                                        if(Player* owner = ObjectAccessor::FindPlayer(((Corpse*)result)->GetOwnerGUID()))
529                                            tmpUnitMap.push_back(owner);
530                                        break;
531                                }
532                            }
533                            else
534                            {
535                                // clear cooldown at fail
536                                if(m_caster->GetTypeId()==TYPEID_PLAYER)
537                                {
538                                    ((Player*)m_caster)->RemoveSpellCooldown(m_spellInfo->Id);
539
540                                    WorldPacket data(SMSG_CLEAR_COOLDOWN, (4+8));
541                                    data << uint32(m_spellInfo->Id);
542                                    data << uint64(m_caster->GetGUID());
543                                    ((Player*)m_caster)->GetSession()->SendPacket(&data);
544                                }
545
546                                SendCastResult(SPELL_FAILED_NO_EDIBLE_CORPSES);
547                                finish(false);
548                            }
549                            break;
550                        }
551                        default:
552                            if(m_targets.getUnitTarget())
553                                tmpUnitMap.push_back(m_targets.getUnitTarget());
554                            break;
555                    }
556                    break;
557                }
558                case SPELL_EFFECT_RESURRECT:
559                case SPELL_EFFECT_CREATE_ITEM:
560                case SPELL_EFFECT_TRIGGER_SPELL:
561                case SPELL_EFFECT_TRIGGER_MISSILE:
562                case SPELL_EFFECT_SKILL_STEP:
563                case SPELL_EFFECT_PROFICIENCY:
564                case SPELL_EFFECT_SELF_RESURRECT:
565                case SPELL_EFFECT_REPUTATION:
566                    if(m_targets.getUnitTarget())
567                        tmpUnitMap.push_back(m_targets.getUnitTarget());
568                    break;
569                case SPELL_EFFECT_SUMMON_PLAYER:
570                    if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->GetSelection())
571                    {
572                        Player* target = objmgr.GetPlayer(((Player*)m_caster)->GetSelection());
573                        if(target)
574                            tmpUnitMap.push_back(target);
575                    }
576                    break;
577                case SPELL_EFFECT_RESURRECT_NEW:
578                    if(m_targets.getUnitTarget())
579                        tmpUnitMap.push_back(m_targets.getUnitTarget());
580                    if(m_targets.getCorpseTargetGUID())
581                    {
582                        Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID());
583                        if(corpse)
584                        {
585                            Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID());
586                            if(owner)
587                                tmpUnitMap.push_back(owner);
588                        }
589                    }
590                    break;
591                case SPELL_EFFECT_SUMMON_CHANGE_ITEM:
592                case SPELL_EFFECT_TRANS_DOOR:
593                case SPELL_EFFECT_ADD_FARSIGHT:
594                case SPELL_EFFECT_STUCK:
595                case SPELL_EFFECT_DESTROY_ALL_TOTEMS:
596                    tmpUnitMap.push_back(m_caster);
597                    break;
598                case SPELL_EFFECT_LEARN_PET_SPELL:
599                    if(Pet* pet = m_caster->GetPet())
600                        tmpUnitMap.push_back(pet);
601                    break;
602                case SPELL_EFFECT_ENCHANT_ITEM:
603                case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY:
604                case SPELL_EFFECT_DISENCHANT:
605                case SPELL_EFFECT_FEED_PET:
606                case SPELL_EFFECT_PROSPECTING:
607                    if(m_targets.getItemTarget())
608                        AddItemTarget(m_targets.getItemTarget(), i);
609                    break;
610                case SPELL_EFFECT_APPLY_AURA:
611                    switch(m_spellInfo->EffectApplyAuraName[i])
612                    {
613                        case SPELL_AURA_ADD_FLAT_MODIFIER:  // some spell mods auras have 0 target modes instead expected TARGET_SELF(1) (and present for other ranks for same spell for example)
614                        case SPELL_AURA_ADD_PCT_MODIFIER:
615                            tmpUnitMap.push_back(m_caster);
616                            break;
617                        default:                            // apply to target in other case
618                            break;
619                    }
620                    break;
621                case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
622                                                            // AreaAura
623                    if(m_spellInfo->Attributes == 0x9050000 || m_spellInfo->Attributes == 0x10000)
624                        SetTargetMap(i,TARGET_AREAEFFECT_PARTY,tmpUnitMap);
625                    break;
626                case SPELL_EFFECT_SKIN_PLAYER_CORPSE:
627                    if(m_targets.getUnitTarget())
628                    {
629                        tmpUnitMap.push_back(m_targets.getUnitTarget());
630                    }
631                    else if (m_targets.getCorpseTargetGUID())
632                    {
633                        Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID());
634                        if(corpse)
635                        {
636                            Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID());
637                            if(owner)
638                                tmpUnitMap.push_back(owner);
639                        }
640                    }
641                    break;
642                default:
643                    break;
644            }
645        }
646        if(IsChanneledSpell(m_spellInfo) && !tmpUnitMap.empty())
647            m_needAliveTargetMask  |= (1<<i);
648
649        if(m_caster->GetTypeId() == TYPEID_PLAYER)
650        {
651            Player *me = (Player*)m_caster;
652            for (std::list<Unit*>::const_iterator itr = tmpUnitMap.begin(); itr != tmpUnitMap.end(); itr++)
653            {
654                Unit *owner = (*itr)->GetOwner();
655                Unit *u = owner ? owner : (*itr);
656                if(u!=m_caster && u->IsPvP() && (!me->duel || me->duel->opponent != u))
657                {
658                    me->UpdatePvP(true);
659                    me->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_ENTER_PVP_COMBAT);
660                    break;
661                }
662            }
663        }
664
665        for (std::list<Unit*>::iterator itr = tmpUnitMap.begin() ; itr != tmpUnitMap.end();)
666        {
667            if(!CheckTarget(*itr, i, false ))
668            {
669                itr = tmpUnitMap.erase(itr);
670                continue;
671            }
672            else
673                ++itr;
674        }
675
676        for(std::list<Unit*>::iterator iunit= tmpUnitMap.begin();iunit != tmpUnitMap.end();++iunit)
677            AddUnitTarget((*iunit), i);
678    }
679}
680
681void Spell::CleanupTargetList()
682{
683    m_UniqueTargetInfo.clear();
684    m_UniqueGOTargetInfo.clear();
685    m_UniqueItemInfo.clear();
686    m_countOfHit = 0;
687    m_countOfMiss = 0;
688    m_delayMoment = 0;
689}
690
691void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
692{
693    if( m_spellInfo->Effect[effIndex]==0 )
694        return;
695
696    uint64 targetGUID = pVictim->GetGUID();
697
698    // Lookup target in already in list
699    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
700    {
701        if (targetGUID == ihit->targetGUID)                 // Found in list
702        {
703            ihit->effectMask |= 1<<effIndex;                // Add only effect mask
704            return;
705        }
706    }
707
708    // This is new target calculate data for him
709
710    // Get spell hit result on target
711    TargetInfo target;
712    target.targetGUID = targetGUID;                         // Store target GUID
713    target.effectMask = 1<<effIndex;                        // Store index of effect
714    target.processed  = false;                              // Effects not apply on target
715
716    // Calculate hit result
717    target.missCondition = m_caster->SpellHitResult(pVictim, m_spellInfo, m_canReflect);
718    if (target.missCondition == SPELL_MISS_NONE)
719        ++m_countOfHit;
720    else
721        ++m_countOfMiss;
722
723    // Spell have speed - need calculate incoming time
724    if (m_spellInfo->speed > 0.0f)
725    {
726        // calculate spell incoming interval
727        float dist = m_caster->GetDistance(pVictim->GetPositionX(), pVictim->GetPositionY(), pVictim->GetPositionZ());
728        if (dist < 5.0f) dist = 5.0f;
729        target.timeDelay = (uint64) floor(dist / m_spellInfo->speed * 1000.0f);
730
731        // Calculate minimum incoming time
732        if (m_delayMoment==0 || m_delayMoment>target.timeDelay)
733            m_delayMoment = target.timeDelay;
734    }
735    else
736        target.timeDelay = 0LL;
737
738    // If target reflect spell back to caster
739    if (target.missCondition==SPELL_MISS_REFLECT)
740    {
741        // Calculate reflected spell result on caster
742        target.reflectResult =  m_caster->SpellHitResult(m_caster, m_spellInfo, m_canReflect);
743
744        if (target.reflectResult == SPELL_MISS_REFLECT)     // Impossible reflect again, so simply deflect spell
745            target.reflectResult = SPELL_MISS_PARRY;
746
747        // Increase time interval for reflected spells by 1.5
748        target.timeDelay+=target.timeDelay>>1;
749    }
750    else
751        target.reflectResult = SPELL_MISS_NONE;
752
753    // Add target to list
754    m_UniqueTargetInfo.push_back(target);
755}
756
757void Spell::AddUnitTarget(uint64 unitGUID, uint32 effIndex)
758{
759    Unit* unit = m_caster->GetGUID()==unitGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, unitGUID);
760    if (unit)
761        AddUnitTarget(unit, effIndex);
762}
763
764void Spell::AddGOTarget(GameObject* pVictim, uint32 effIndex)
765{
766    if( m_spellInfo->Effect[effIndex]==0 )
767        return;
768
769    uint64 targetGUID = pVictim->GetGUID();
770
771    // Lookup target in already in list
772    for(std::list<GOTargetInfo>::iterator ihit= m_UniqueGOTargetInfo.begin();ihit != m_UniqueGOTargetInfo.end();++ihit)
773    {
774        if (targetGUID == ihit->targetGUID)                 // Found in list
775        {
776            ihit->effectMask |= 1<<effIndex;                // Add only effect mask
777            return;
778        }
779    }
780
781    // This is new target calculate data for him
782
783    GOTargetInfo target;
784    target.targetGUID = targetGUID;
785    target.effectMask = 1<<effIndex;
786    target.processed  = false;                              // Effects not apply on target
787
788    // Spell have speed - need calculate incoming time
789    if (m_spellInfo->speed > 0.0f)
790    {
791        // calculate spell incoming interval
792        float dist = m_caster->GetDistance(pVictim->GetPositionX(), pVictim->GetPositionY(), pVictim->GetPositionZ());
793        if (dist < 5.0f) dist = 5.0f;
794        target.timeDelay = (uint64) floor(dist / m_spellInfo->speed * 1000.0f);
795        if (m_delayMoment==0 || m_delayMoment>target.timeDelay)
796            m_delayMoment = target.timeDelay;
797    }
798    else
799        target.timeDelay = 0LL;
800
801    ++m_countOfHit;
802
803    // Add target to list
804    m_UniqueGOTargetInfo.push_back(target);
805}
806
807void Spell::AddGOTarget(uint64 goGUID, uint32 effIndex)
808{
809    GameObject* go = ObjectAccessor::GetGameObject(*m_caster, goGUID);
810    if (go)
811        AddGOTarget(go, effIndex);
812}
813
814void Spell::AddItemTarget(Item* pitem, uint32 effIndex)
815{
816    if( m_spellInfo->Effect[effIndex]==0 )
817        return;
818
819    // Lookup target in already in list
820    for(std::list<ItemTargetInfo>::iterator ihit= m_UniqueItemInfo.begin();ihit != m_UniqueItemInfo.end();++ihit)
821    {
822        if (pitem == ihit->item)                            // Found in list
823        {
824            ihit->effectMask |= 1<<effIndex;                // Add only effect mask
825            return;
826        }
827    }
828
829    // This is new target add data
830
831    ItemTargetInfo target;
832    target.item       = pitem;
833    target.effectMask = 1<<effIndex;
834    m_UniqueItemInfo.push_back(target);
835}
836
837void Spell::doTriggers(SpellMissInfo missInfo, uint32 damage, SpellSchoolMask damageSchoolMask, uint32 block, uint32 absorb, bool crit)
838{
839    // Do triggers depends from hit result (triggers on hit do in effects)
840    // Set aura states depends from hit result
841    if (missInfo!=SPELL_MISS_NONE)
842    {
843        // Miss/dodge/parry/block only for melee based spells
844        // Resist only for magic based spells
845        switch (missInfo)
846        {
847            case SPELL_MISS_MISS:
848                if(m_caster->GetTypeId()== TYPEID_PLAYER)
849                    ((Player*)m_caster)->UpdateWeaponSkill(BASE_ATTACK);
850
851                m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_MISS, m_spellInfo, m_IsTriggeredSpell);
852                break;
853            case SPELL_MISS_RESIST:
854                m_caster->ProcDamageAndSpell(unitTarget, PROC_FLAG_TARGET_RESISTS, PROC_FLAG_RESIST_SPELL, 0, damageSchoolMask, m_spellInfo, m_IsTriggeredSpell);
855                break;
856            case SPELL_MISS_DODGE:
857                if(unitTarget->GetTypeId() == TYPEID_PLAYER)
858                    ((Player*)unitTarget)->UpdateDefense();
859
860                // Overpower
861                if (m_caster->GetTypeId() == TYPEID_PLAYER && m_caster->getClass() == CLASS_WARRIOR)
862                {
863                    ((Player*) m_caster)->AddComboPoints(unitTarget, 1);
864                    m_caster->StartReactiveTimer( REACTIVE_OVERPOWER );
865                }
866
867                // Riposte
868                if (unitTarget->getClass() != CLASS_ROGUE)
869                {
870                    unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true);
871                    unitTarget->StartReactiveTimer( REACTIVE_DEFENSE );
872                }
873
874                m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_DODGE, m_spellInfo, m_IsTriggeredSpell);
875                break;
876            case SPELL_MISS_PARRY:
877                // Update victim defense ?
878                if(unitTarget->GetTypeId() == TYPEID_PLAYER)
879                    ((Player*)unitTarget)->UpdateDefense();
880                // Mongoose bite - set only Counterattack here
881                if (unitTarget->getClass() == CLASS_HUNTER)
882                {
883                    unitTarget->ModifyAuraState(AURA_STATE_HUNTER_PARRY,true);
884                    unitTarget->StartReactiveTimer( REACTIVE_HUNTER_PARRY );
885                }
886                else
887                {
888                    unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true);
889                    unitTarget->StartReactiveTimer( REACTIVE_DEFENSE );
890                }
891                m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_PARRY, m_spellInfo, m_IsTriggeredSpell);
892                break;
893            case SPELL_MISS_BLOCK:
894                unitTarget->ModifyAuraState(AURA_STATE_DEFENSE, true);
895                unitTarget->StartReactiveTimer( REACTIVE_DEFENSE );
896
897                m_caster->CastMeleeProcDamageAndSpell(unitTarget, 0, damageSchoolMask, m_attackType, MELEE_HIT_BLOCK, m_spellInfo, m_IsTriggeredSpell);
898                break;
899                // Trigger from this events not supported
900            case SPELL_MISS_EVADE:
901            case SPELL_MISS_IMMUNE:
902            case SPELL_MISS_IMMUNE2:
903            case SPELL_MISS_DEFLECT:
904            case SPELL_MISS_ABSORB:
905                // Trigger from reflects need do after get reflect result
906            case SPELL_MISS_REFLECT:
907                break;
908            default:
909                break;
910        }
911    }
912}
913
914void Spell::DoAllEffectOnTarget(TargetInfo *target)
915{
916    if (target->processed)                                  // Check target
917        return;
918    target->processed = true;                               // Target checked in apply effects procedure
919
920    // Get mask of effects for target
921    uint32 mask = target->effectMask;
922    if (mask == 0)                                          // No effects
923        return;
924
925    Unit* unit = m_caster->GetGUID()==target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster,target->targetGUID);
926    if (!unit)
927        return;
928
929    SpellMissInfo missInfo = target->missCondition;
930    // Need init unitTarget by default unit (can changed in code on reflect)
931    // Or on missInfo!=SPELL_MISS_NONE unitTarget undefined (but need in trigger subsystem)
932    unitTarget = unit;
933
934    if (missInfo==SPELL_MISS_NONE)                          // In case spell hit target, do all effect on that target
935        DoSpellHitOnUnit(unit, mask);
936    else if (missInfo == SPELL_MISS_REFLECT)                // In case spell reflect from target, do all effect on caster (if hit)
937    {
938        if (target->reflectResult == SPELL_MISS_NONE)       // If reflected spell hit caster -> do all effect on him
939            DoSpellHitOnUnit(m_caster, mask);
940    }
941
942    // Do triggers only on miss/resist/parry/dodge
943    if (missInfo!=SPELL_MISS_NONE)
944        doTriggers(missInfo);
945
946    // Call scripted function for AI if this spell is casted upon a creature (except pets)
947    if(IS_CREATURE_GUID(target->targetGUID))
948    {
949        // cast at creature (or GO) quest objectives update at successful cast finished (+channel finished)
950        // ignore autorepeat/melee casts for speed (not exist quest for spells (hm... )
951        if( m_caster->GetTypeId() == TYPEID_PLAYER && !IsAutoRepeat() && !IsNextMeleeSwingSpell() && !IsChannelActive() )
952            ((Player*)m_caster)->CastedCreatureOrGO(unit->GetEntry(),unit->GetGUID(),m_spellInfo->Id);
953    }
954
955    if( !m_caster->IsFriendlyTo(unit) && !IsPositiveSpell(m_spellInfo->Id))
956    {
957        if( !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) )
958        {
959            if(!unit->IsStandState() && !unit->hasUnitState(UNIT_STAT_STUNNED))
960                unit->SetStandState(PLAYER_STATE_NONE);
961
962            if(!unit->isInCombat() && unit->GetTypeId() != TYPEID_PLAYER && ((Creature*)unit)->AI())
963                ((Creature*)unit)->AI()->AttackStart(m_caster);
964
965            unit->SetInCombatWith(m_caster);
966            m_caster->SetInCombatWith(unit);
967
968            if(Player *attackedPlayer = unit->GetCharmerOrOwnerPlayerOrPlayerItself())
969                m_caster->SetContestedPvP(attackedPlayer);
970        }
971    }
972}
973
974void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
975{
976    if(!unit || !effectMask)
977        return;
978
979    // remove spell_magnet aura after first spell redirect and destroy target if its totem
980    if(m_magnetPair.first && m_magnetPair.second && m_magnetPair.second == unit)
981    {
982        if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->isTotem())
983            unit->DealDamage(unit,unit->GetHealth(), NULL, DIRECT_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
984        return;
985    }
986
987    // Recheck immune (only for delayed spells)
988    if( m_spellInfo->speed && (
989        unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo),true) ||
990        unit->IsImmunedToSpell(m_spellInfo,true) ))
991    {
992        m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_IMMUNE);
993        return;
994    }
995
996    if( m_caster != unit )
997    {
998        if( !m_caster->IsFriendlyTo(unit) )
999        {
1000            // for delayed spells ignore not visible explicit target
1001            if(m_spellInfo->speed > 0.0f && unit==m_targets.getUnitTarget() && !unit->isVisibleForOrDetect(m_caster,false))
1002            {
1003                m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
1004                return;
1005            }
1006
1007            //if(!IsPositiveSpell(m_spellInfo->Id))
1008            {
1009                unit->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
1010            }
1011        }
1012        else
1013        {
1014            // for delayed spells ignore negative spells (after duel end) for friendly targets
1015            if(m_spellInfo->speed > 0.0f && !IsPositiveSpell(m_spellInfo->Id))
1016            {
1017                m_caster->SendSpellMiss(unit, m_spellInfo->Id, SPELL_MISS_EVADE);
1018                return;
1019            }
1020
1021            // assisting case, healing and resurrection
1022            if(unit->hasUnitState(UNIT_STAT_ATTACK_PLAYER))
1023                m_caster->SetContestedPvP();
1024            if( unit->isInCombat() && !(m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_NO_INITIAL_AGGRO) )
1025            {
1026                m_caster->SetInCombatState(unit->GetCombatTimer() > 0);
1027                unit->getHostilRefManager().threatAssist(m_caster, 0.0f);
1028            }
1029        }
1030    }
1031
1032    // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add
1033    m_diminishGroup = GetDiminishingReturnsGroupForSpell(m_spellInfo,m_triggeredByAuraSpell);
1034    m_diminishLevel = unit->GetDiminishing(m_diminishGroup);
1035    // Increase Diminishing on unit, current informations for actually casts will use values above
1036    if((GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_PLAYER && unit->GetTypeId() == TYPEID_PLAYER) || GetDiminishingReturnsGroupType(m_diminishGroup) == DRTYPE_ALL)
1037        unit->IncrDiminishing(m_diminishGroup);
1038
1039    for(uint32 effectNumber=0;effectNumber<3;effectNumber++)
1040    {
1041        if (effectMask & (1<<effectNumber))
1042        {
1043            HandleEffects(unit,NULL,NULL,effectNumber,m_damageMultipliers[effectNumber]);
1044            if ( m_applyMultiplierMask & (1 << effectNumber) )
1045            {
1046                // Get multiplier
1047                float multiplier = m_spellInfo->DmgMultiplier[effectNumber];
1048                // Apply multiplier mods
1049                if(Player* modOwner = m_originalCaster->GetSpellModOwner())
1050                    modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_EFFECT_PAST_FIRST, multiplier,this);
1051                m_damageMultipliers[effectNumber] *= multiplier;
1052            }
1053        }
1054    }
1055
1056    if(unit->GetTypeId() == TYPEID_UNIT && ((Creature*)unit)->AI())
1057        ((Creature*)unit)->AI()->SpellHit(m_caster, m_spellInfo);
1058
1059    if(m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->AI())
1060        ((Creature*)m_caster)->AI()->SpellHitTarget(unit, m_spellInfo);
1061
1062    if(int32 spell_triggered = spellmgr.GetSpellLinked(m_spellInfo->Id, 1))
1063    {
1064        if(spell_triggered > 0)
1065            unit->CastSpell(unit, spell_triggered, true, 0, 0, m_caster->GetGUID());
1066        else
1067            unit->RemoveAurasDueToSpell(-spell_triggered);
1068    }
1069}
1070
1071void Spell::DoAllEffectOnTarget(GOTargetInfo *target)
1072{
1073    if (target->processed)                                  // Check target
1074        return;
1075    target->processed = true;                               // Target checked in apply effects procedure
1076
1077    uint32 effectMask = target->effectMask;
1078    if(!effectMask)
1079        return;
1080
1081    GameObject* go = ObjectAccessor::GetGameObject(*m_caster, target->targetGUID);
1082    if(!go)
1083        return;
1084
1085    for(uint32 effectNumber=0;effectNumber<3;effectNumber++)
1086        if (effectMask & (1<<effectNumber))
1087            HandleEffects(NULL,NULL,go,effectNumber);
1088
1089    // cast at creature (or GO) quest objectives update at successful cast finished (+channel finished)
1090    // ignore autorepeat/melee casts for speed (not exist quest for spells (hm... )
1091    if( m_caster->GetTypeId() == TYPEID_PLAYER && !IsAutoRepeat() && !IsNextMeleeSwingSpell() && !IsChannelActive() )
1092        ((Player*)m_caster)->CastedCreatureOrGO(go->GetEntry(),go->GetGUID(),m_spellInfo->Id);
1093}
1094
1095void Spell::DoAllEffectOnTarget(ItemTargetInfo *target)
1096{
1097    uint32 effectMask = target->effectMask;
1098    if(!target->item || !effectMask)
1099        return;
1100
1101    for(uint32 effectNumber=0;effectNumber<3;effectNumber++)
1102        if (effectMask & (1<<effectNumber))
1103            HandleEffects(NULL, target->item, NULL, effectNumber);
1104}
1105
1106bool Spell::IsAliveUnitPresentInTargetList()
1107{
1108    // Not need check return true
1109    if (m_needAliveTargetMask == 0)
1110        return true;
1111
1112    uint8 needAliveTargetMask = m_needAliveTargetMask;
1113
1114    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
1115    {
1116        if( ihit->missCondition == SPELL_MISS_NONE && (needAliveTargetMask & ihit->effectMask) )
1117        {
1118            Unit *unit = m_caster->GetGUID()==ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
1119
1120            if (unit && unit->isAlive())
1121                needAliveTargetMask &= ~ihit->effectMask;   // remove from need alive mask effect that have alive target
1122        }
1123    }
1124
1125    // is all effects from m_needAliveTargetMask have alive targets
1126    return needAliveTargetMask==0;
1127}
1128
1129// Helper for Chain Healing
1130// Spell target first
1131// Raidmates then descending by injury suffered (MaxHealth - Health)
1132// Other players/mobs then descending by injury suffered (MaxHealth - Health)
1133struct ChainHealingOrder : public std::binary_function<const Unit*, const Unit*, bool>
1134{
1135    const Unit* MainTarget;
1136    ChainHealingOrder(Unit const* Target) : MainTarget(Target) {};
1137    // functor for operator ">"
1138    bool operator()(Unit const* _Left, Unit const* _Right) const
1139    {
1140        return (ChainHealingHash(_Left) < ChainHealingHash(_Right));
1141    }
1142    int32 ChainHealingHash(Unit const* Target) const
1143    {
1144        if (Target == MainTarget)
1145            return 0;
1146        else if (Target->GetTypeId() == TYPEID_PLAYER && MainTarget->GetTypeId() == TYPEID_PLAYER &&
1147            ((Player const*)Target)->IsInSameRaidWith((Player const*)MainTarget))
1148        {
1149            if (Target->GetHealth() == Target->GetMaxHealth())
1150                return 40000;
1151            else
1152                return 20000 - Target->GetMaxHealth() + Target->GetHealth();
1153        }
1154        else
1155            return 40000 - Target->GetMaxHealth() + Target->GetHealth();
1156    }
1157};
1158
1159class ChainHealingFullHealth: std::unary_function<const Unit*, bool>
1160{
1161    public:
1162        const Unit* MainTarget;
1163        ChainHealingFullHealth(const Unit* Target) : MainTarget(Target) {};
1164
1165        bool operator()(const Unit* Target)
1166        {
1167            return (Target != MainTarget && Target->GetHealth() == Target->GetMaxHealth());
1168        }
1169};
1170
1171// Helper for targets nearest to the spell target
1172// The spell target is always first unless there is a target at _completely_ the same position (unbelievable case)
1173struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit, bool>
1174{
1175    const Unit* MainTarget;
1176    TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {};
1177    // functor for operator ">"
1178    bool operator()(const Unit* _Left, const Unit* _Right) const
1179    {
1180        return (MainTarget->GetDistance(_Left) < MainTarget->GetDistance(_Right));
1181    }
1182};
1183
1184void Spell::SearchChainTarget(std::list<Unit*> &TagUnitMap, Unit* pUnitTarget, float max_range, uint32 unMaxTargets)
1185{
1186    if(!pUnitTarget)
1187        return;
1188
1189    //FIXME: This very like horrible hack and wrong for most spells
1190    if(m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE)
1191        max_range += unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
1192
1193    CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
1194    Cell cell(p);
1195    cell.data.Part.reserved = ALL_DISTRICT;
1196    cell.SetNoCreate();
1197
1198    std::list<Unit *> tempUnitMap;
1199
1200    {
1201        Trinity::AnyAoETargetUnitInObjectRangeCheck u_check(pUnitTarget, m_caster, max_range);
1202        Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck> searcher(tempUnitMap, u_check);
1203
1204        TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
1205        TypeContainerVisitor<Trinity::UnitListSearcher<Trinity::AnyAoETargetUnitInObjectRangeCheck>, GridTypeMapContainer >  grid_unit_searcher(searcher);
1206
1207        CellLock<GridReadGuard> cell_lock(cell, p);
1208        cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1209        cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1210    }
1211
1212    tempUnitMap.sort(TargetDistanceOrder(pUnitTarget));
1213
1214    if(tempUnitMap.empty())
1215        return;
1216
1217    uint32 t = unMaxTargets;
1218    if(pUnitTarget != m_caster)
1219    {
1220        if(*tempUnitMap.begin() == pUnitTarget)
1221            tempUnitMap.erase(tempUnitMap.begin());
1222        TagUnitMap.push_back(pUnitTarget);
1223        --t;
1224    }
1225    Unit *prev = pUnitTarget;
1226
1227    std::list<Unit*>::iterator next = tempUnitMap.begin();
1228
1229    while(t && next != tempUnitMap.end())
1230    {
1231        if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
1232            break;
1233
1234        if(!prev->IsWithinLOSInMap(*next)
1235            || m_spellInfo->DmgClass==SPELL_DAMAGE_CLASS_MELEE && !m_caster->isInFront(*next, max_range))
1236        {
1237            ++next;
1238            continue;
1239        }
1240
1241        prev = *next;
1242        TagUnitMap.push_back(prev);
1243        tempUnitMap.erase(next);
1244        tempUnitMap.sort(TargetDistanceOrder(prev));
1245        next = tempUnitMap.begin();
1246        --t;
1247    }
1248}
1249
1250void Spell::SearchAreaTarget(std::list<Unit*> &TagUnitMap, float radius, const uint32 &type, SpellTargets TargetType, uint32 entry)
1251{
1252    if(type == PUSH_DEST_CENTER && !m_targets.HasDest())
1253    {
1254        sLog.outError( "SPELL: cannot find destination for spell ID %u\n", m_spellInfo->Id );
1255        return;
1256    }
1257
1258    CellPair p(Trinity::ComputeCellPair(m_targets.m_destX, m_targets.m_destY));
1259    Cell cell(p);
1260    cell.data.Part.reserved = ALL_DISTRICT;
1261    cell.SetNoCreate();
1262    CellLock<GridReadGuard> cell_lock(cell, p);
1263
1264    Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, entry);
1265   
1266    if(TargetType != SPELL_TARGETS_ENTRY)
1267    {
1268        TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
1269        cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1270    }
1271    if(!spellmgr.GetSpellExtraAttr(m_spellInfo->Id, SPELL_EXTRA_ATTR_MAX_TARGETS))
1272    {
1273        TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer >  grid_object_notifier(notifier);
1274        cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1275    }
1276}
1277
1278Unit* Spell::SearchNearbyTarget(float radius, SpellTargets TargetType, uint32 entry)
1279{
1280    CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
1281    Cell cell(p);
1282    cell.data.Part.reserved = ALL_DISTRICT;
1283    cell.SetNoCreate();
1284    CellLock<GridReadGuard> cell_lock(cell, p);
1285
1286    Unit* target = NULL;
1287    switch(TargetType)
1288    {
1289        case SPELL_TARGETS_ENTRY:
1290        {
1291            Creature* target = NULL;
1292            Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster, entry, true, radius);
1293            Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(target, u_check);
1294            TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer >  grid_unit_searcher(searcher);
1295            cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1296            return target;
1297        }break;
1298        default:
1299        case SPELL_TARGETS_AOE_DAMAGE:
1300        {
1301            Trinity::AnyUnfriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius);
1302            Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck> searcher(target, u_check);
1303            TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
1304            TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::AnyUnfriendlyUnitInObjectRangeCheck>, GridTypeMapContainer >  grid_unit_searcher(searcher);
1305            cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1306            cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1307        }break;
1308        case SPELL_TARGETS_FRIENDLY:
1309        {
1310            Trinity::AnyFriendlyUnitInObjectRangeCheck u_check(m_caster, m_caster, radius);
1311            Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck> searcher(target, u_check);
1312            TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck>, WorldTypeMapContainer > world_unit_searcher(searcher);
1313            TypeContainerVisitor<Trinity::UnitLastSearcher<Trinity::AnyFriendlyUnitInObjectRangeCheck>, GridTypeMapContainer >  grid_unit_searcher(searcher);
1314            cell_lock->Visit(cell_lock, world_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1315            cell_lock->Visit(cell_lock, grid_unit_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1316        }break;
1317    }
1318    return target;
1319}
1320
1321void Spell::SetTargetMap(uint32 i,uint32 cur,std::list<Unit*> &TagUnitMap)
1322{
1323    float radius;
1324    if (m_spellInfo->EffectRadiusIndex[i])
1325        radius = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
1326    else
1327        radius = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
1328
1329    uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[i];
1330    uint32 unMaxTargets = m_spellInfo->MaxAffectedTargets;
1331    if(!unMaxTargets)
1332        unMaxTargets = spellmgr.GetSpellExtraAttr(m_spellInfo->Id, SPELL_EXTRA_ATTR_MAX_TARGETS);
1333    if(m_originalCaster)
1334    {
1335        if(Player* modOwner = m_originalCaster->GetSpellModOwner())
1336        {
1337            modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius,this);
1338            modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this);
1339        }
1340    }
1341
1342    switch(cur)
1343    {
1344        // specific unit
1345        case TARGET_SELF:
1346        case TARGET_SELF_FISHING:
1347        {
1348            TagUnitMap.push_back(m_caster);
1349        }break;
1350        case TARGET_MASTER:
1351        {
1352            if(Unit* owner = m_caster->GetCharmerOrOwner())
1353                TagUnitMap.push_back(owner);
1354        }break;
1355        case TARGET_PET:
1356        {
1357            if(Pet* tmpUnit = m_caster->GetPet())
1358                TagUnitMap.push_back(tmpUnit);
1359        }break;
1360        case TARGET_NONCOMBAT_PET:
1361        {
1362            if(Unit* target = m_targets.getUnitTarget())
1363                if( target->GetTypeId() == TYPEID_UNIT && ((Creature*)target)->isPet() && ((Pet*)target)->getPetType() == MINI_PET)
1364                    TagUnitMap.push_back(target);
1365        }break;
1366        case TARGET_SINGLE_FRIEND: // ally
1367        case TARGET_SINGLE_FRIEND_2: // raid member
1368        case TARGET_DUELVSPLAYER: // all (SelectMagnetTarget()?)
1369        case TARGET_UNIT_SINGLE_UNKNOWN:
1370        {
1371            if(m_targets.getUnitTarget())
1372                TagUnitMap.push_back(m_targets.getUnitTarget());
1373        }break;
1374        case TARGET_CHAIN_DAMAGE:
1375        {
1376            if(Unit* pUnitTarget = SelectMagnetTarget())
1377            {
1378                if(EffectChainTarget <= 1)
1379                    TagUnitMap.push_back(pUnitTarget);
1380                else //TODO: chain target should also use magnet target
1381                    SearchChainTarget(TagUnitMap, pUnitTarget, radius, EffectChainTarget);
1382            }
1383        }break;
1384        case TARGET_GAMEOBJECT:
1385        {
1386            if(m_targets.getGOTarget())
1387                AddGOTarget(m_targets.getGOTarget(), i);
1388        }break;
1389        case TARGET_GAMEOBJECT_ITEM:
1390        {
1391            if(m_targets.getGOTargetGUID())
1392                AddGOTarget(m_targets.getGOTarget(), i);
1393            else if(m_targets.getItemTarget())
1394                AddItemTarget(m_targets.getItemTarget(), i);
1395        }break;
1396
1397        // channel
1398        case TARGET_SINGLE_ENEMY:
1399            if(m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL])
1400            {
1401                if(Unit* target = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.getUnitTarget())
1402                    TagUnitMap.push_back(target);
1403                else
1404                    sLog.outError( "SPELL: cannot find channel spell target for spell ID %u\n", m_spellInfo->Id );
1405            }
1406            else
1407                sLog.outError( "SPELL: no current channeled spell for spell ID %u\n", m_spellInfo->Id );
1408            break;
1409        case TARGET_DEST_CHANNEL:
1410            if(m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL])
1411            {
1412                if(m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets.HasDest())
1413                    m_targets = m_caster->m_currentSpells[CURRENT_CHANNELED_SPELL]->m_targets;
1414                else
1415                    sLog.outError( "SPELL: cannot find channel spell destination for spell ID %u\n", m_spellInfo->Id );
1416            }
1417            else
1418                sLog.outError( "SPELL: no current channeled spell for spell ID %u\n", m_spellInfo->Id );
1419            break;
1420
1421        // reference dest
1422        case TARGET_EFFECT_SELECT:
1423            m_targets.setDestination(m_caster, true);
1424            break;
1425        case TARGET_ALL_AROUND_CASTER:
1426            m_targets.setDestination(m_caster, false);
1427            break;
1428        case TARGET_CURRENT_ENEMY_COORDINATES:
1429            m_targets.setDestination(m_targets.getUnitTarget(), true);
1430            break;
1431        case TARGET_DUELVSPLAYER_COORDINATES: // no ground?
1432            m_targets.setDestination(m_targets.getUnitTarget(), false);
1433            break;
1434        case TARGET_DEST_TABLE_UNKNOWN2:
1435        case TARGET_TABLE_X_Y_Z_COORDINATES:
1436            if(SpellTargetPosition const* st = spellmgr.GetSpellTargetPosition(m_spellInfo->Id))
1437            {
1438                if (st->target_mapId == m_caster->GetMapId())
1439                    m_targets.setDestination(st->target_X, st->target_Y, st->target_Z);
1440            }
1441            else
1442                sLog.outError( "SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id );
1443            break;
1444
1445        // area targets
1446                case TARGET_AREAEFFECT_CUSTOM:
1447        case TARGET_ALL_ENEMY_IN_AREA_INSTANT:
1448            if(m_spellInfo->Effect[i] == SPELL_EFFECT_PERSISTENT_AREA_AURA)
1449                break;
1450            m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
1451        case TARGET_ALL_ENEMY_IN_AREA:
1452            SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_AOE_DAMAGE);
1453            break;
1454        case TARGET_ALL_FRIENDLY_UNITS_IN_AREA:
1455            m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
1456        case TARGET_ALL_FRIENDLY_UNITS_AROUND_CASTER:
1457            SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_FRIENDLY);
1458            break;
1459        //case TARGET_AREAEFFECT_CUSTOM:
1460        //    m_targets.m_targetMask |= TARGET_FLAG_DEST_LOCATION;
1461        case TARGET_UNIT_AREA_ENTRY:
1462        {
1463            SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id);
1464            SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id);
1465            if(lower==upper)
1466            {
1467                sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT, but does not have record in `spell_script_target`",m_spellInfo->Id);
1468                break;
1469            }
1470            // let it be done in one check?
1471            for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST)
1472            {
1473                if(i_spellST->second.type != SPELL_TARGET_TYPE_CREATURE)
1474                {
1475                    sLog.outError( "SPELL: spell ID %u requires non-creature target\n", m_spellInfo->Id );
1476                    continue;
1477                }
1478                SearchAreaTarget(TagUnitMap, radius, PUSH_DEST_CENTER, SPELL_TARGETS_ENTRY, i_spellST->second.targetEntry);
1479            }
1480        }break;
1481        case TARGET_IN_FRONT_OF_CASTER:
1482        case TARGET_UNIT_CONE_ENEMY_UNKNOWN:
1483        {
1484            switch(spellmgr.GetSpellExtraAttr(m_spellInfo->Id, SPELL_EXTRA_ATTR_CONE_TYPE))
1485            {
1486                default:
1487                case 0:
1488                    SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_AOE_DAMAGE);
1489                    break;
1490                case 1:
1491                    SearchAreaTarget(TagUnitMap, radius, PUSH_IN_BACK, SPELL_TARGETS_AOE_DAMAGE);
1492                    break;
1493                case 2:
1494                    SearchAreaTarget(TagUnitMap, radius, PUSH_IN_LINE, SPELL_TARGETS_AOE_DAMAGE);
1495                    break;
1496            }
1497        }break;
1498        case TARGET_UNIT_CONE_ALLY:
1499        {
1500            SearchAreaTarget(TagUnitMap, radius, PUSH_IN_FRONT, SPELL_TARGETS_FRIENDLY);
1501        }break;
1502
1503        // nearby target
1504        case TARGET_UNIT_NEARBY_ALLY:
1505        {
1506            if(Unit* pUnitTarget = SearchNearbyTarget(radius, SPELL_TARGETS_FRIENDLY))
1507                TagUnitMap.push_back(pUnitTarget);
1508        }break;
1509        case TARGET_RANDOM_ENEMY_CHAIN_IN_AREA:
1510        {
1511            if(EffectChainTarget <= 1)
1512            {
1513                if(Unit* pUnitTarget = SearchNearbyTarget(radius, SPELL_TARGETS_AOE_DAMAGE))
1514                    TagUnitMap.push_back(pUnitTarget);
1515            }
1516            else
1517                SearchChainTarget(TagUnitMap, m_caster, radius, EffectChainTarget);
1518        }break;
1519        case TARGET_SCRIPT:
1520        case TARGET_SCRIPT_COORDINATES:
1521        {
1522            SpellScriptTarget::const_iterator lower = spellmgr.GetBeginSpellScriptTarget(m_spellInfo->Id);
1523            SpellScriptTarget::const_iterator upper = spellmgr.GetEndSpellScriptTarget(m_spellInfo->Id);
1524            if(lower==upper)
1525                sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_SCRIPT or TARGET_SCRIPT_COORDINATES, but does not have record in `spell_script_target`",m_spellInfo->Id);
1526
1527            SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
1528            float range = GetSpellMaxRange(srange);
1529
1530            Creature* creatureScriptTarget = NULL;
1531            GameObject* goScriptTarget = NULL;
1532
1533            for(SpellScriptTarget::const_iterator i_spellST = lower; i_spellST != upper; ++i_spellST)
1534            {
1535                switch(i_spellST->second.type)
1536                {
1537                case SPELL_TARGET_TYPE_GAMEOBJECT:
1538                    {
1539                        GameObject* p_GameObject = NULL;
1540
1541                        if(i_spellST->second.targetEntry)
1542                        {
1543                            CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
1544                            Cell cell(p);
1545                            cell.data.Part.reserved = ALL_DISTRICT;
1546
1547                            Trinity::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster,i_spellST->second.targetEntry,range);
1548                            Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck> checker(p_GameObject,go_check);
1549
1550                            TypeContainerVisitor<Trinity::GameObjectLastSearcher<Trinity::NearestGameObjectEntryInObjectRangeCheck>, GridTypeMapContainer > object_checker(checker);
1551                            CellLock<GridReadGuard> cell_lock(cell, p);
1552                            cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1553
1554                            if(p_GameObject)
1555                            {
1556                                // remember found target and range, next attempt will find more near target with another entry
1557                                creatureScriptTarget = NULL;
1558                                goScriptTarget = p_GameObject;
1559                                range = go_check.GetLastRange();
1560                            }
1561                        }
1562                        else if( focusObject )          //Focus Object
1563                        {
1564                            float frange = m_caster->GetDistance(focusObject);
1565                            if(range >= frange)
1566                            {
1567                                creatureScriptTarget = NULL;
1568                                goScriptTarget = focusObject;
1569                                range = frange;
1570                            }
1571                        }
1572                        break;
1573                    }
1574                case SPELL_TARGET_TYPE_CREATURE:
1575                case SPELL_TARGET_TYPE_DEAD:
1576                default:
1577                    {
1578                        Creature *p_Creature = NULL;
1579
1580                        CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
1581                        Cell cell(p);
1582                        cell.data.Part.reserved = ALL_DISTRICT;
1583                        cell.SetNoCreate();             // Really don't know what is that???
1584
1585                        Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster,i_spellST->second.targetEntry,i_spellST->second.type!=SPELL_TARGET_TYPE_DEAD,range);
1586                        Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(p_Creature, u_check);
1587
1588                        TypeContainerVisitor<Trinity::CreatureLastSearcher<Trinity::NearestCreatureEntryWithLiveStateInObjectRangeCheck>, GridTypeMapContainer >  grid_creature_searcher(searcher);
1589
1590                        CellLock<GridReadGuard> cell_lock(cell, p);
1591                        cell_lock->Visit(cell_lock, grid_creature_searcher, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1592
1593                        if(p_Creature )
1594                        {
1595                            creatureScriptTarget = p_Creature;
1596                            goScriptTarget = NULL;
1597                            range = u_check.GetLastRange();
1598                        }
1599                        break;
1600                    }
1601                }
1602            }
1603
1604            if(cur == TARGET_SCRIPT_COORDINATES)
1605            {
1606                if(creatureScriptTarget)
1607                    m_targets.setDestination(creatureScriptTarget->GetPositionX(),creatureScriptTarget->GetPositionY(),creatureScriptTarget->GetPositionZ());
1608                else if(goScriptTarget)
1609                    m_targets.setDestination(goScriptTarget->GetPositionX(),goScriptTarget->GetPositionY(),goScriptTarget->GetPositionZ());
1610            }
1611            else
1612            {
1613                if(creatureScriptTarget)
1614                    TagUnitMap.push_back(creatureScriptTarget);
1615                else if(goScriptTarget)
1616                    AddGOTarget(goScriptTarget, i);
1617            }
1618        }break;
1619
1620        // dummy
1621        case TARGET_AREAEFFECT_CUSTOM_2:
1622        {
1623            TagUnitMap.push_back(m_caster);
1624            break;
1625        }
1626
1627        case TARGET_ALL_PARTY_AROUND_CASTER:
1628        case TARGET_ALL_PARTY_AROUND_CASTER_2:
1629        case TARGET_ALL_PARTY:
1630        {
1631            Player *pTarget = m_caster->GetCharmerOrOwnerPlayerOrPlayerItself();
1632            Group *pGroup = pTarget ? pTarget->GetGroup() : NULL;
1633
1634            if(pGroup)
1635            {
1636                uint8 subgroup = pTarget->GetSubGroup();
1637
1638                for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
1639                {
1640                    Player* Target = itr->getSource();
1641
1642                    // IsHostileTo check duel and controlled by enemy
1643                    if( Target && Target->GetSubGroup()==subgroup && !m_caster->IsHostileTo(Target) )
1644                    {
1645                        if( m_caster->IsWithinDistInMap(Target, radius) )
1646                            TagUnitMap.push_back(Target);
1647
1648                        if(Pet* pet = Target->GetPet())
1649                            if( m_caster->IsWithinDistInMap(pet, radius) )
1650                                TagUnitMap.push_back(pet);
1651                    }
1652                }
1653            }
1654            else
1655            {
1656                Unit* ownerOrSelf = pTarget ? pTarget : m_caster->GetCharmerOrOwnerOrSelf();
1657                if(ownerOrSelf==m_caster || m_caster->IsWithinDistInMap(ownerOrSelf, radius))
1658                    TagUnitMap.push_back(ownerOrSelf);
1659                if(Pet* pet = ownerOrSelf->GetPet())
1660                    if( m_caster->IsWithinDistInMap(pet, radius) )
1661                        TagUnitMap.push_back(pet);
1662            }
1663        }break;
1664        case TARGET_RANDOM_RAID_MEMBER:
1665        {
1666            if (m_caster->GetTypeId() == TYPEID_PLAYER)
1667                if(Player* target = ((Player*)m_caster)->GetNextRandomRaidMember(radius))
1668                    TagUnitMap.push_back(target);
1669        }break;
1670        // TARGET_SINGLE_PARTY means that the spells can only be casted on a party member and not on the caster (some sceals, fire shield from imp, etc..)
1671        case TARGET_SINGLE_PARTY:
1672        {
1673            Unit *target = m_targets.getUnitTarget();
1674            // Thoses spells apparently can't be casted on the caster.
1675            if( target && target != m_caster)
1676            {
1677                // Can only be casted on group's members or its pets
1678                Group  *pGroup = NULL;
1679
1680                Unit* owner = m_caster->GetCharmerOrOwner();
1681                Unit *targetOwner = target->GetCharmerOrOwner();
1682                if(owner)
1683                {
1684                    if(owner->GetTypeId() == TYPEID_PLAYER)
1685                    {
1686                        if( target == owner )
1687                        {
1688                            TagUnitMap.push_back(target);
1689                            break;
1690                        }
1691                        pGroup = ((Player*)owner)->GetGroup();
1692                    }
1693                }
1694                else if (m_caster->GetTypeId() == TYPEID_PLAYER)
1695                {
1696                    if( targetOwner == m_caster && target->GetTypeId()==TYPEID_UNIT && ((Creature*)target)->isPet())
1697                    {
1698                        TagUnitMap.push_back(target);
1699                        break;
1700                    }
1701                    pGroup = ((Player*)m_caster)->GetGroup();
1702                }
1703
1704                if(pGroup)
1705                {
1706                    // Our target can also be a player's pet who's grouped with us or our pet. But can't be controlled player
1707                    if(targetOwner)
1708                    {
1709                        if( targetOwner->GetTypeId() == TYPEID_PLAYER &&
1710                            target->GetTypeId()==TYPEID_UNIT && (((Creature*)target)->isPet()) &&
1711                            target->GetOwnerGUID()==targetOwner->GetGUID() &&
1712                            pGroup->IsMember(((Player*)targetOwner)->GetGUID()))
1713                        {
1714                            TagUnitMap.push_back(target);
1715                        }
1716                    }
1717                    // 1Our target can be a player who is on our group
1718                    else if (target->GetTypeId() == TYPEID_PLAYER && pGroup->IsMember(((Player*)target)->GetGUID()))
1719                    {
1720                        TagUnitMap.push_back(target);
1721                    }
1722                }
1723            }
1724        }break;
1725        case TARGET_ALL_ENEMY_IN_AREA_CHANNELED:
1726        {
1727            // targets the ground, not the units in the area
1728            if (m_spellInfo->Effect[i]!=SPELL_EFFECT_PERSISTENT_AREA_AURA)
1729            {
1730                CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
1731                Cell cell(p);
1732                cell.data.Part.reserved = ALL_DISTRICT;
1733                cell.SetNoCreate();
1734
1735                Trinity::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, PUSH_DEST_CENTER,SPELL_TARGETS_AOE_DAMAGE);
1736
1737                TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
1738                TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer >  grid_object_notifier(notifier);
1739
1740                CellLock<GridReadGuard> cell_lock(cell, p);
1741                cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1742                cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1743            }
1744        }break;
1745        case TARGET_AREAEFFECT_PARTY:
1746        {
1747            Unit* owner = m_caster->GetCharmerOrOwner();
1748            Player *pTarget = NULL;
1749
1750            if(owner)
1751            {
1752                TagUnitMap.push_back(m_caster);
1753                if(owner->GetTypeId() == TYPEID_PLAYER)
1754                    pTarget = (Player*)owner;
1755            }
1756            else if (m_caster->GetTypeId() == TYPEID_PLAYER)
1757            {
1758                if(Unit* target = m_targets.getUnitTarget())
1759                {
1760                    if( target->GetTypeId() != TYPEID_PLAYER)
1761                    {
1762                        if(((Creature*)target)->isPet())
1763                        {
1764                            Unit *targetOwner = target->GetOwner();
1765                            if(targetOwner->GetTypeId() == TYPEID_PLAYER)
1766                                pTarget = (Player*)targetOwner;
1767                        }
1768                    }
1769                    else
1770                        pTarget = (Player*)target;
1771                }
1772            }
1773
1774            Group* pGroup = pTarget ? pTarget->GetGroup() : NULL;
1775
1776            if(pGroup)
1777            {
1778                uint8 subgroup = pTarget->GetSubGroup();
1779
1780                for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
1781                {
1782                    Player* Target = itr->getSource();
1783
1784                    // IsHostileTo check duel and controlled by enemy
1785                    if(Target && Target->GetSubGroup()==subgroup && !m_caster->IsHostileTo(Target))
1786                    {
1787                        if( pTarget->IsWithinDistInMap(Target, radius) )
1788                            TagUnitMap.push_back(Target);
1789
1790                        if(Pet* pet = Target->GetPet())
1791                            if( pTarget->IsWithinDistInMap(pet, radius) )
1792                                TagUnitMap.push_back(pet);
1793                    }
1794                }
1795            }
1796            else if (owner)
1797            {
1798                if(m_caster->IsWithinDistInMap(owner, radius))
1799                    TagUnitMap.push_back(owner);
1800            }
1801            else if(pTarget)
1802            {
1803                TagUnitMap.push_back(pTarget);
1804
1805                if(Pet* pet = pTarget->GetPet())
1806                    if( m_caster->IsWithinDistInMap(pet, radius) )
1807                        TagUnitMap.push_back(pet);
1808            }
1809
1810        }break;
1811        case TARGET_CHAIN_HEAL:
1812        {
1813            Unit* pUnitTarget = m_targets.getUnitTarget();
1814            if(!pUnitTarget)
1815                break;
1816
1817            if (EffectChainTarget <= 1)
1818                TagUnitMap.push_back(pUnitTarget);
1819            else
1820            {
1821                unMaxTargets = EffectChainTarget;
1822                float max_range = radius + unMaxTargets * CHAIN_SPELL_JUMP_RADIUS;
1823
1824                std::list<Unit *> tempUnitMap;
1825
1826                {
1827                    CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
1828                    Cell cell(p);
1829                    cell.data.Part.reserved = ALL_DISTRICT;
1830                    cell.SetNoCreate();
1831
1832                    Trinity::SpellNotifierCreatureAndPlayer notifier(*this, tempUnitMap, max_range, PUSH_SELF_CENTER, SPELL_TARGETS_FRIENDLY);
1833
1834                    TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, WorldTypeMapContainer > world_object_notifier(notifier);
1835                    TypeContainerVisitor<Trinity::SpellNotifierCreatureAndPlayer, GridTypeMapContainer >  grid_object_notifier(notifier);
1836
1837                    CellLock<GridReadGuard> cell_lock(cell, p);
1838                    cell_lock->Visit(cell_lock, world_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1839                    cell_lock->Visit(cell_lock, grid_object_notifier, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
1840
1841                }
1842
1843                if(m_caster != pUnitTarget && std::find(tempUnitMap.begin(),tempUnitMap.end(),m_caster) == tempUnitMap.end() )
1844                    tempUnitMap.push_front(m_caster);
1845
1846                tempUnitMap.sort(TargetDistanceOrder(pUnitTarget));
1847
1848                if(tempUnitMap.empty())
1849                    break;
1850
1851                if(*tempUnitMap.begin() == pUnitTarget)
1852                    tempUnitMap.erase(tempUnitMap.begin());
1853
1854                TagUnitMap.push_back(pUnitTarget);
1855                uint32 t = unMaxTargets - 1;
1856                Unit *prev = pUnitTarget;
1857                std::list<Unit*>::iterator next = tempUnitMap.begin();
1858
1859                while(t && next != tempUnitMap.end() )
1860                {
1861                    if(prev->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
1862                        break;
1863
1864                    if(!prev->IsWithinLOSInMap(*next))
1865                    {
1866                        ++next;
1867                        continue;
1868                    }
1869
1870                    if((*next)->GetHealth() == (*next)->GetMaxHealth())
1871                    {
1872                        next = tempUnitMap.erase(next);
1873                        continue;
1874                    }
1875
1876                    prev = *next;
1877                    TagUnitMap.push_back(prev);
1878                    tempUnitMap.erase(next);
1879                    tempUnitMap.sort(TargetDistanceOrder(prev));
1880                    next = tempUnitMap.begin();
1881
1882                    --t;
1883                }
1884            }
1885        }break;
1886        case TARGET_AREAEFFECT_PARTY_AND_CLASS:
1887        {
1888            Player* targetPlayer = m_targets.getUnitTarget() && m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER
1889                ? (Player*)m_targets.getUnitTarget() : NULL;
1890
1891            Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL;
1892            if(pGroup)
1893            {
1894                for(GroupReference *itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
1895                {
1896                    Player* Target = itr->getSource();
1897
1898                    // IsHostileTo check duel and controlled by enemy
1899                    if( Target && targetPlayer->IsWithinDistInMap(Target, radius) &&
1900                        targetPlayer->getClass() == Target->getClass() &&
1901                        !m_caster->IsHostileTo(Target) )
1902                    {
1903                        TagUnitMap.push_back(Target);
1904                    }
1905                }
1906            }
1907            else if(m_targets.getUnitTarget())
1908                TagUnitMap.push_back(m_targets.getUnitTarget());
1909            break;
1910        }
1911
1912        // destination around caster
1913        case TARGET_DEST_CASTER_FRONT_LEFT:
1914        case TARGET_DEST_CASTER_BACK_LEFT:
1915        case TARGET_DEST_CASTER_BACK_RIGHT:
1916        case TARGET_DEST_CASTER_FRONT_RIGHT:
1917        case TARGET_DEST_CASTER_FRONT:
1918        case TARGET_MINION:
1919        case TARGET_DEST_CASTER_FRONT_LEAP:
1920        case TARGET_DEST_CASTER_FRONT_UNKNOWN:
1921        case TARGET_DEST_CASTER_BACK:
1922        case TARGET_DEST_CASTER_RIGHT:
1923        case TARGET_DEST_CASTER_LEFT:
1924        case TARGET_DEST_CASTER_RANDOM:
1925        case TARGET_DEST_CASTER_RADIUS:
1926        {
1927            float x, y, z, angle, dist;
1928
1929            if (m_spellInfo->EffectRadiusIndex[i])
1930                dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
1931            else
1932                dist = 3.0f;//do we need this?
1933            if (cur == TARGET_DEST_CASTER_RANDOM)
1934                dist *= rand_norm(); // This case we need to consider caster size
1935            else
1936                dist -= m_caster->GetObjectSize(); // Size is calculated in GetNearPoint(), but we do not need it
1937            //need a new function to remove this repeated work
1938
1939            switch(cur)
1940            {
1941                case TARGET_DEST_CASTER_FRONT_LEFT: angle = -M_PI/4;    break;
1942                case TARGET_DEST_CASTER_BACK_LEFT:  angle = -3*M_PI/4;  break;
1943                case TARGET_DEST_CASTER_BACK_RIGHT: angle = 3*M_PI/4;   break;
1944                case TARGET_DEST_CASTER_FRONT_RIGHT:angle = M_PI/4;     break;
1945                case TARGET_MINION:
1946                case TARGET_DEST_CASTER_FRONT_LEAP:
1947                case TARGET_DEST_CASTER_FRONT_UNKNOWN:
1948                case TARGET_DEST_CASTER_FRONT:      angle = 0.0f;       break;
1949                case TARGET_DEST_CASTER_BACK:       angle = M_PI;       break;
1950                case TARGET_DEST_CASTER_RIGHT:      angle = M_PI/2;     break;
1951                case TARGET_DEST_CASTER_LEFT:       angle = -M_PI/2;    break;
1952                default:                            angle = rand_norm()*2*M_PI; break;
1953            }
1954
1955            m_caster->GetClosePoint(x, y, z, 0, dist, angle);
1956            m_targets.setDestination(x, y, z); // do not know if has ground visual
1957        }break;
1958
1959        // destination around target
1960        case TARGET_DEST_TARGET_FRONT:
1961        case TARGET_DEST_TARGET_BACK:
1962        case TARGET_DEST_TARGET_RIGHT:
1963        case TARGET_DEST_TARGET_LEFT:
1964        case TARGET_DEST_TARGET_RANDOM:
1965        case TARGET_DEST_TARGET_RADIUS:
1966        {
1967            Unit *target = m_targets.getUnitTarget();
1968            if(!target)
1969            {
1970                sLog.outError("SPELL: no unit target for spell ID %u\n", m_spellInfo->Id);
1971                break;
1972            }
1973
1974            float x, y, z, angle, dist;
1975
1976            if (m_spellInfo->EffectRadiusIndex[i])
1977                dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
1978            else
1979                dist = 3.0f;//do we need this?
1980            if (cur == TARGET_DEST_TARGET_RANDOM)
1981                dist *= rand_norm(); // This case we need to consider caster size
1982            else
1983                dist -= target->GetObjectSize(); // Size is calculated in GetNearPoint(), but we do not need it
1984            //need a new function to remove this repeated work
1985
1986            switch(cur)
1987            {
1988                case TARGET_DEST_TARGET_FRONT:      angle = 0.0f;       break;
1989                case TARGET_DEST_TARGET_BACK:       angle = M_PI;       break;
1990                case TARGET_DEST_TARGET_RIGHT:      angle = M_PI/2;     break;
1991                case TARGET_DEST_TARGET_LEFT:       angle = -M_PI/2;    break;
1992                default:                            angle = rand_norm()*2*M_PI; break;
1993            }
1994
1995            target->GetClosePoint(x, y, z, 0, dist, angle);
1996            m_targets.setDestination(x, y, z); // do not know if has ground visual
1997        }break;
1998
1999        // destination around destination
2000        case TARGET_DEST_DEST_RANDOM:
2001        {
2002            if(!(m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION))
2003            {
2004                sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id);
2005                break;
2006            }
2007            float x, y, z, dist, px, py, pz;
2008            dist = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
2009            x = m_targets.m_destX;
2010            y = m_targets.m_destY;
2011            z = m_targets.m_destZ;
2012            m_caster->GetRandomPoint(x, y, z, dist, px, py, pz);
2013            m_targets.setDestination(px, py, pz);
2014        }break;
2015        case TARGET_SELF2:
2016            m_targets.m_hasDest = true;
2017            break;
2018        default:
2019            break;
2020    }
2021
2022    if (unMaxTargets && TagUnitMap.size() > unMaxTargets)
2023    {
2024        // make sure one unit is always removed per iteration
2025        uint32 removed_utarget = 0;
2026        for (std::list<Unit*>::iterator itr = TagUnitMap.begin(), next; itr != TagUnitMap.end(); itr = next)
2027        {
2028            next = itr;
2029            ++next;
2030            if (!*itr) continue;
2031            if ((*itr) == m_targets.getUnitTarget())
2032            {
2033                TagUnitMap.erase(itr);
2034                removed_utarget = 1;
2035                //        break;
2036            }
2037        }
2038        // remove random units from the map
2039        while (TagUnitMap.size() > unMaxTargets - removed_utarget)
2040        {
2041            uint32 poz = urand(0, TagUnitMap.size()-1);
2042            for (std::list<Unit*>::iterator itr = TagUnitMap.begin(); itr != TagUnitMap.end(); ++itr, --poz)
2043            {
2044                if (!*itr) continue;
2045                if (!poz)
2046                {
2047                    TagUnitMap.erase(itr);
2048                    break;
2049                }
2050            }
2051        }
2052        // the player's target will always be added to the map
2053        if (removed_utarget && m_targets.getUnitTarget())
2054            TagUnitMap.push_back(m_targets.getUnitTarget());
2055    }
2056}
2057
2058void Spell::prepare(SpellCastTargets * targets, Aura* triggeredByAura)
2059{
2060    m_targets = *targets;
2061
2062    m_spellState = SPELL_STATE_PREPARING;
2063
2064    m_caster->GetPosition(m_castPositionX, m_castPositionY, m_castPositionZ);
2065    m_castOrientation = m_caster->GetOrientation();
2066
2067    if(triggeredByAura)
2068        m_triggeredByAuraSpell  = triggeredByAura->GetSpellProto();
2069
2070    // create and add update event for this spell
2071    SpellEvent* Event = new SpellEvent(this);
2072    m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1));
2073
2074    //Prevent casting at cast another spell (ServerSide check)
2075    if(m_caster->IsNonMeleeSpellCasted(false, true) && m_cast_count)
2076    {
2077        SendCastResult(SPELL_FAILED_SPELL_IN_PROGRESS);
2078        finish(false);
2079        return;
2080    }
2081
2082    if(m_caster->GetTypeId() == TYPEID_PLAYER || (m_caster->GetTypeId() == TYPEID_UNIT && ((Creature*)m_caster)->isPet()))
2083    {
2084        if(objmgr.IsPlayerSpellDisabled(m_spellInfo->Id))
2085        {
2086            SendCastResult(SPELL_FAILED_SPELL_UNAVAILABLE);
2087            finish(false);
2088            return;
2089        }
2090    }
2091    else
2092    {
2093        if(objmgr.IsCreatureSpellDisabled(m_spellInfo->Id))
2094        {
2095            finish(false);
2096            return;
2097        }
2098    }
2099
2100    // Fill cost data
2101    m_powerCost = CalculatePowerCost();
2102
2103    uint8 result = CanCast(true);
2104    if(result != 0 && !IsAutoRepeat())                      //always cast autorepeat dummy for triggering
2105    {
2106        if(triggeredByAura)
2107        {
2108            SendChannelUpdate(0);
2109            triggeredByAura->SetAuraDuration(0);
2110        }
2111        SendCastResult(result);
2112        finish(false);
2113        return;
2114    }
2115
2116    // calculate cast time (calculated after first CanCast check to prevent charge counting for first CanCast fail)
2117    m_casttime = GetSpellCastTime(m_spellInfo, this);
2118
2119    // set timer base at cast time
2120    ReSetTimer();
2121
2122    // stealth must be removed at cast starting (at show channel bar)
2123    // skip triggered spell (item equip spell casting and other not explicit character casts/item uses)
2124    if ( !m_IsTriggeredSpell && isSpellBreakStealth(m_spellInfo) )
2125    {
2126        m_caster->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
2127        m_caster->RemoveSpellsCausingAura(SPELL_AURA_FEIGN_DEATH);
2128    }
2129
2130    if(m_IsTriggeredSpell)
2131        cast(true);
2132    else
2133    {
2134        m_caster->SetCurrentCastedSpell( this );
2135        m_selfContainer = &(m_caster->m_currentSpells[GetCurrentContainer()]);
2136        SendSpellStart();
2137    }
2138}
2139
2140void Spell::cancel()
2141{
2142    if(m_spellState == SPELL_STATE_FINISHED)
2143        return;
2144
2145    m_autoRepeat = false;
2146    switch (m_spellState)
2147    {
2148        case SPELL_STATE_PREPARING:
2149        case SPELL_STATE_DELAYED:
2150        {
2151            SendInterrupted(0);
2152            SendCastResult(SPELL_FAILED_INTERRUPTED);
2153        } break;
2154
2155        case SPELL_STATE_CASTING:
2156        {
2157            for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
2158            {
2159                if( ihit->missCondition == SPELL_MISS_NONE )
2160                {
2161                    Unit* unit = m_caster->GetGUID()==(*ihit).targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
2162                    if( unit && unit->isAlive() )
2163                        unit->RemoveAurasDueToSpell(m_spellInfo->Id);
2164                }
2165            }
2166
2167            m_caster->RemoveAurasDueToSpell(m_spellInfo->Id);
2168            SendChannelUpdate(0);
2169            SendInterrupted(0);
2170            SendCastResult(SPELL_FAILED_INTERRUPTED);
2171        } break;
2172
2173        default:
2174        {
2175        } break;
2176    }
2177
2178    finish(false);
2179    m_caster->RemoveDynObject(m_spellInfo->Id);
2180    m_caster->RemoveGameObject(m_spellInfo->Id,true);
2181}
2182
2183void Spell::cast(bool skipCheck)
2184{
2185    uint8 castResult = 0;
2186
2187    // update pointers base at GUIDs to prevent access to non-existed already object
2188    UpdatePointers();
2189
2190    // cancel at lost main target unit
2191    if(!m_targets.getUnitTarget() && m_targets.getUnitTargetGUID() && m_targets.getUnitTargetGUID() != m_caster->GetGUID())
2192    {
2193        cancel();
2194        return;
2195    }
2196
2197    if(m_caster->GetTypeId() != TYPEID_PLAYER && m_targets.getUnitTarget() && m_targets.getUnitTarget() != m_caster)
2198        m_caster->SetInFront(m_targets.getUnitTarget());
2199
2200    castResult = CheckPower();
2201    if(castResult != 0)
2202    {
2203        SendCastResult(castResult);
2204        finish(false);
2205        return;
2206    }
2207
2208    // triggered cast called from Spell::prepare where it was already checked
2209    if(!skipCheck)
2210    {
2211        castResult = CanCast(false);
2212        if(castResult != 0)
2213        {
2214            SendCastResult(castResult);
2215            finish(false);
2216            return;
2217        }
2218    }
2219
2220    FillTargetMap();
2221
2222    // who did this hack?
2223    // Conflagrate - consumes immolate
2224    if ((m_spellInfo->TargetAuraState == AURA_STATE_IMMOLATE) && m_targets.getUnitTarget())
2225    {
2226        // for caster applied auras only
2227        Unit::AuraList const &mPeriodic = m_targets.getUnitTarget()->GetAurasByType(SPELL_AURA_PERIODIC_DAMAGE);
2228        for(Unit::AuraList::const_iterator i = mPeriodic.begin(); i != mPeriodic.end(); ++i)
2229        {
2230            if( (*i)->GetSpellProto()->SpellFamilyName == SPELLFAMILY_WARLOCK && ((*i)->GetSpellProto()->SpellFamilyFlags & 4) &&
2231                (*i)->GetCasterGUID()==m_caster->GetGUID() )
2232            {
2233                m_targets.getUnitTarget()->RemoveAura((*i)->GetId(), (*i)->GetEffIndex());
2234                break;
2235            }
2236        }
2237    }
2238
2239    if(int32 spell_triggered = spellmgr.GetSpellLinked(m_spellInfo->Id, 0))
2240    {
2241        if(spell_triggered > 0)
2242            m_caster->CastSpell(m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster, spell_triggered, true);
2243        else
2244            m_caster->RemoveAurasDueToSpell(-spell_triggered);
2245    }
2246
2247    // traded items have trade slot instead of guid in m_itemTargetGUID
2248    // set to real guid to be sent later to the client
2249    m_targets.updateTradeSlotItem();
2250
2251    // CAST SPELL
2252    SendSpellCooldown();
2253
2254    TakePower();
2255    TakeReagents();                                         // we must remove reagents before HandleEffects to allow place crafted item in same slot
2256
2257    if(m_spellState == SPELL_STATE_FINISHED)                // stop cast if spell marked as finish somewhere in Take*/FillTargetMap
2258        return;
2259
2260    SendCastResult(castResult);
2261    SendSpellGo();                                          // we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()...
2262
2263    // Pass cast spell event to handler (not send triggered by aura spells)
2264    if (m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_MELEE && m_spellInfo->DmgClass != SPELL_DAMAGE_CLASS_RANGED && !m_triggeredByAuraSpell)
2265    {
2266        m_caster->ProcDamageAndSpell(m_targets.getUnitTarget(), PROC_FLAG_CAST_SPELL, PROC_FLAG_NONE, 0, SPELL_SCHOOL_MASK_NONE, m_spellInfo, m_IsTriggeredSpell);
2267
2268        // update pointers base at GUIDs to prevent access to non-existed already object
2269        UpdatePointers();                                   // pointers can be invalidate at triggered spell casting
2270    }
2271
2272    // Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
2273    if (m_spellInfo->speed > 0.0f)
2274    {
2275
2276        // Remove used for cast item if need (it can be already NULL after TakeReagents call
2277        // in case delayed spell remove item at cast delay start
2278        TakeCastItem();
2279
2280        // Okay, maps created, now prepare flags
2281        m_immediateHandled = false;
2282        m_spellState = SPELL_STATE_DELAYED;
2283        SetDelayStart(0);
2284    }
2285    else
2286    {
2287        // Immediate spell, no big deal
2288        handle_immediate();
2289    }
2290}
2291
2292void Spell::handle_immediate()
2293{
2294    // start channeling if applicable
2295    if(IsChanneledSpell(m_spellInfo))
2296    {
2297        m_spellState = SPELL_STATE_CASTING;
2298        SendChannelStart(GetSpellDuration(m_spellInfo));
2299    }
2300
2301    // process immediate effects (items, ground, etc.) also initialize some variables
2302    _handle_immediate_phase();
2303
2304    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
2305        DoAllEffectOnTarget(&(*ihit));
2306
2307    for(std::list<GOTargetInfo>::iterator ihit= m_UniqueGOTargetInfo.begin();ihit != m_UniqueGOTargetInfo.end();++ihit)
2308        DoAllEffectOnTarget(&(*ihit));
2309
2310    // spell is finished, perform some last features of the spell here
2311    _handle_finish_phase();
2312
2313    // Remove used for cast item if need (it can be already NULL after TakeReagents call
2314    TakeCastItem();
2315
2316    if(m_spellState != SPELL_STATE_CASTING)
2317        finish(true);                                       // successfully finish spell cast (not last in case autorepeat or channel spell)
2318}
2319
2320uint64 Spell::handle_delayed(uint64 t_offset)
2321{
2322    uint64 next_time = 0;
2323
2324    if (!m_immediateHandled)
2325    {
2326        _handle_immediate_phase();
2327        m_immediateHandled = true;
2328    }
2329
2330    // now recheck units targeting correctness (need before any effects apply to prevent adding immunity at first effect not allow apply second spell effect and similar cases)
2331    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();++ihit)
2332    {
2333        if (ihit->processed == false)
2334        {
2335            if ( ihit->timeDelay <= t_offset )
2336                DoAllEffectOnTarget(&(*ihit));
2337            else if( next_time == 0 || ihit->timeDelay < next_time )
2338                next_time = ihit->timeDelay;
2339        }
2340    }
2341
2342    // now recheck gameobject targeting correctness
2343    for(std::list<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end();++ighit)
2344    {
2345        if (ighit->processed == false)
2346        {
2347            if ( ighit->timeDelay <= t_offset )
2348                DoAllEffectOnTarget(&(*ighit));
2349            else if( next_time == 0 || ighit->timeDelay < next_time )
2350                next_time = ighit->timeDelay;
2351        }
2352    }
2353    // All targets passed - need finish phase
2354    if (next_time == 0)
2355    {
2356        // spell is finished, perform some last features of the spell here
2357        _handle_finish_phase();
2358
2359        finish(true);                                       // successfully finish spell cast
2360
2361        // return zero, spell is finished now
2362        return 0;
2363    }
2364    else
2365    {
2366        // spell is unfinished, return next execution time
2367        return next_time;
2368    }
2369}
2370
2371void Spell::_handle_immediate_phase()
2372{
2373    // handle some immediate features of the spell here
2374    HandleThreatSpells(m_spellInfo->Id);
2375
2376    m_needSpellLog = IsNeedSendToClient();
2377    for(uint32 j = 0;j<3;j++)
2378    {
2379        if(m_spellInfo->Effect[j]==0)
2380            continue;
2381
2382        // apply Send Event effect to ground in case empty target lists
2383        if( m_spellInfo->Effect[j] == SPELL_EFFECT_SEND_EVENT && !HaveTargetsForEffect(j) )
2384        {
2385            HandleEffects(NULL,NULL,NULL, j);
2386            continue;
2387        }
2388
2389        // Don't do spell log, if is school damage spell
2390        if(m_spellInfo->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE || m_spellInfo->Effect[j] == 0)
2391            m_needSpellLog = false;
2392
2393        uint32 EffectChainTarget = m_spellInfo->EffectChainTarget[j];
2394        if(m_originalCaster)
2395            if(Player* modOwner = m_originalCaster->GetSpellModOwner())
2396                modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, EffectChainTarget, this);
2397
2398        // initialize multipliers
2399        m_damageMultipliers[j] = 1.0f;
2400        if( (m_spellInfo->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[j] == TARGET_CHAIN_HEAL) &&
2401            (EffectChainTarget > 1) )
2402            m_applyMultiplierMask |= 1 << j;
2403    }
2404
2405    // initialize Diminishing Returns Data
2406    m_diminishLevel = DIMINISHING_LEVEL_1;
2407    m_diminishGroup = DIMINISHING_NONE;
2408
2409    // process items
2410    for(std::list<ItemTargetInfo>::iterator ihit= m_UniqueItemInfo.begin();ihit != m_UniqueItemInfo.end();++ihit)
2411        DoAllEffectOnTarget(&(*ihit));
2412
2413    // process ground
2414    for(uint32 j = 0;j<3;j++)
2415    {
2416        // persistent area auras target only the ground
2417        if(m_spellInfo->Effect[j] == SPELL_EFFECT_PERSISTENT_AREA_AURA)
2418            HandleEffects(NULL,NULL,NULL, j);
2419    }
2420}
2421
2422void Spell::_handle_finish_phase()
2423{
2424    // spell log
2425    if(m_needSpellLog)
2426        SendLogExecute();
2427}
2428
2429void Spell::SendSpellCooldown()
2430{
2431    if(m_caster->GetTypeId() != TYPEID_PLAYER)
2432        return;
2433
2434    Player* _player = (Player*)m_caster;
2435    // Add cooldown for max (disable spell)
2436    // Cooldown started on SendCooldownEvent call
2437    if (m_spellInfo->Attributes & SPELL_ATTR_DISABLED_WHILE_ACTIVE)
2438    {
2439        _player->AddSpellCooldown(m_spellInfo->Id, 0, time(NULL) - 1);
2440        return;
2441    }
2442
2443    // init cooldown values
2444    uint32 cat   = 0;
2445    int32 rec    = -1;
2446    int32 catrec = -1;
2447
2448    // some special item spells without correct cooldown in SpellInfo
2449    // cooldown information stored in item prototype
2450    // This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client.
2451
2452    if(m_CastItem)
2453    {
2454        ItemPrototype const* proto = m_CastItem->GetProto();
2455        if(proto)
2456        {
2457            for(int idx = 0; idx < 5; ++idx)
2458            {
2459                if(proto->Spells[idx].SpellId == m_spellInfo->Id)
2460                {
2461                    cat    = proto->Spells[idx].SpellCategory;
2462                    rec    = proto->Spells[idx].SpellCooldown;
2463                    catrec = proto->Spells[idx].SpellCategoryCooldown;
2464                    break;
2465                }
2466            }
2467        }
2468    }
2469
2470    // if no cooldown found above then base at DBC data
2471    if(rec < 0 && catrec < 0)
2472    {
2473        cat = m_spellInfo->Category;
2474        rec = m_spellInfo->RecoveryTime;
2475        catrec = m_spellInfo->CategoryRecoveryTime;
2476    }
2477
2478    // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK)
2479    // prevent 0 cooldowns set by another way
2480    if (rec <= 0 && catrec <= 0 && (cat == 76 || cat == 351))
2481        rec = _player->GetAttackTime(RANGED_ATTACK);
2482
2483    // Now we have cooldown data (if found any), time to apply mods
2484    if(rec > 0)
2485        _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, rec, this);
2486
2487    if(catrec > 0)
2488        _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, catrec, this);
2489
2490    // replace negative cooldowns by 0
2491    if (rec < 0) rec = 0;
2492    if (catrec < 0) catrec = 0;
2493
2494    // no cooldown after applying spell mods
2495    if( rec == 0 && catrec == 0)
2496        return;
2497
2498    time_t curTime = time(NULL);
2499
2500    time_t catrecTime = catrec ? curTime+catrec/1000 : 0;   // in secs
2501    time_t recTime    = rec ? curTime+rec/1000 : catrecTime;// in secs
2502
2503    // self spell cooldown
2504    if(recTime > 0)
2505        _player->AddSpellCooldown(m_spellInfo->Id, m_CastItem ? m_CastItem->GetEntry() : 0, recTime);
2506
2507    // category spells
2508    if (catrec > 0)
2509    {
2510        SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat);
2511        if(i_scstore != sSpellCategoryStore.end())
2512        {
2513            for(SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset)
2514            {
2515                if(*i_scset == m_spellInfo->Id)             // skip main spell, already handled above
2516                    continue;
2517
2518                _player->AddSpellCooldown(m_spellInfo->Id, m_CastItem ? m_CastItem->GetEntry() : 0, catrecTime);
2519            }
2520        }
2521    }
2522}
2523
2524void Spell::update(uint32 difftime)
2525{
2526    // update pointers based at it's GUIDs
2527    UpdatePointers();
2528
2529    if(m_targets.getUnitTargetGUID() && !m_targets.getUnitTarget())
2530    {
2531        cancel();
2532        return;
2533    }
2534
2535    // check if the player caster has moved before the spell finished
2536    if ((m_caster->GetTypeId() == TYPEID_PLAYER && m_timer != 0) &&
2537        (m_castPositionX != m_caster->GetPositionX() || m_castPositionY != m_caster->GetPositionY() || m_castPositionZ != m_caster->GetPositionZ()) &&
2538        (m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING)))
2539    {
2540        // always cancel for channeled spells
2541        if( m_spellState == SPELL_STATE_CASTING )
2542            cancel();
2543        // don't cancel for melee, autorepeat, triggered and instant spells
2544        else if(!IsNextMeleeSwingSpell() && !IsAutoRepeat() && !m_IsTriggeredSpell && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT))
2545            cancel();
2546    }
2547
2548    switch(m_spellState)
2549    {
2550        case SPELL_STATE_PREPARING:
2551        {
2552            if(m_timer)
2553            {
2554                if(difftime >= m_timer)
2555                    m_timer = 0;
2556                else
2557                    m_timer -= difftime;
2558            }
2559
2560            if(m_timer == 0 && !IsNextMeleeSwingSpell() && !IsAutoRepeat())
2561                cast();
2562        } break;
2563        case SPELL_STATE_CASTING:
2564        {
2565            if(m_timer > 0)
2566            {
2567                if( m_caster->GetTypeId() == TYPEID_PLAYER )
2568                {
2569                    // check if player has jumped before the channeling finished
2570                    if(m_caster->HasUnitMovementFlag(MOVEMENTFLAG_JUMPING))
2571                        cancel();
2572
2573                    // check for incapacitating player states
2574                    if( m_caster->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_CONFUSED))
2575                        cancel();
2576
2577                    // check if player has turned if flag is set
2578                    if( m_spellInfo->ChannelInterruptFlags & CHANNEL_FLAG_TURNING && m_castOrientation != m_caster->GetOrientation() )
2579                        cancel();
2580                }
2581
2582                // check if there are alive targets left
2583                if (!IsAliveUnitPresentInTargetList())
2584                {
2585                    SendChannelUpdate(0);
2586                    finish();
2587                }
2588
2589                if(difftime >= m_timer)
2590                    m_timer = 0;
2591                else
2592                    m_timer -= difftime;
2593            }
2594
2595            if(m_timer == 0)
2596            {
2597                SendChannelUpdate(0);
2598
2599                // channeled spell processed independently for quest targeting
2600                // cast at creature (or GO) quest objectives update at successful cast channel finished
2601                // ignore autorepeat/melee casts for speed (not exist quest for spells (hm... )
2602                if( m_caster->GetTypeId() == TYPEID_PLAYER && !IsAutoRepeat() && !IsNextMeleeSwingSpell() )
2603                {
2604                    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
2605                    {
2606                        TargetInfo* target = &*ihit;
2607                        if(!IS_CREATURE_GUID(target->targetGUID))
2608                            continue;
2609
2610                        Unit* unit = m_caster->GetGUID()==target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster,target->targetGUID);
2611                        if (unit==NULL)
2612                            continue;
2613
2614                        ((Player*)m_caster)->CastedCreatureOrGO(unit->GetEntry(),unit->GetGUID(),m_spellInfo->Id);
2615                    }
2616
2617                    for(std::list<GOTargetInfo>::iterator ihit= m_UniqueGOTargetInfo.begin();ihit != m_UniqueGOTargetInfo.end();++ihit)
2618                    {
2619                        GOTargetInfo* target = &*ihit;
2620
2621                        GameObject* go = ObjectAccessor::GetGameObject(*m_caster, target->targetGUID);
2622                        if(!go)
2623                            continue;
2624
2625                        ((Player*)m_caster)->CastedCreatureOrGO(go->GetEntry(),go->GetGUID(),m_spellInfo->Id);
2626                    }
2627                }
2628
2629                finish();
2630            }
2631        } break;
2632        default:
2633        {
2634        }break;
2635    }
2636}
2637
2638void Spell::finish(bool ok)
2639{
2640    if(!m_caster)
2641        return;
2642
2643    if(m_spellState == SPELL_STATE_FINISHED)
2644        return;
2645
2646    m_spellState = SPELL_STATE_FINISHED;
2647
2648    //remove spell mods
2649    if (m_caster->GetTypeId() == TYPEID_PLAYER)
2650        ((Player*)m_caster)->RemoveSpellMods(this);
2651
2652    // other code related only to successfully finished spells
2653    if(!ok)
2654        return;
2655
2656    //handle SPELL_AURA_ADD_TARGET_TRIGGER auras
2657    Unit::AuraList const& targetTriggers = m_caster->GetAurasByType(SPELL_AURA_ADD_TARGET_TRIGGER);
2658    for(Unit::AuraList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i)
2659    {
2660        SpellEntry const *auraSpellInfo = (*i)->GetSpellProto();
2661        uint32 auraSpellIdx = (*i)->GetEffIndex();
2662        if (IsAffectedBy(auraSpellInfo, auraSpellIdx))
2663        {
2664            for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
2665                if( ihit->effectMask & (1<<auraSpellIdx) )
2666            {
2667                // check m_caster->GetGUID() let load auras at login and speedup most often case
2668                Unit *unit = m_caster->GetGUID()== ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
2669                if (unit && unit->isAlive())
2670                {
2671                    // Calculate chance at that moment (can be depend for example from combo points)
2672                    int32 chance = m_caster->CalculateSpellDamage(auraSpellInfo, auraSpellIdx, (*i)->GetBasePoints(),unit);
2673
2674                    if(roll_chance_i(chance))
2675                        m_caster->CastSpell(unit, auraSpellInfo->EffectTriggerSpell[auraSpellIdx], true, NULL, (*i));
2676                }
2677            }
2678        }
2679    }
2680
2681    if (IsMeleeAttackResetSpell())
2682    {
2683        m_caster->resetAttackTimer(BASE_ATTACK);
2684        if(m_caster->haveOffhandWeapon())
2685            m_caster->resetAttackTimer(OFF_ATTACK);
2686    }
2687
2688    /*if (IsRangedAttackResetSpell())
2689        m_caster->resetAttackTimer(RANGED_ATTACK);*/
2690
2691    // Clear combo at finish state
2692    if(m_caster->GetTypeId() == TYPEID_PLAYER && NeedsComboPoints(m_spellInfo))
2693        ((Player*)m_caster)->ClearComboPoints();
2694
2695    // call triggered spell only at successful cast (after clear combo points -> for add some if need)
2696    if(!m_TriggerSpells.empty())
2697        TriggerSpell();
2698
2699    // Stop Attack for some spells
2700    if( m_spellInfo->Attributes & SPELL_ATTR_STOP_ATTACK_TARGET )
2701        m_caster->AttackStop();
2702}
2703
2704void Spell::SendCastResult(uint8 result)
2705{
2706    if (m_caster->GetTypeId() != TYPEID_PLAYER)
2707        return;
2708
2709    if(((Player*)m_caster)->GetSession()->PlayerLoading())  // don't send cast results at loading time
2710        return;
2711
2712    if(result != 0)
2713    {
2714        WorldPacket data(SMSG_CAST_FAILED, (4+1+1));
2715        data << uint32(m_spellInfo->Id);
2716        data << uint8(result);                              // problem
2717        data << uint8(m_cast_count);                        // single cast or multi 2.3 (0/1)
2718        switch (result)
2719        {
2720            case SPELL_FAILED_REQUIRES_SPELL_FOCUS:
2721                data << uint32(m_spellInfo->RequiresSpellFocus);
2722                break;
2723            case SPELL_FAILED_REQUIRES_AREA:
2724                // hardcode areas limitation case
2725                if( m_spellInfo->Id==41618 || m_spellInfo->Id==41620 )
2726                    data << uint32(3842);
2727                else if( m_spellInfo->Id==41617 || m_spellInfo->Id==41619 )
2728                    data << uint32(3905);
2729                // normal case
2730                else
2731                    data << uint32(m_spellInfo->AreaId);
2732                break;
2733            case SPELL_FAILED_TOTEMS:
2734                if(m_spellInfo->Totem[0])
2735                    data << uint32(m_spellInfo->Totem[0]);
2736                if(m_spellInfo->Totem[1])
2737                    data << uint32(m_spellInfo->Totem[1]);
2738                break;
2739            case SPELL_FAILED_TOTEM_CATEGORY:
2740                if(m_spellInfo->TotemCategory[0])
2741                    data << uint32(m_spellInfo->TotemCategory[0]);
2742                if(m_spellInfo->TotemCategory[1])
2743                    data << uint32(m_spellInfo->TotemCategory[1]);
2744                break;
2745            case SPELL_FAILED_EQUIPPED_ITEM_CLASS:
2746                data << uint32(m_spellInfo->EquippedItemClass);
2747                data << uint32(m_spellInfo->EquippedItemSubClassMask);
2748                data << uint32(m_spellInfo->EquippedItemInventoryTypeMask);
2749                break;
2750        }
2751        ((Player*)m_caster)->GetSession()->SendPacket(&data);
2752    }
2753    else
2754    {
2755        WorldPacket data(SMSG_CLEAR_EXTRA_AURA_INFO, (8+4));
2756        data.append(m_caster->GetPackGUID());
2757        data << uint32(m_spellInfo->Id);
2758        ((Player*)m_caster)->GetSession()->SendPacket(&data);
2759    }
2760}
2761
2762void Spell::SendSpellStart()
2763{
2764    if(!IsNeedSendToClient())
2765        return;
2766
2767    sLog.outDebug("Sending SMSG_SPELL_START id=%u",m_spellInfo->Id);
2768
2769    uint16 castFlags = CAST_FLAG_UNKNOWN1;
2770    if(IsRangedSpell())
2771        castFlags |= CAST_FLAG_AMMO;
2772
2773    Unit * target;
2774    if(!m_targets.getUnitTarget())
2775        target = m_caster;
2776    else
2777        target = m_targets.getUnitTarget();
2778
2779    WorldPacket data(SMSG_SPELL_START, (8+8+4+4+2));
2780    if(m_CastItem)
2781        data.append(m_CastItem->GetPackGUID());
2782    else
2783        data.append(m_caster->GetPackGUID());
2784
2785    data.append(m_caster->GetPackGUID());
2786    data << uint32(m_spellInfo->Id);
2787    data << uint8(m_cast_count);                            // single cast or multi 2.3 (0/1)
2788    data << uint16(castFlags);
2789    data << uint32(m_timer);
2790
2791    m_targets.write(&data);
2792
2793    if( castFlags & CAST_FLAG_AMMO )
2794        WriteAmmoToPacket(&data);
2795
2796    m_caster->SendMessageToSet(&data, true);
2797}
2798
2799void Spell::SendSpellGo()
2800{
2801    // not send invisible spell casting
2802    if(!IsNeedSendToClient())
2803        return;
2804
2805    sLog.outDebug("Sending SMSG_SPELL_GO id=%u",m_spellInfo->Id);
2806
2807    Unit * target;
2808    if(!m_targets.getUnitTarget())
2809        target = m_caster;
2810    else
2811        target = m_targets.getUnitTarget();
2812
2813    uint16 castFlags = CAST_FLAG_UNKNOWN3;
2814    if(IsRangedSpell())
2815        castFlags |= CAST_FLAG_AMMO;
2816
2817    WorldPacket data(SMSG_SPELL_GO, 50);                    // guess size
2818    if(m_CastItem)
2819        data.append(m_CastItem->GetPackGUID());
2820    else
2821        data.append(m_caster->GetPackGUID());
2822
2823    data.append(m_caster->GetPackGUID());
2824    data << uint32(m_spellInfo->Id);
2825    data << uint16(castFlags);
2826    data << uint32(getMSTime());                            // timestamp
2827
2828    WriteSpellGoTargets(&data);
2829
2830    m_targets.write(&data);
2831
2832    if( castFlags & CAST_FLAG_AMMO )
2833        WriteAmmoToPacket(&data);
2834
2835    m_caster->SendMessageToSet(&data, true);
2836}
2837
2838void Spell::WriteAmmoToPacket( WorldPacket * data )
2839{
2840    uint32 ammoInventoryType = 0;
2841    uint32 ammoDisplayID = 0;
2842
2843    if (m_caster->GetTypeId() == TYPEID_PLAYER)
2844    {
2845        Item *pItem = ((Player*)m_caster)->GetWeaponForAttack( RANGED_ATTACK );
2846        if(pItem)
2847        {
2848            ammoInventoryType = pItem->GetProto()->InventoryType;
2849            if( ammoInventoryType == INVTYPE_THROWN )
2850                ammoDisplayID = pItem->GetProto()->DisplayInfoID;
2851            else
2852            {
2853                uint32 ammoID = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID);
2854                if(ammoID)
2855                {
2856                    ItemPrototype const *pProto = objmgr.GetItemPrototype( ammoID );
2857                    if(pProto)
2858                    {
2859                        ammoDisplayID = pProto->DisplayInfoID;
2860                        ammoInventoryType = pProto->InventoryType;
2861                    }
2862                }
2863                else if(m_caster->GetDummyAura(46699))      // Requires No Ammo
2864                {
2865                    ammoDisplayID = 5996;                   // normal arrow
2866                    ammoInventoryType = INVTYPE_AMMO;
2867                }
2868            }
2869        }
2870    }
2871    // TODO: implement selection ammo data based at ranged weapon stored in equipmodel/equipinfo/equipslot fields
2872
2873    *data << uint32(ammoDisplayID);
2874    *data << uint32(ammoInventoryType);
2875}
2876
2877void Spell::WriteSpellGoTargets( WorldPacket * data )
2878{
2879    *data << (uint8)m_countOfHit;
2880    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
2881        if ((*ihit).missCondition == SPELL_MISS_NONE)       // Add only hits
2882            *data << uint64(ihit->targetGUID);
2883
2884    for(std::list<GOTargetInfo>::iterator ighit= m_UniqueGOTargetInfo.begin();ighit != m_UniqueGOTargetInfo.end();++ighit)
2885        *data << uint64(ighit->targetGUID);                 // Always hits
2886
2887    *data << (uint8)m_countOfMiss;
2888    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
2889    {
2890        if( ihit->missCondition != SPELL_MISS_NONE )        // Add only miss
2891        {
2892            *data << uint64(ihit->targetGUID);
2893            *data << uint8(ihit->missCondition);
2894            if( ihit->missCondition == SPELL_MISS_REFLECT )
2895                *data << uint8(ihit->reflectResult);
2896        }
2897    }
2898}
2899
2900void Spell::SendLogExecute()
2901{
2902    Unit *target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster;
2903
2904    WorldPacket data(SMSG_SPELLLOGEXECUTE, (8+4+4+4+4+8));
2905
2906    if(m_caster->GetTypeId() == TYPEID_PLAYER)
2907        data.append(m_caster->GetPackGUID());
2908    else
2909        data.append(target->GetPackGUID());
2910
2911    data << uint32(m_spellInfo->Id);
2912    uint32 count1 = 1;
2913    data << uint32(count1);                                 // count1 (effect count?)
2914    for(uint32 i = 0; i < count1; ++i)
2915    {
2916        data << uint32(m_spellInfo->Effect[0]);             // spell effect?
2917        uint32 count2 = 1;
2918        data << uint32(count2);                             // count2 (target count?)
2919        for(uint32 j = 0; j < count2; ++j)
2920        {
2921            switch(m_spellInfo->Effect[0])
2922            {
2923                case SPELL_EFFECT_POWER_DRAIN:
2924                    if(Unit *unit = m_targets.getUnitTarget())
2925                        data.append(unit->GetPackGUID());
2926                    else
2927                        data << uint8(0);
2928                    data << uint32(0);
2929                    data << uint32(0);
2930                    data << float(0);
2931                    break;
2932                case SPELL_EFFECT_ADD_EXTRA_ATTACKS:
2933                    if(Unit *unit = m_targets.getUnitTarget())
2934                        data.append(unit->GetPackGUID());
2935                    else
2936                        data << uint8(0);
2937                    data << uint32(0);                      // count?
2938                    break;
2939                case SPELL_EFFECT_INTERRUPT_CAST:
2940                    if(Unit *unit = m_targets.getUnitTarget())
2941                        data.append(unit->GetPackGUID());
2942                    else
2943                        data << uint8(0);
2944                    data << uint32(0);                      // spellid
2945                    break;
2946                case SPELL_EFFECT_DURABILITY_DAMAGE:
2947                    if(Unit *unit = m_targets.getUnitTarget())
2948                        data.append(unit->GetPackGUID());
2949                    else
2950                        data << uint8(0);
2951                    data << uint32(0);
2952                    data << uint32(0);
2953                    break;
2954                case SPELL_EFFECT_OPEN_LOCK:
2955                case SPELL_EFFECT_OPEN_LOCK_ITEM:
2956                    if(Item *item = m_targets.getItemTarget())
2957                        data.append(item->GetPackGUID());
2958                    else
2959                        data << uint8(0);
2960                    break;
2961                case SPELL_EFFECT_CREATE_ITEM:
2962                    data << uint32(m_spellInfo->EffectItemType[0]);
2963                    break;
2964                case SPELL_EFFECT_SUMMON:
2965                case SPELL_EFFECT_SUMMON_WILD:
2966                case SPELL_EFFECT_SUMMON_GUARDIAN:
2967                case SPELL_EFFECT_TRANS_DOOR:
2968                case SPELL_EFFECT_SUMMON_PET:
2969                case SPELL_EFFECT_SUMMON_POSSESSED:
2970                case SPELL_EFFECT_SUMMON_TOTEM:
2971                case SPELL_EFFECT_SUMMON_OBJECT_WILD:
2972                case SPELL_EFFECT_CREATE_HOUSE:
2973                case SPELL_EFFECT_DUEL:
2974                case SPELL_EFFECT_SUMMON_TOTEM_SLOT1:
2975                case SPELL_EFFECT_SUMMON_TOTEM_SLOT2:
2976                case SPELL_EFFECT_SUMMON_TOTEM_SLOT3:
2977                case SPELL_EFFECT_SUMMON_TOTEM_SLOT4:
2978                case SPELL_EFFECT_SUMMON_PHANTASM:
2979                case SPELL_EFFECT_SUMMON_CRITTER:
2980                case SPELL_EFFECT_SUMMON_OBJECT_SLOT1:
2981                case SPELL_EFFECT_SUMMON_OBJECT_SLOT2:
2982                case SPELL_EFFECT_SUMMON_OBJECT_SLOT3:
2983                case SPELL_EFFECT_SUMMON_OBJECT_SLOT4:
2984                case SPELL_EFFECT_SUMMON_DEMON:
2985                case SPELL_EFFECT_150:
2986                    if(Unit *unit = m_targets.getUnitTarget())
2987                        data.append(unit->GetPackGUID());
2988                    else if(m_targets.getItemTargetGUID())
2989                        data.appendPackGUID(m_targets.getItemTargetGUID());
2990                    else if(GameObject *go = m_targets.getGOTarget())
2991                        data.append(go->GetPackGUID());
2992                    else
2993                        data << uint8(0);                   // guid
2994                    break;
2995                case SPELL_EFFECT_FEED_PET:
2996                    data << uint32(m_targets.getItemTargetEntry());
2997                    break;
2998                case SPELL_EFFECT_DISMISS_PET:
2999                    if(Unit *unit = m_targets.getUnitTarget())
3000                        data.append(unit->GetPackGUID());
3001                    else
3002                        data << uint8(0);
3003                    break;
3004                default:
3005                    return;
3006            }
3007        }
3008    }
3009
3010    m_caster->SendMessageToSet(&data, true);
3011}
3012
3013void Spell::SendInterrupted(uint8 result)
3014{
3015    WorldPacket data(SMSG_SPELL_FAILURE, (8+4+1));
3016    data.append(m_caster->GetPackGUID());
3017    data << m_spellInfo->Id;
3018    data << result;
3019    m_caster->SendMessageToSet(&data, true);
3020
3021    data.Initialize(SMSG_SPELL_FAILED_OTHER, (8+4));
3022    data.append(m_caster->GetPackGUID());
3023    data << m_spellInfo->Id;
3024    m_caster->SendMessageToSet(&data, true);
3025}
3026
3027void Spell::SendChannelUpdate(uint32 time)
3028{
3029    if(time == 0)
3030    {
3031        m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT,0);
3032        m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL,0);
3033    }
3034
3035    if (m_caster->GetTypeId() != TYPEID_PLAYER)
3036        return;
3037
3038    WorldPacket data( MSG_CHANNEL_UPDATE, 8+4 );
3039    data.append(m_caster->GetPackGUID());
3040    data << time;
3041
3042    ((Player*)m_caster)->GetSession()->SendPacket( &data );
3043}
3044
3045void Spell::SendChannelStart(uint32 duration)
3046{
3047    WorldObject* target = NULL;
3048
3049    // select first not rsusted target from target list for _0_ effect
3050    if(!m_UniqueTargetInfo.empty())
3051    {
3052        for(std::list<TargetInfo>::iterator itr= m_UniqueTargetInfo.begin();itr != m_UniqueTargetInfo.end();++itr)
3053        {
3054            if( (itr->effectMask & (1<<0)) && itr->reflectResult==SPELL_MISS_NONE && itr->targetGUID != m_caster->GetGUID())
3055            {
3056                target = ObjectAccessor::GetUnit(*m_caster, itr->targetGUID);
3057                break;
3058            }
3059        }
3060    }
3061    else if(!m_UniqueGOTargetInfo.empty())
3062    {
3063        for(std::list<GOTargetInfo>::iterator itr= m_UniqueGOTargetInfo.begin();itr != m_UniqueGOTargetInfo.end();++itr)
3064        {
3065            if(itr->effectMask & (1<<0) )
3066            {
3067                target = ObjectAccessor::GetGameObject(*m_caster, itr->targetGUID);
3068                break;
3069            }
3070        }
3071    }
3072
3073    if (m_caster->GetTypeId() == TYPEID_PLAYER)
3074    {
3075        WorldPacket data( MSG_CHANNEL_START, (8+4+4) );
3076        data.append(m_caster->GetPackGUID());
3077        data << m_spellInfo->Id;
3078        data << duration;
3079
3080        ((Player*)m_caster)->GetSession()->SendPacket( &data );
3081    }
3082
3083    m_timer = duration;
3084    if(target)
3085        m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, target->GetGUID());
3086    m_caster->SetUInt32Value(UNIT_CHANNEL_SPELL, m_spellInfo->Id);
3087}
3088
3089void Spell::SendResurrectRequest(Player* target)
3090{
3091    WorldPacket data(SMSG_RESURRECT_REQUEST, (8+4+2+4));
3092    data << m_caster->GetGUID();
3093    data << uint32(1) << uint16(0) << uint32(1);
3094
3095    target->GetSession()->SendPacket(&data);
3096}
3097
3098void Spell::SendPlaySpellVisual(uint32 SpellID)
3099{
3100    if (m_caster->GetTypeId() != TYPEID_PLAYER)
3101        return;
3102
3103    WorldPacket data(SMSG_PLAY_SPELL_VISUAL, 12);
3104    data << m_caster->GetGUID();
3105    data << SpellID;
3106    ((Player*)m_caster)->GetSession()->SendPacket(&data);
3107}
3108
3109void Spell::TakeCastItem()
3110{
3111    if(!m_CastItem || m_caster->GetTypeId() != TYPEID_PLAYER)
3112        return;
3113
3114    // not remove cast item at triggered spell (equipping, weapon damage, etc)
3115    if(m_IsTriggeredSpell)
3116        return;
3117
3118    ItemPrototype const *proto = m_CastItem->GetProto();
3119
3120    if(!proto)
3121    {
3122        // This code is to avoid a crash
3123        // I'm not sure, if this is really an error, but I guess every item needs a prototype
3124        sLog.outError("Cast item has no item prototype highId=%d, lowId=%d",m_CastItem->GetGUIDHigh(), m_CastItem->GetGUIDLow());
3125        return;
3126    }
3127
3128    bool expendable = false;
3129    bool withoutCharges = false;
3130
3131    for (int i = 0; i<5; i++)
3132    {
3133        if (proto->Spells[i].SpellId)
3134        {
3135            // item has limited charges
3136            if (proto->Spells[i].SpellCharges)
3137            {
3138                if (proto->Spells[i].SpellCharges < 0)
3139                    expendable = true;
3140
3141                int32 charges = m_CastItem->GetSpellCharges(i);
3142
3143                // item has charges left
3144                if (charges)
3145                {
3146                    (charges > 0) ? --charges : ++charges;  // abs(charges) less at 1 after use
3147                    if (proto->Stackable < 2)
3148                        m_CastItem->SetSpellCharges(i, charges);
3149                    m_CastItem->SetState(ITEM_CHANGED, (Player*)m_caster);
3150                }
3151
3152                // all charges used
3153                withoutCharges = (charges == 0);
3154            }
3155        }
3156    }
3157
3158    if (expendable && withoutCharges)
3159    {
3160        uint32 count = 1;
3161        ((Player*)m_caster)->DestroyItemCount(m_CastItem, count, true);
3162
3163        // prevent crash at access to deleted m_targets.getItemTarget
3164        if(m_CastItem==m_targets.getItemTarget())
3165            m_targets.setItemTarget(NULL);
3166
3167        m_CastItem = NULL;
3168    }
3169}
3170
3171void Spell::TakePower()
3172{
3173    if(m_CastItem || m_triggeredByAuraSpell)
3174        return;
3175
3176    // health as power used
3177    if(m_spellInfo->powerType == POWER_HEALTH)
3178    {
3179        m_caster->ModifyHealth( -(int32)m_powerCost );
3180        return;
3181    }
3182
3183    if(m_spellInfo->powerType >= MAX_POWERS)
3184    {
3185        sLog.outError("Spell::TakePower: Unknown power type '%d'", m_spellInfo->powerType);
3186        return;
3187    }
3188
3189    Powers powerType = Powers(m_spellInfo->powerType);
3190
3191    m_caster->ModifyPower(powerType, -(int32)m_powerCost);
3192
3193    // Set the five second timer
3194    if (powerType == POWER_MANA && m_powerCost > 0)
3195        m_caster->SetLastManaUse(getMSTime());
3196}
3197
3198void Spell::TakeReagents()
3199{
3200    if(m_IsTriggeredSpell)                                  // reagents used in triggered spell removed by original spell or don't must be removed.
3201        return;
3202
3203    if (m_caster->GetTypeId() != TYPEID_PLAYER)
3204        return;
3205
3206    if (m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP &&
3207        m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION))
3208        return;
3209
3210    Player* p_caster = (Player*)m_caster;
3211
3212    for(uint32 x=0;x<8;x++)
3213    {
3214        if(m_spellInfo->Reagent[x] <= 0)
3215            continue;
3216
3217        uint32 itemid = m_spellInfo->Reagent[x];
3218        uint32 itemcount = m_spellInfo->ReagentCount[x];
3219
3220        // if CastItem is also spell reagent
3221        if (m_CastItem)
3222        {
3223            ItemPrototype const *proto = m_CastItem->GetProto();
3224            if( proto && proto->ItemId == itemid )
3225            {
3226                for(int s=0;s<5;s++)
3227                {
3228                    // CastItem will be used up and does not count as reagent
3229                    int32 charges = m_CastItem->GetSpellCharges(s);
3230                    if (proto->Spells[s].SpellCharges < 0 && abs(charges) < 2)
3231                    {
3232                        ++itemcount;
3233                        break;
3234                    }
3235                }
3236
3237                m_CastItem = NULL;
3238            }
3239        }
3240
3241        // if getItemTarget is also spell reagent
3242        if (m_targets.getItemTargetEntry()==itemid)
3243            m_targets.setItemTarget(NULL);
3244
3245        p_caster->DestroyItemCount(itemid, itemcount, true);
3246    }
3247}
3248
3249void Spell::HandleThreatSpells(uint32 spellId)
3250{
3251    if(!m_targets.getUnitTarget() || !spellId)
3252        return;
3253
3254    if(!m_targets.getUnitTarget()->CanHaveThreatList())
3255        return;
3256
3257    SpellThreatEntry const *threatSpell = sSpellThreatStore.LookupEntry<SpellThreatEntry>(spellId);
3258    if(!threatSpell)
3259        return;
3260
3261    m_targets.getUnitTarget()->AddThreat(m_caster, float(threatSpell->threat));
3262
3263    DEBUG_LOG("Spell %u, rank %u, added an additional %i threat", spellId, spellmgr.GetSpellRank(spellId), threatSpell->threat);
3264}
3265
3266void Spell::HandleEffects(Unit *pUnitTarget,Item *pItemTarget,GameObject *pGOTarget,uint32 i, float DamageMultiplier)
3267{
3268    unitTarget = pUnitTarget;
3269    itemTarget = pItemTarget;
3270    gameObjTarget = pGOTarget;
3271
3272    uint8 eff = m_spellInfo->Effect[i];
3273    uint32 mechanic = m_spellInfo->EffectMechanic[i];
3274
3275    damage = int32(CalculateDamage((uint8)i,unitTarget)*DamageMultiplier);
3276
3277    sLog.outDebug( "Spell: Effect : %u", eff);
3278
3279    //Simply return. Do not display "immune" in red text on client
3280    if(unitTarget && unitTarget->IsImmunedToSpellEffect(eff, mechanic))
3281        return;
3282
3283    if(eff<TOTAL_SPELL_EFFECTS)
3284    {
3285        //sLog.outDebug( "WORLD: Spell FX %d < TOTAL_SPELL_EFFECTS ", eff);
3286        (*this.*SpellEffects[eff])(i);
3287    }
3288    /*
3289    else
3290    {
3291        sLog.outDebug( "WORLD: Spell FX %d > TOTAL_SPELL_EFFECTS ", eff);
3292        if (m_CastItem)
3293            EffectEnchantItemTmp(i);
3294        else
3295        {
3296            sLog.outError("SPELL: unknown effect %u spell id %u\n",
3297                eff, m_spellInfo->Id);
3298        }
3299    }
3300    */
3301}
3302
3303void Spell::TriggerSpell()
3304{
3305    for(TriggerSpells::iterator si=m_TriggerSpells.begin(); si!=m_TriggerSpells.end(); ++si)
3306    {
3307        Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID, this->m_selfContainer);
3308        spell->prepare(&m_targets);                         // use original spell original targets
3309    }
3310}
3311
3312uint8 Spell::CanCast(bool strict)
3313{
3314    // check cooldowns to prevent cheating
3315    if(m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->HasSpellCooldown(m_spellInfo->Id))
3316    {
3317        if(m_triggeredByAuraSpell)
3318            return SPELL_FAILED_DONT_REPORT;
3319        else
3320            return SPELL_FAILED_NOT_READY;
3321    }
3322
3323    // only allow triggered spells if at an ended battleground
3324    if( !m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER)
3325        if(BattleGround * bg = ((Player*)m_caster)->GetBattleGround())
3326            if(bg->GetStatus() == STATUS_WAIT_LEAVE)
3327                return SPELL_FAILED_DONT_REPORT;
3328
3329    // only check at first call, Stealth auras are already removed at second call
3330    // for now, ignore triggered spells
3331    if( strict && !m_IsTriggeredSpell)
3332    {
3333        // Cannot be used in this stance/form
3334        if(uint8 shapeError = GetErrorAtShapeshiftedCast(m_spellInfo, m_caster->m_form))
3335            return shapeError;
3336
3337        if ((m_spellInfo->Attributes & SPELL_ATTR_ONLY_STEALTHED) && !(m_caster->HasStealthAura()))
3338            return SPELL_FAILED_ONLY_STEALTHED;
3339    }
3340
3341    // caster state requirements
3342    if(m_spellInfo->CasterAuraState && !m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraState)))
3343        return SPELL_FAILED_CASTER_AURASTATE;
3344    if(m_spellInfo->CasterAuraStateNot && m_caster->HasAuraState(AuraState(m_spellInfo->CasterAuraStateNot)))
3345        return SPELL_FAILED_CASTER_AURASTATE;
3346
3347    // cancel autorepeat spells if cast start when moving
3348    // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code)
3349    if( m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->isMoving() )
3350    {
3351        // skip stuck spell to allow use it in falling case and apply spell limitations at movement
3352        if( (!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING) || m_spellInfo->Effect[0] != SPELL_EFFECT_STUCK) &&
3353            (IsAutoRepeat() || (m_spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) != 0) )
3354            return SPELL_FAILED_MOVING;
3355    }
3356
3357    Unit *target = m_targets.getUnitTarget();
3358
3359    if(target)
3360    {
3361        // target state requirements (not allowed state), apply to self also
3362        if(m_spellInfo->TargetAuraStateNot && target->HasAuraState(AuraState(m_spellInfo->TargetAuraStateNot)))
3363            return SPELL_FAILED_TARGET_AURASTATE;
3364
3365
3366        if(target != m_caster)
3367        {
3368            // target state requirements (apply to non-self only), to allow cast affects to self like Dirty Deeds
3369            if(m_spellInfo->TargetAuraState && !target->HasAuraState(AuraState(m_spellInfo->TargetAuraState)))
3370                return SPELL_FAILED_TARGET_AURASTATE;
3371
3372            // Not allow casting on flying player
3373            if (target->isInFlight())
3374                return SPELL_FAILED_BAD_TARGETS;
3375
3376            if(VMAP::VMapFactory::checkSpellForLoS(m_spellInfo->Id) && !m_caster->IsWithinLOSInMap(target))
3377                return SPELL_FAILED_LINE_OF_SIGHT;
3378
3379            // auto selection spell rank implemented in WorldSession::HandleCastSpellOpcode
3380            // this case can be triggered if rank not found (too low-level target for first rank)
3381            if(m_caster->GetTypeId() == TYPEID_PLAYER && !IsPassiveSpell(m_spellInfo->Id) && !m_CastItem)
3382            {
3383                for(int i=0;i<3;i++)
3384                {
3385                    if(IsPositiveEffect(m_spellInfo->Id, i) && m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
3386                        if(target->getLevel() + 10 < m_spellInfo->spellLevel)
3387                            return SPELL_FAILED_LOWLEVEL;
3388                }
3389            }
3390        }
3391
3392        // check pet presents
3393        for(int j=0;j<3;j++)
3394        {
3395            if(m_spellInfo->EffectImplicitTargetA[j] == TARGET_PET)
3396            {
3397                target = m_caster->GetPet();
3398                if(!target)
3399                {
3400                    if(m_triggeredByAuraSpell)              // not report pet not existence for triggered spells
3401                        return SPELL_FAILED_DONT_REPORT;
3402                    else
3403                        return SPELL_FAILED_NO_PET;
3404                }
3405                break;
3406            }
3407        }
3408
3409        //check creature type
3410        //ignore self casts (including area casts when caster selected as target)
3411        if(target != m_caster)
3412        {
3413            if(!CheckTargetCreatureType(target))
3414            {
3415                if(target->GetTypeId()==TYPEID_PLAYER)
3416                    return SPELL_FAILED_TARGET_IS_PLAYER;
3417                else
3418                    return SPELL_FAILED_BAD_TARGETS;
3419            }
3420        }
3421
3422        // TODO: this check can be applied and for player to prevent cheating when IsPositiveSpell will return always correct result.
3423        // check target for pet/charmed casts (not self targeted), self targeted cast used for area effects and etc
3424        if(m_caster != target && m_caster->GetTypeId()==TYPEID_UNIT && m_caster->GetCharmerOrOwnerGUID())
3425        {
3426            // check correctness positive/negative cast target (pet cast real check and cheating check)
3427            if(IsPositiveSpell(m_spellInfo->Id))
3428            {
3429                if(m_caster->IsHostileTo(target))
3430                    return SPELL_FAILED_BAD_TARGETS;
3431            }
3432            else
3433            {
3434                if(m_caster->IsFriendlyTo(target))
3435                    return SPELL_FAILED_BAD_TARGETS;
3436            }
3437        }
3438
3439        if(IsPositiveSpell(m_spellInfo->Id))
3440        {
3441            if(target->IsImmunedToSpell(m_spellInfo,false))
3442                return SPELL_FAILED_TARGET_AURASTATE;
3443        }
3444
3445        //Must be behind the target.
3446        if( m_spellInfo->AttributesEx2 == 0x100000 && (m_spellInfo->AttributesEx & 0x200) == 0x200 && target->HasInArc(M_PI, m_caster) )
3447        {
3448            SendInterrupted(2);
3449            return SPELL_FAILED_NOT_BEHIND;
3450        }
3451
3452        //Target must be facing you.
3453        if((m_spellInfo->Attributes == 0x150010) && !target->HasInArc(M_PI, m_caster) )
3454        {
3455            SendInterrupted(2);
3456            return SPELL_FAILED_NOT_INFRONT;
3457        }
3458
3459        // check if target is in combat
3460        if (target != m_caster && (m_spellInfo->AttributesEx & SPELL_ATTR_EX_NOT_IN_COMBAT_TARGET) && target->isInCombat())
3461        {
3462            return SPELL_FAILED_TARGET_AFFECTING_COMBAT;
3463        }
3464    }
3465    // Spell casted only on battleground
3466    if((m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_BATTLEGROUND) &&  m_caster->GetTypeId()==TYPEID_PLAYER)
3467        if(!((Player*)m_caster)->InBattleGround())
3468            return SPELL_FAILED_ONLY_BATTLEGROUNDS;
3469
3470    // do not allow spells to be cast in arenas
3471    // - with greater than 15 min CD without SPELL_ATTR_EX4_USABLE_IN_ARENA flag
3472    // - with SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA flag
3473    if( (m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_NOT_USABLE_IN_ARENA) ||
3474        GetSpellRecoveryTime(m_spellInfo) > 15 * MINUTE * 1000 && !(m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_USABLE_IN_ARENA) )
3475        if(MapEntry const* mapEntry = sMapStore.LookupEntry(m_caster->GetMapId()))
3476            if(mapEntry->IsBattleArena())
3477                return SPELL_FAILED_NOT_IN_ARENA;
3478
3479    // zone check
3480    if(!IsSpellAllowedInLocation(m_spellInfo,m_caster->GetMapId(),m_caster->GetZoneId(),m_caster->GetAreaId()))
3481        return SPELL_FAILED_REQUIRES_AREA;
3482
3483    // not let players cast spells at mount (and let do it to creatures)
3484    if( m_caster->IsMounted() && m_caster->GetTypeId()==TYPEID_PLAYER && !m_IsTriggeredSpell &&
3485        !IsPassiveSpell(m_spellInfo->Id) && !(m_spellInfo->Attributes & SPELL_ATTR_CASTABLE_WHILE_MOUNTED) )
3486    {
3487        if(m_caster->isInFlight())
3488            return SPELL_FAILED_NOT_FLYING;
3489        else
3490            return SPELL_FAILED_NOT_MOUNTED;
3491    }
3492
3493    // always (except passive spells) check items (focus object can be required for any type casts)
3494    if(!IsPassiveSpell(m_spellInfo->Id))
3495        if(uint8 castResult = CheckItems())
3496            return castResult;
3497
3498    if(uint8 castResult = CheckRange(strict))
3499        return castResult;
3500
3501    {
3502        if(uint8 castResult = CheckPower())
3503            return castResult;
3504    }
3505
3506    if(!m_triggeredByAuraSpell)                             // triggered spell not affected by stun/etc
3507        if(uint8 castResult = CheckCasterAuras())
3508            return castResult;
3509
3510    for (int i = 0; i < 3; i++)
3511    {
3512        // for effects of spells that have only one target
3513        switch(m_spellInfo->Effect[i])
3514        {
3515            case SPELL_EFFECT_DUMMY:
3516            {
3517                if(m_spellInfo->SpellIconID == 1648)        // Execute
3518                {
3519                    if(!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2)
3520                        return SPELL_FAILED_BAD_TARGETS;
3521                }
3522                else if (m_spellInfo->Id == 51582)          // Rocket Boots Engaged
3523                {
3524                    if(m_caster->IsInWater())
3525                        return SPELL_FAILED_ONLY_ABOVEWATER;
3526                }
3527                else if(m_spellInfo->SpellIconID==156)      // Holy Shock
3528                {
3529                    // spell different for friends and enemies
3530                    // hart version required facing
3531                    if(m_targets.getUnitTarget() && !m_caster->IsFriendlyTo(m_targets.getUnitTarget()) && !m_caster->HasInArc( M_PI, target ))
3532                        return SPELL_FAILED_UNIT_NOT_INFRONT;
3533                }
3534                break;
3535            }
3536            case SPELL_EFFECT_SCHOOL_DAMAGE:
3537            {
3538                // Hammer of Wrath
3539                if(m_spellInfo->SpellVisual == 7250)
3540                {
3541                    if (!m_targets.getUnitTarget())
3542                        return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
3543
3544                    if(m_targets.getUnitTarget()->GetHealth() > m_targets.getUnitTarget()->GetMaxHealth()*0.2)
3545                        return SPELL_FAILED_BAD_TARGETS;
3546                }
3547                break;
3548            }
3549            case SPELL_EFFECT_TAMECREATURE:
3550            {
3551                if (!m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() == TYPEID_PLAYER)
3552                    return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
3553
3554                if (m_targets.getUnitTarget()->getLevel() > m_caster->getLevel())
3555                    return SPELL_FAILED_HIGHLEVEL;
3556
3557                CreatureInfo const *cinfo = ((Creature*)m_targets.getUnitTarget())->GetCreatureInfo();
3558                if( cinfo->type != CREATURE_TYPE_BEAST )
3559                    return SPELL_FAILED_BAD_TARGETS;
3560
3561                // use SMSG_PET_TAME_FAILURE?
3562                if( !(cinfo->flag1 & 1) || !(cinfo->family) )
3563                    return SPELL_FAILED_BAD_TARGETS;
3564
3565                if(m_caster->GetPetGUID())
3566                    return SPELL_FAILED_ALREADY_HAVE_SUMMON;
3567
3568                if(m_caster->GetCharmGUID())
3569                    return SPELL_FAILED_ALREADY_HAVE_CHARM;
3570
3571                break;
3572            }
3573            case SPELL_EFFECT_LEARN_SPELL:
3574            {
3575                if(m_spellInfo->EffectImplicitTargetA[i] != TARGET_PET)
3576                    break;
3577
3578                Pet* pet = m_caster->GetPet();
3579
3580                if(!pet)
3581                    return SPELL_FAILED_NO_PET;
3582
3583                SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
3584
3585                if(!learn_spellproto)
3586                    return SPELL_FAILED_NOT_KNOWN;
3587
3588                if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id))
3589                    return SPELL_FAILED_TOO_MANY_SKILLS;
3590
3591                if(m_spellInfo->spellLevel > pet->getLevel())
3592                    return SPELL_FAILED_LOWLEVEL;
3593
3594                if(!pet->HasTPForSpell(learn_spellproto->Id))
3595                    return SPELL_FAILED_TRAINING_POINTS;
3596
3597                break;
3598            }
3599            case SPELL_EFFECT_LEARN_PET_SPELL:
3600            {
3601                Pet* pet = m_caster->GetPet();
3602
3603                if(!pet)
3604                    return SPELL_FAILED_NO_PET;
3605
3606                SpellEntry const *learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
3607
3608                if(!learn_spellproto)
3609                    return SPELL_FAILED_NOT_KNOWN;
3610
3611                if(!pet->CanTakeMoreActiveSpells(learn_spellproto->Id))
3612                    return SPELL_FAILED_TOO_MANY_SKILLS;
3613
3614                if(m_spellInfo->spellLevel > pet->getLevel())
3615                    return SPELL_FAILED_LOWLEVEL;
3616
3617                if(!pet->HasTPForSpell(learn_spellproto->Id))
3618                    return SPELL_FAILED_TRAINING_POINTS;
3619
3620                break;
3621            }
3622            case SPELL_EFFECT_FEED_PET:
3623            {
3624                if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_targets.getItemTarget() )
3625                    return SPELL_FAILED_BAD_TARGETS;
3626
3627                Pet* pet = m_caster->GetPet();
3628
3629                if(!pet)
3630                    return SPELL_FAILED_NO_PET;
3631
3632                if(!pet->HaveInDiet(m_targets.getItemTarget()->GetProto()))
3633                    return SPELL_FAILED_WRONG_PET_FOOD;
3634
3635                if(!pet->GetCurrentFoodBenefitLevel(m_targets.getItemTarget()->GetProto()->ItemLevel))
3636                    return SPELL_FAILED_FOOD_LOWLEVEL;
3637
3638                if(m_caster->isInCombat() || pet->isInCombat())
3639                    return SPELL_FAILED_AFFECTING_COMBAT;
3640
3641                break;
3642            }
3643            case SPELL_EFFECT_POWER_BURN:
3644            case SPELL_EFFECT_POWER_DRAIN:
3645            {
3646                // Can be area effect, Check only for players and not check if target - caster (spell can have multiply drain/burn effects)
3647                if(m_caster->GetTypeId() == TYPEID_PLAYER)
3648                    if(Unit* target = m_targets.getUnitTarget())
3649                        if(target!=m_caster && target->getPowerType()!=m_spellInfo->EffectMiscValue[i])
3650                            return SPELL_FAILED_BAD_TARGETS;
3651                break;
3652            }
3653            case SPELL_EFFECT_CHARGE:
3654            {
3655                if (m_caster->hasUnitState(UNIT_STAT_ROOT))
3656                    return SPELL_FAILED_ROOTED;
3657
3658                break;
3659            }
3660            case SPELL_EFFECT_SKINNING:
3661            {
3662                if (m_caster->GetTypeId() != TYPEID_PLAYER || !m_targets.getUnitTarget() || m_targets.getUnitTarget()->GetTypeId() != TYPEID_UNIT)
3663                    return SPELL_FAILED_BAD_TARGETS;
3664
3665                if( !(m_targets.getUnitTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & UNIT_FLAG_SKINNABLE) )
3666                    return SPELL_FAILED_TARGET_UNSKINNABLE;
3667
3668                Creature* creature = (Creature*)m_targets.getUnitTarget();
3669                if ( creature->GetCreatureType() != CREATURE_TYPE_CRITTER && ( !creature->lootForBody || !creature->loot.empty() ) )
3670                {
3671                    return SPELL_FAILED_TARGET_NOT_LOOTED;
3672                }
3673
3674                uint32 skill;
3675                if(creature->GetCreatureInfo()->flag1 & 256)
3676                    skill = SKILL_HERBALISM;                // special case
3677                else if(creature->GetCreatureInfo()->flag1 & 512)
3678                    skill = SKILL_MINING;                   // special case
3679                else
3680                    skill = SKILL_SKINNING;                 // normal case
3681
3682                int32 skillValue = ((Player*)m_caster)->GetSkillValue(skill);
3683                int32 TargetLevel = m_targets.getUnitTarget()->getLevel();
3684                int32 ReqValue = (skillValue < 100 ? (TargetLevel-10)*10 : TargetLevel*5);
3685                if (ReqValue > skillValue)
3686                    return SPELL_FAILED_LOW_CASTLEVEL;
3687
3688                // chance for fail at orange skinning attempt
3689                if( (m_selfContainer && (*m_selfContainer) == this) &&
3690                    skillValue < sWorld.GetConfigMaxSkillValue() &&
3691                    (ReqValue < 0 ? 0 : ReqValue) > irand(skillValue-25, skillValue+37) )
3692                    return SPELL_FAILED_TRY_AGAIN;
3693
3694                break;
3695            }
3696            case SPELL_EFFECT_OPEN_LOCK_ITEM:
3697            case SPELL_EFFECT_OPEN_LOCK:
3698            {
3699                if( m_spellInfo->EffectImplicitTargetA[i] != TARGET_GAMEOBJECT &&
3700                    m_spellInfo->EffectImplicitTargetA[i] != TARGET_GAMEOBJECT_ITEM )
3701                    break;
3702
3703                if( m_caster->GetTypeId() != TYPEID_PLAYER  // only players can open locks, gather etc.
3704                    // we need a go target in case of TARGET_GAMEOBJECT
3705                    || m_spellInfo->EffectImplicitTargetA[i] == TARGET_GAMEOBJECT && !m_targets.getGOTarget()
3706                    // we need a go target, or an openable item target in case of TARGET_GAMEOBJECT_ITEM
3707                    || m_spellInfo->EffectImplicitTargetA[i] == TARGET_GAMEOBJECT_ITEM && !m_targets.getGOTarget() &&
3708                    (!m_targets.getItemTarget() || !m_targets.getItemTarget()->GetProto()->LockID || m_targets.getItemTarget()->GetOwner() != m_caster ) )
3709                    return SPELL_FAILED_BAD_TARGETS;
3710
3711                // In BattleGround players can use only flags and banners
3712                if( ((Player*)m_caster)->InBattleGround() &&
3713                    !((Player*)m_caster)->isAllowUseBattleGroundObject() )
3714                    return SPELL_FAILED_TRY_AGAIN;
3715
3716                // get the lock entry
3717                LockEntry const *lockInfo = NULL;
3718                if (GameObject* go=m_targets.getGOTarget())
3719                    lockInfo = sLockStore.LookupEntry(go->GetLockId());
3720                else if(Item* itm=m_targets.getItemTarget())
3721                    lockInfo = sLockStore.LookupEntry(itm->GetProto()->LockID);
3722
3723                // check lock compatibility
3724                if (lockInfo)
3725                {
3726                    // check for lock - key pair (checked by client also, just prevent cheating
3727                    bool ok_key = false;
3728                    for(int it = 0; it < 5; ++it)
3729                    {
3730                        switch(lockInfo->keytype[it])
3731                        {
3732                            case LOCK_KEY_NONE:
3733                                break;
3734                            case LOCK_KEY_ITEM:
3735                            {
3736                                if(lockInfo->key[it])
3737                                {
3738                                    if(m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it])
3739                                        ok_key =true;
3740                                    break;
3741                                }
3742                            }
3743                            case LOCK_KEY_SKILL:
3744                            {
3745                                if(uint32(m_spellInfo->EffectMiscValue[i])!=lockInfo->key[it])
3746                                    break;
3747
3748                                switch(lockInfo->key[it])
3749                                {
3750                                    case LOCKTYPE_HERBALISM:
3751                                        if(((Player*)m_caster)->HasSkill(SKILL_HERBALISM))
3752                                            ok_key =true;
3753                                        break;
3754                                    case LOCKTYPE_MINING:
3755                                        if(((Player*)m_caster)->HasSkill(SKILL_MINING))
3756                                            ok_key =true;
3757                                        break;
3758                                    default:
3759                                        ok_key =true;
3760                                        break;
3761                                }
3762                            }
3763                        }
3764                        if(ok_key)
3765                            break;
3766                    }
3767
3768                    if(!ok_key)
3769                        return SPELL_FAILED_BAD_TARGETS;
3770                }
3771
3772                // chance for fail at orange mining/herb/LockPicking gathering attempt
3773                if (!m_selfContainer || ((*m_selfContainer) != this))
3774                    break;
3775
3776                // get the skill value of the player
3777                int32 SkillValue = 0;
3778                bool canFailAtMax = true;
3779                if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_HERBALISM)
3780                {
3781                    SkillValue = ((Player*)m_caster)->GetSkillValue(SKILL_HERBALISM);
3782                    canFailAtMax = false;
3783                }
3784                else if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_MINING)
3785                {
3786                    SkillValue = ((Player*)m_caster)->GetSkillValue(SKILL_MINING);
3787                    canFailAtMax = false;
3788                }
3789                else if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK)
3790                    SkillValue = ((Player*)m_caster)->GetSkillValue(SKILL_LOCKPICKING);
3791
3792                // castitem check: rogue using skeleton keys. the skill values should not be added in this case.
3793                if(m_CastItem)
3794                    SkillValue = 0;
3795
3796                // add the damage modifier from the spell casted (cheat lock / skeleton key etc.) (use m_currentBasePoints, CalculateDamage returns wrong value)
3797                SkillValue += m_currentBasePoints[i]+1;
3798
3799                // get the required lock value
3800                int32 ReqValue=0;
3801                if (lockInfo)
3802                {
3803                    // check for lock - key pair
3804                    bool ok = false;
3805                    for(int it = 0; it < 5; ++it)
3806                    {
3807                        if(lockInfo->keytype[it]==LOCK_KEY_ITEM && lockInfo->key[it] && m_CastItem && m_CastItem->GetEntry()==lockInfo->key[it])
3808                        {
3809                            // if so, we're good to go
3810                            ok = true;
3811                            break;
3812                        }
3813                    }
3814                    if(ok)
3815                        break;
3816
3817                    if (m_spellInfo->EffectMiscValue[i] == LOCKTYPE_PICKLOCK)
3818                        ReqValue = lockInfo->requiredlockskill;
3819                    else
3820                        ReqValue = lockInfo->requiredminingskill;
3821                }
3822
3823                // skill doesn't meet the required value
3824                if (ReqValue > SkillValue)
3825                    return SPELL_FAILED_LOW_CASTLEVEL;
3826
3827                // chance for failure in orange gather / lockpick (gathering skill can't fail at maxskill)
3828                if((canFailAtMax || SkillValue < sWorld.GetConfigMaxSkillValue()) && ReqValue > irand(SkillValue-25, SkillValue+37))
3829                    return SPELL_FAILED_TRY_AGAIN;
3830
3831                break;
3832            }
3833            case SPELL_EFFECT_SUMMON_DEAD_PET:
3834            {
3835                Creature *pet = m_caster->GetPet();
3836                if(!pet)
3837                    return SPELL_FAILED_NO_PET;
3838
3839                if(pet->isAlive())
3840                    return SPELL_FAILED_ALREADY_HAVE_SUMMON;
3841
3842                break;
3843            }
3844            // This is generic summon effect now and don't make this check for summon types similar
3845            // SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN.
3846            // These won't show up in m_caster->GetPetGUID()
3847            case SPELL_EFFECT_SUMMON:
3848            {
3849                switch(m_spellInfo->EffectMiscValueB[i])
3850                {
3851                    case SUMMON_TYPE_POSESSED:
3852                    case SUMMON_TYPE_POSESSED2:
3853                    case SUMMON_TYPE_DEMON:
3854                    case SUMMON_TYPE_SUMMON:
3855                    {
3856                        if(m_caster->GetPetGUID())
3857                            return SPELL_FAILED_ALREADY_HAVE_SUMMON;
3858
3859                        if(m_caster->GetCharmGUID())
3860                            return SPELL_FAILED_ALREADY_HAVE_CHARM;
3861                        break;
3862                    }
3863                }
3864                break;
3865            }
3866            // Don't make this check for SPELL_EFFECT_SUMMON_CRITTER, SPELL_EFFECT_SUMMON_WILD or SPELL_EFFECT_SUMMON_GUARDIAN.
3867            // These won't show up in m_caster->GetPetGUID()
3868            case SPELL_EFFECT_SUMMON_POSSESSED:
3869            case SPELL_EFFECT_SUMMON_PHANTASM:
3870            case SPELL_EFFECT_SUMMON_DEMON:
3871            {
3872                if(m_caster->GetPetGUID())
3873                    return SPELL_FAILED_ALREADY_HAVE_SUMMON;
3874
3875                if(m_caster->GetCharmGUID())
3876                    return SPELL_FAILED_ALREADY_HAVE_CHARM;
3877
3878                break;
3879            }
3880            case SPELL_EFFECT_SUMMON_PET:
3881            {
3882                if(m_caster->GetPetGUID())                  //let warlock do a replacement summon
3883                {
3884
3885                    Pet* pet = ((Player*)m_caster)->GetPet();
3886
3887                    if (m_caster->GetTypeId()==TYPEID_PLAYER && m_caster->getClass()==CLASS_WARLOCK)
3888                    {
3889                        if (strict)                         //starting cast, trigger pet stun (cast by pet so it doesn't attack player)
3890                            pet->CastSpell(pet, 32752, true, NULL, NULL, pet->GetGUID());
3891                    }
3892                    else
3893                        return SPELL_FAILED_ALREADY_HAVE_SUMMON;
3894                }
3895
3896                if(m_caster->GetCharmGUID())
3897                    return SPELL_FAILED_ALREADY_HAVE_CHARM;
3898
3899                break;
3900            }
3901            case SPELL_EFFECT_SUMMON_PLAYER:
3902            {
3903                if(m_caster->GetTypeId()!=TYPEID_PLAYER)
3904                    return SPELL_FAILED_BAD_TARGETS;
3905                if(!((Player*)m_caster)->GetSelection())
3906                    return SPELL_FAILED_BAD_TARGETS;
3907
3908                Player* target = objmgr.GetPlayer(((Player*)m_caster)->GetSelection());
3909                if( !target || ((Player*)m_caster)==target || !target->IsInSameRaidWith((Player*)m_caster) )
3910                    return SPELL_FAILED_BAD_TARGETS;
3911
3912                // check if our map is dungeon
3913                if( sMapStore.LookupEntry(m_caster->GetMapId())->IsDungeon() )
3914                {
3915                    InstanceTemplate const* instance = ObjectMgr::GetInstanceTemplate(m_caster->GetMapId());
3916                    if(!instance)
3917                        return SPELL_FAILED_TARGET_NOT_IN_INSTANCE;
3918                    if ( instance->levelMin > target->getLevel() )
3919                        return SPELL_FAILED_LOWLEVEL;
3920                    if ( instance->levelMax && instance->levelMax < target->getLevel() )
3921                        return SPELL_FAILED_HIGHLEVEL;
3922                }
3923                break;
3924            }
3925            case SPELL_EFFECT_LEAP:
3926            case SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER:
3927            {
3928                float dis = GetSpellRadius(sSpellRadiusStore.LookupEntry(m_spellInfo->EffectRadiusIndex[i]));
3929                float fx = m_caster->GetPositionX() + dis * cos(m_caster->GetOrientation());
3930                float fy = m_caster->GetPositionY() + dis * sin(m_caster->GetOrientation());
3931                // teleport a bit above terrain level to avoid falling below it
3932                float fz = MapManager::Instance().GetBaseMap(m_caster->GetMapId())->GetHeight(fx,fy,m_caster->GetPositionZ(),true);
3933                if(fz <= INVALID_HEIGHT)                    // note: this also will prevent use effect in instances without vmaps height enabled
3934                    return SPELL_FAILED_TRY_AGAIN;
3935
3936                float caster_pos_z = m_caster->GetPositionZ();
3937                // Control the caster to not climb or drop when +-fz > 8
3938                if(!(fz<=caster_pos_z+8 && fz>=caster_pos_z-8))
3939                    return SPELL_FAILED_TRY_AGAIN;
3940
3941                // not allow use this effect at battleground until battleground start
3942                if(m_caster->GetTypeId()==TYPEID_PLAYER)
3943                    if(BattleGround const *bg = ((Player*)m_caster)->GetBattleGround())
3944                        if(bg->GetStatus() != STATUS_IN_PROGRESS)
3945                            return SPELL_FAILED_TRY_AGAIN;
3946                break;
3947            }
3948            case SPELL_EFFECT_STEAL_BENEFICIAL_BUFF:
3949            {
3950                if (m_targets.getUnitTarget()==m_caster)
3951                    return SPELL_FAILED_BAD_TARGETS;
3952                break;
3953            }
3954            default:break;
3955        }
3956    }
3957
3958    for (int i = 0; i < 3; i++)
3959    {
3960        switch(m_spellInfo->EffectApplyAuraName[i])
3961        {
3962            case SPELL_AURA_MOD_POSSESS:
3963            case SPELL_AURA_MOD_CHARM:
3964            {
3965                if(m_caster->GetPetGUID())
3966                    return SPELL_FAILED_ALREADY_HAVE_SUMMON;
3967
3968                if(m_caster->GetCharmGUID())
3969                    return SPELL_FAILED_ALREADY_HAVE_CHARM;
3970
3971                if(m_caster->GetCharmerGUID())
3972                    return SPELL_FAILED_CHARMED;
3973
3974                if(!m_targets.getUnitTarget())
3975                    return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
3976
3977                if(m_targets.getUnitTarget()->GetCharmerGUID())
3978                    return SPELL_FAILED_CHARMED;
3979
3980                if(int32(m_targets.getUnitTarget()->getLevel()) > CalculateDamage(i,m_targets.getUnitTarget()))
3981                    return SPELL_FAILED_HIGHLEVEL;
3982            };break;
3983            case SPELL_AURA_MOUNTED:
3984            {
3985                if (m_caster->IsInWater())
3986                    return SPELL_FAILED_ONLY_ABOVEWATER;
3987
3988                if (m_caster->GetTypeId()==TYPEID_PLAYER && ((Player*)m_caster)->GetTransport())
3989                    return SPELL_FAILED_NO_MOUNTS_ALLOWED;
3990
3991                // Ignore map check if spell have AreaId. AreaId already checked and this prevent special mount spells
3992                if (m_caster->GetTypeId()==TYPEID_PLAYER && !sMapStore.LookupEntry(m_caster->GetMapId())->IsMountAllowed() && !m_IsTriggeredSpell && !m_spellInfo->AreaId)
3993                    return SPELL_FAILED_NO_MOUNTS_ALLOWED;
3994
3995                if (m_caster->GetAreaId()==35)
3996                    return SPELL_FAILED_NO_MOUNTS_ALLOWED;
3997
3998                ShapeshiftForm form = m_caster->m_form;
3999                if( form == FORM_CAT          || form == FORM_TREE      || form == FORM_TRAVEL   ||
4000                    form == FORM_AQUA         || form == FORM_BEAR      || form == FORM_DIREBEAR ||
4001                    form == FORM_CREATUREBEAR || form == FORM_GHOSTWOLF || form == FORM_FLIGHT   ||
4002                    form == FORM_FLIGHT_EPIC  || form == FORM_MOONKIN )
4003                    return SPELL_FAILED_NOT_SHAPESHIFT;
4004
4005                break;
4006            }
4007            case SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS:
4008            {
4009                if(!m_targets.getUnitTarget())
4010                    return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
4011
4012                // can be casted at non-friendly unit or own pet/charm
4013                if(m_caster->IsFriendlyTo(m_targets.getUnitTarget()))
4014                    return SPELL_FAILED_TARGET_FRIENDLY;
4015            };break;
4016            case SPELL_AURA_MOD_INCREASE_FLIGHT_SPEED:
4017            case SPELL_AURA_FLY:
4018            {
4019                // not allow cast fly spells at old maps by players (all spells is self target)
4020                if(m_caster->GetTypeId()==TYPEID_PLAYER)
4021                {
4022                    if( !((Player*)m_caster)->isGameMaster() &&
4023                        GetVirtualMapForMapAndZone(m_caster->GetMapId(),m_caster->GetZoneId()) != 530)
4024                        return SPELL_FAILED_NOT_HERE;
4025                }
4026            };break;
4027            case SPELL_AURA_PERIODIC_MANA_LEECH:
4028            {
4029                if (!m_targets.getUnitTarget())
4030                    return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
4031
4032                if (m_caster->GetTypeId()!=TYPEID_PLAYER || m_CastItem)
4033                    break;
4034
4035                if(m_targets.getUnitTarget()->getPowerType()!=POWER_MANA)
4036                    return SPELL_FAILED_BAD_TARGETS;
4037                break;
4038            }
4039            default:break;
4040        }
4041    }
4042
4043    // all ok
4044    return 0;
4045}
4046
4047int16 Spell::PetCanCast(Unit* target)
4048{
4049    if(!m_caster->isAlive())
4050        return SPELL_FAILED_CASTER_DEAD;
4051
4052    if(m_caster->IsNonMeleeSpellCasted(false))              //prevent spellcast interuption by another spellcast
4053        return SPELL_FAILED_SPELL_IN_PROGRESS;
4054    if(m_caster->isInCombat() && IsNonCombatSpell(m_spellInfo))
4055        return SPELL_FAILED_AFFECTING_COMBAT;
4056
4057    if(m_caster->GetTypeId()==TYPEID_UNIT && (((Creature*)m_caster)->isPet() || m_caster->isCharmed()))
4058    {
4059                                                            //dead owner (pets still alive when owners ressed?)
4060        if(m_caster->GetCharmerOrOwner() && !m_caster->GetCharmerOrOwner()->isAlive())
4061            return SPELL_FAILED_CASTER_DEAD;
4062
4063        if(!target && m_targets.getUnitTarget())
4064            target = m_targets.getUnitTarget();
4065
4066        bool need = false;
4067        for(uint32 i = 0;i<3;i++)
4068        {
4069            if(m_spellInfo->EffectImplicitTargetA[i] == TARGET_CHAIN_DAMAGE || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_FRIEND || m_spellInfo->EffectImplicitTargetA[i] == TARGET_DUELVSPLAYER || m_spellInfo->EffectImplicitTargetA[i] == TARGET_SINGLE_PARTY || m_spellInfo->EffectImplicitTargetA[i] == TARGET_CURRENT_ENEMY_COORDINATES)
4070            {
4071                need = true;
4072                if(!target)
4073                    return SPELL_FAILED_BAD_IMPLICIT_TARGETS;
4074                break;
4075            }
4076        }
4077        if(need)
4078            m_targets.setUnitTarget(target);
4079
4080        Unit* _target = m_targets.getUnitTarget();
4081
4082        if(_target)                                         //for target dead/target not valid
4083        {
4084            if(!_target->isAlive())
4085                return SPELL_FAILED_BAD_TARGETS;
4086
4087            if(IsPositiveSpell(m_spellInfo->Id))
4088            {
4089                if(m_caster->IsHostileTo(_target))
4090                    return SPELL_FAILED_BAD_TARGETS;
4091            }
4092            else
4093            {
4094                bool duelvsplayertar = false;
4095                for(int j=0;j<3;j++)
4096                {
4097                                                            //TARGET_DUELVSPLAYER is positive AND negative
4098                    duelvsplayertar |= (m_spellInfo->EffectImplicitTargetA[j] == TARGET_DUELVSPLAYER);
4099                }
4100                if(m_caster->IsFriendlyTo(target) && !duelvsplayertar)
4101                {
4102                    return SPELL_FAILED_BAD_TARGETS;
4103                }
4104            }
4105        }
4106                                                            //cooldown
4107        if(((Creature*)m_caster)->HasSpellCooldown(m_spellInfo->Id))
4108            return SPELL_FAILED_NOT_READY;
4109    }
4110
4111    uint16 result = CanCast(true);
4112    if(result != 0)
4113        return result;
4114    else
4115        return -1;                                          //this allows to check spell fail 0, in combat
4116}
4117
4118uint8 Spell::CheckCasterAuras() const
4119{
4120    // Flag drop spells totally immuned to caster auras
4121    // FIXME: find more nice check for all totally immuned spells
4122    // AttributesEx3 & 0x10000000?
4123    if(m_spellInfo->Id==23336 || m_spellInfo->Id==23334 || m_spellInfo->Id==34991)
4124        return 0;
4125
4126    uint8 school_immune = 0;
4127    uint32 mechanic_immune = 0;
4128    uint32 dispel_immune = 0;
4129
4130    //Check if the spell grants school or mechanic immunity.
4131    //We use bitmasks so the loop is done only once and not on every aura check below.
4132    if ( m_spellInfo->AttributesEx & SPELL_ATTR_EX_DISPEL_AURAS_ON_IMMUNITY )
4133    {
4134        for(int i = 0;i < 3; i ++)
4135        {
4136            if(m_spellInfo->EffectApplyAuraName[i] == SPELL_AURA_SCHOOL_IMMUNITY)
4137                school_immune |= uint32(m_spellInfo->EffectMiscValue[i]);
4138            else if(m_spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MECHANIC_IMMUNITY)
4139                mechanic_immune |= 1 << uint32(m_spellInfo->EffectMiscValue[i]);
4140            else if(m_spellInfo->EffectApplyAuraName[i] == SPELL_AURA_DISPEL_IMMUNITY)
4141                dispel_immune |= GetDispellMask(DispelType(m_spellInfo->EffectMiscValue[i]));
4142        }
4143        //immune movement impairement and loss of control
4144        if(m_spellInfo->Id==(uint32)42292)
4145            mechanic_immune = IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK;
4146    }
4147
4148    //Check whether the cast should be prevented by any state you might have.
4149    uint8 prevented_reason = 0;
4150    // Have to check if there is a stun aura. Otherwise will have problems with ghost aura apply while logging out
4151    if(!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED) && m_caster->HasAuraType(SPELL_AURA_MOD_STUN))
4152        prevented_reason = SPELL_FAILED_STUNNED;
4153    else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_CONFUSED) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED))
4154        prevented_reason = SPELL_FAILED_CONFUSED;
4155    else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_FLEEING) && !(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED))
4156        prevented_reason = SPELL_FAILED_FLEEING;
4157    else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE)
4158        prevented_reason = SPELL_FAILED_SILENCED;
4159    else if(m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED) && m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY)
4160        prevented_reason = SPELL_FAILED_PACIFIED;
4161
4162    // Attr must make flag drop spell totally immuned from all effects
4163    if(prevented_reason)
4164    {
4165        if(school_immune || mechanic_immune || dispel_immune)
4166        {
4167            //Checking auras is needed now, because you are prevented by some state but the spell grants immunity.
4168            Unit::AuraMap const& auras = m_caster->GetAuras();
4169            for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); itr++)
4170            {
4171                if(itr->second)
4172                {
4173                    if( GetSpellMechanicMask(itr->second->GetSpellProto(), itr->second->GetEffIndex()) & mechanic_immune )
4174                        continue;
4175                    if( GetSpellSchoolMask(itr->second->GetSpellProto()) & school_immune )
4176                        continue;
4177                    if( (1<<(itr->second->GetSpellProto()->Dispel)) & dispel_immune)
4178                        continue;
4179
4180                    //Make a second check for spell failed so the right SPELL_FAILED message is returned.
4181                    //That is needed when your casting is prevented by multiple states and you are only immune to some of them.
4182                    switch(itr->second->GetModifier()->m_auraname)
4183                    {
4184                        case SPELL_AURA_MOD_STUN:
4185                            if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED))
4186                                return SPELL_FAILED_STUNNED;
4187                            break;
4188                        case SPELL_AURA_MOD_CONFUSE:
4189                            if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED))
4190                                return SPELL_FAILED_CONFUSED;
4191                            break;
4192                        case SPELL_AURA_MOD_FEAR:
4193                            if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED))
4194                                return SPELL_FAILED_FLEEING;
4195                            break;
4196                        case SPELL_AURA_MOD_SILENCE:
4197                        case SPELL_AURA_MOD_PACIFY:
4198                        case SPELL_AURA_MOD_PACIFY_SILENCE:
4199                            if( m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_PACIFY)
4200                                return SPELL_FAILED_PACIFIED;
4201                            else if ( m_spellInfo->PreventionType==SPELL_PREVENTION_TYPE_SILENCE)
4202                                return SPELL_FAILED_SILENCED;
4203                            break;
4204                    }
4205                }
4206            }
4207        }
4208        //You are prevented from casting and the spell casted does not grant immunity. Return a failed error.
4209        else
4210            return prevented_reason;
4211    }
4212    return 0;                                               // all ok
4213}
4214
4215bool Spell::CanAutoCast(Unit* target)
4216{
4217    uint64 targetguid = target->GetGUID();
4218
4219    for(uint32 j = 0;j<3;j++)
4220    {
4221        if(m_spellInfo->Effect[j] == SPELL_EFFECT_APPLY_AURA)
4222        {
4223            if( m_spellInfo->StackAmount <= 1)
4224            {
4225                if( target->HasAura(m_spellInfo->Id, j) )
4226                    return false;
4227            }
4228            else
4229            {
4230                if( target->GetAuras().count(Unit::spellEffectPair(m_spellInfo->Id, j)) >= m_spellInfo->StackAmount)
4231                    return false;
4232            }
4233        }
4234        else if ( IsAreaAuraEffect( m_spellInfo->Effect[j] ))
4235        {
4236                if( target->HasAura(m_spellInfo->Id, j) )
4237                    return false;
4238        }
4239    }
4240
4241    int16 result = PetCanCast(target);
4242
4243    if(result == -1 || result == SPELL_FAILED_UNIT_NOT_INFRONT)
4244    {
4245        FillTargetMap();
4246        //check if among target units, our WANTED target is as well (->only self cast spells return false)
4247        for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
4248            if( ihit->targetGUID == targetguid )
4249                return true;
4250    }
4251    return false;                                           //target invalid
4252}
4253
4254uint8 Spell::CheckRange(bool strict)
4255{
4256    float range_mod;
4257
4258    // self cast doesn't need range checking -- also for Starshards fix
4259    if (m_spellInfo->rangeIndex == 1) return 0;
4260
4261    if (strict)                                             //add radius of caster
4262        range_mod = 1.25;
4263    else                                                    //add radius of caster and ~5 yds "give"
4264        range_mod = 6.25;
4265
4266    SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
4267    float max_range = GetSpellMaxRange(srange) + range_mod;
4268    float min_range = GetSpellMinRange(srange);
4269
4270    if(Player* modOwner = m_caster->GetSpellModOwner())
4271        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range, this);
4272
4273    Unit *target = m_targets.getUnitTarget();
4274
4275    if(target && target != m_caster)
4276    {
4277        // distance from target center in checks
4278        if(!m_caster->IsWithinCombatDist(target, max_range))
4279            return SPELL_FAILED_OUT_OF_RANGE;               //0x5A;
4280        if(min_range && m_caster->IsWithinCombatDist(target, min_range)) // skip this check if min_range = 0
4281            return SPELL_FAILED_TOO_CLOSE;
4282        if( m_caster->GetTypeId() == TYPEID_PLAYER &&
4283            (m_spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT) && !m_caster->HasInArc( M_PI, target ) )
4284            return SPELL_FAILED_UNIT_NOT_INFRONT;
4285    }
4286
4287    if(m_targets.m_targetMask == TARGET_FLAG_DEST_LOCATION && m_targets.m_destX != 0 && m_targets.m_destY != 0 && m_targets.m_destZ != 0)
4288    {
4289        float dist = m_caster->GetDistance(m_targets.m_destX, m_targets.m_destY, m_targets.m_destZ);
4290        if(dist > max_range)
4291            return SPELL_FAILED_OUT_OF_RANGE;
4292        if(dist < min_range)
4293            return SPELL_FAILED_TOO_CLOSE;
4294    }
4295
4296    return 0;                                               // ok
4297}
4298
4299int32 Spell::CalculatePowerCost()
4300{
4301    // item cast not used power
4302    if(m_CastItem)
4303        return 0;
4304
4305    // Spell drain all exist power on cast (Only paladin lay of Hands)
4306    if (m_spellInfo->AttributesEx & SPELL_ATTR_EX_DRAIN_ALL_POWER)
4307    {
4308        // If power type - health drain all
4309        if (m_spellInfo->powerType == POWER_HEALTH)
4310            return m_caster->GetHealth();
4311        // Else drain all power
4312        if (m_spellInfo->powerType < MAX_POWERS)
4313            return m_caster->GetPower(Powers(m_spellInfo->powerType));
4314        sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id);
4315        return 0;
4316    }
4317
4318    // Base powerCost
4319    int32 powerCost = m_spellInfo->manaCost;
4320    // PCT cost from total amount
4321    if (m_spellInfo->ManaCostPercentage)
4322    {
4323        switch (m_spellInfo->powerType)
4324        {
4325            // health as power used
4326            case POWER_HEALTH:
4327                powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetCreateHealth() / 100;
4328                break;
4329            case POWER_MANA:
4330                powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetCreateMana() / 100;
4331                break;
4332            case POWER_RAGE:
4333            case POWER_FOCUS:
4334            case POWER_ENERGY:
4335            case POWER_HAPPINESS:
4336                //            case POWER_RUNES:
4337                powerCost += m_spellInfo->ManaCostPercentage * m_caster->GetMaxPower(Powers(m_spellInfo->powerType)) / 100;
4338                break;
4339            default:
4340                sLog.outError("Spell::CalculateManaCost: Unknown power type '%d' in spell %d", m_spellInfo->powerType, m_spellInfo->Id);
4341                return 0;
4342        }
4343    }
4344    SpellSchools school = GetFirstSchoolInMask(m_spellSchoolMask);
4345    // Flat mod from caster auras by spell school
4346    powerCost += m_caster->GetInt32Value(UNIT_FIELD_POWER_COST_MODIFIER + school);
4347    // Shiv - costs 20 + weaponSpeed*10 energy (apply only to non-triggered spell with energy cost)
4348    if ( m_spellInfo->AttributesEx4 & SPELL_ATTR_EX4_SPELL_VS_EXTEND_COST )
4349        powerCost += m_caster->GetAttackTime(OFF_ATTACK)/100;
4350    // Apply cost mod by spell
4351    if(Player* modOwner = m_caster->GetSpellModOwner())
4352        modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, powerCost, this);
4353
4354    if(m_spellInfo->Attributes & SPELL_ATTR_LEVEL_DAMAGE_CALCULATION)
4355        powerCost = int32(powerCost/ (1.117f* m_spellInfo->spellLevel / m_caster->getLevel() -0.1327f));
4356
4357    // PCT mod from user auras by school
4358    powerCost = int32(powerCost * (1.0f+m_caster->GetFloatValue(UNIT_FIELD_POWER_COST_MULTIPLIER+school)));
4359    if (powerCost < 0)
4360        powerCost = 0;
4361    return powerCost;
4362}
4363
4364uint8 Spell::CheckPower()
4365{
4366    // item cast not used power
4367    if(m_CastItem)
4368        return 0;
4369
4370    // health as power used - need check health amount
4371    if(m_spellInfo->powerType == POWER_HEALTH)
4372    {
4373        if(m_caster->GetHealth() <= m_powerCost)
4374            return SPELL_FAILED_CASTER_AURASTATE;
4375        return 0;
4376    }
4377    // Check valid power type
4378    if( m_spellInfo->powerType >= MAX_POWERS )
4379    {
4380        sLog.outError("Spell::CheckMana: Unknown power type '%d'", m_spellInfo->powerType);
4381        return SPELL_FAILED_UNKNOWN;
4382    }
4383    // Check power amount
4384    Powers powerType = Powers(m_spellInfo->powerType);
4385    if(m_caster->GetPower(powerType) < m_powerCost)
4386        return SPELL_FAILED_NO_POWER;
4387    else
4388        return 0;
4389}
4390
4391uint8 Spell::CheckItems()
4392{
4393    if (m_caster->GetTypeId() != TYPEID_PLAYER)
4394        return 0;
4395
4396    uint32 itemid, itemcount;
4397    Player* p_caster = (Player*)m_caster;
4398
4399    if(m_CastItem)
4400    {
4401        itemid = m_CastItem->GetEntry();
4402        if( !p_caster->HasItemCount(itemid,1) )
4403            return SPELL_FAILED_ITEM_NOT_READY;
4404        else
4405        {
4406            ItemPrototype const *proto = m_CastItem->GetProto();
4407            if(!proto)
4408                return SPELL_FAILED_ITEM_NOT_READY;
4409
4410            for (int i = 0; i<5; i++)
4411            {
4412                if (proto->Spells[i].SpellCharges)
4413                {
4414                    if(m_CastItem->GetSpellCharges(i)==0)
4415                        return SPELL_FAILED_NO_CHARGES_REMAIN;
4416                }
4417            }
4418
4419            uint32 ItemClass = proto->Class;
4420            if (ItemClass == ITEM_CLASS_CONSUMABLE && m_targets.getUnitTarget())
4421            {
4422                for (int i = 0; i < 3; i++)
4423                {
4424                    // skip check, pet not required like checks, and for TARGET_PET m_targets.getUnitTarget() is not the real target but the caster
4425                    if (m_spellInfo->EffectImplicitTargetA[i] == TARGET_PET)
4426                        continue;
4427
4428                    if (m_spellInfo->Effect[i] == SPELL_EFFECT_HEAL)
4429                        if (m_targets.getUnitTarget()->GetHealth() == m_targets.getUnitTarget()->GetMaxHealth())
4430                            return (uint8)SPELL_FAILED_ALREADY_AT_FULL_HEALTH;
4431
4432                    // Mana Potion, Rage Potion, Thistle Tea(Rogue), ...
4433                    if (m_spellInfo->Effect[i] == SPELL_EFFECT_ENERGIZE)
4434                    {
4435                        if(m_spellInfo->EffectMiscValue[i] < 0 || m_spellInfo->EffectMiscValue[i] >= MAX_POWERS)
4436                            return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER;
4437
4438                        Powers power = Powers(m_spellInfo->EffectMiscValue[i]);
4439
4440                        if (m_targets.getUnitTarget()->GetPower(power) == m_targets.getUnitTarget()->GetMaxPower(power))
4441                            return (uint8)SPELL_FAILED_ALREADY_AT_FULL_POWER;
4442                    }
4443                }
4444            }
4445        }
4446    }
4447
4448    if(m_targets.getItemTargetGUID())
4449    {
4450        if(m_caster->GetTypeId() != TYPEID_PLAYER)
4451            return SPELL_FAILED_BAD_TARGETS;
4452
4453        if(!m_targets.getItemTarget())
4454            return SPELL_FAILED_ITEM_GONE;
4455
4456        if(!m_targets.getItemTarget()->IsFitToSpellRequirements(m_spellInfo))
4457            return SPELL_FAILED_EQUIPPED_ITEM_CLASS;
4458    }
4459    // if not item target then required item must be equipped
4460    else
4461    {
4462        if(m_caster->GetTypeId() == TYPEID_PLAYER && !((Player*)m_caster)->HasItemFitToSpellReqirements(m_spellInfo))
4463            return SPELL_FAILED_EQUIPPED_ITEM_CLASS;
4464    }
4465
4466    if(m_spellInfo->RequiresSpellFocus)
4467    {
4468        CellPair p(Trinity::ComputeCellPair(m_caster->GetPositionX(), m_caster->GetPositionY()));
4469        Cell cell(p);
4470        cell.data.Part.reserved = ALL_DISTRICT;
4471
4472        GameObject* ok = NULL;
4473        Trinity::GameObjectFocusCheck go_check(m_caster,m_spellInfo->RequiresSpellFocus);
4474        Trinity::GameObjectSearcher<Trinity::GameObjectFocusCheck> checker(ok,go_check);
4475
4476        TypeContainerVisitor<Trinity::GameObjectSearcher<Trinity::GameObjectFocusCheck>, GridTypeMapContainer > object_checker(checker);
4477        CellLock<GridReadGuard> cell_lock(cell, p);
4478        cell_lock->Visit(cell_lock, object_checker, *MapManager::Instance().GetMap(m_caster->GetMapId(), m_caster));
4479
4480        if(!ok)
4481            return (uint8)SPELL_FAILED_REQUIRES_SPELL_FOCUS;
4482
4483        focusObject = ok;                                   // game object found in range
4484    }
4485
4486    if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_NO_REAGENT_WHILE_PREP &&
4487        m_caster->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PREPARATION)))
4488    {
4489        for(uint32 i=0;i<8;i++)
4490        {
4491            if(m_spellInfo->Reagent[i] <= 0)
4492                continue;
4493
4494            itemid    = m_spellInfo->Reagent[i];
4495            itemcount = m_spellInfo->ReagentCount[i];
4496
4497            // if CastItem is also spell reagent
4498            if( m_CastItem && m_CastItem->GetEntry() == itemid )
4499            {
4500                ItemPrototype const *proto = m_CastItem->GetProto();
4501                if(!proto)
4502                    return SPELL_FAILED_ITEM_NOT_READY;
4503                for(int s=0;s<5;s++)
4504                {
4505                    // CastItem will be used up and does not count as reagent
4506                    int32 charges = m_CastItem->GetSpellCharges(s);
4507                    if (proto->Spells[s].SpellCharges < 0 && abs(charges) < 2)
4508                    {
4509                        ++itemcount;
4510                        break;
4511                    }
4512                }
4513            }
4514            if( !p_caster->HasItemCount(itemid,itemcount) )
4515                return (uint8)SPELL_FAILED_ITEM_NOT_READY;      //0x54
4516        }
4517    }
4518
4519    uint32 totems = 2;
4520    for(int i=0;i<2;++i)
4521    {
4522        if(m_spellInfo->Totem[i] != 0)
4523        {
4524            if( p_caster->HasItemCount(m_spellInfo->Totem[i],1) )
4525            {
4526                totems -= 1;
4527                continue;
4528            }
4529        }else
4530        totems -= 1;
4531    }
4532    if(totems != 0)
4533        return (uint8)SPELL_FAILED_TOTEMS;                  //0x7C
4534
4535    //Check items for TotemCategory
4536    uint32 TotemCategory = 2;
4537    for(int i=0;i<2;++i)
4538    {
4539        if(m_spellInfo->TotemCategory[i] != 0)
4540        {
4541            if( p_caster->HasItemTotemCategory(m_spellInfo->TotemCategory[i]) )
4542            {
4543                TotemCategory -= 1;
4544                continue;
4545            }
4546        }
4547        else
4548            TotemCategory -= 1;
4549    }
4550    if(TotemCategory != 0)
4551        return (uint8)SPELL_FAILED_TOTEM_CATEGORY;          //0x7B
4552
4553    for(int i = 0; i < 3; i++)
4554    {
4555        switch (m_spellInfo->Effect[i])
4556        {
4557            case SPELL_EFFECT_CREATE_ITEM:
4558            {
4559                if (!m_IsTriggeredSpell && m_spellInfo->EffectItemType[i])
4560                {
4561                    ItemPosCountVec dest;
4562                    uint8 msg = p_caster->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->EffectItemType[i], 1 );
4563                    if (msg != EQUIP_ERR_OK )
4564                    {
4565                        p_caster->SendEquipError( msg, NULL, NULL );
4566                        return SPELL_FAILED_DONT_REPORT;
4567                    }
4568                }
4569                break;
4570            }
4571            case SPELL_EFFECT_ENCHANT_ITEM:
4572            {
4573                Item* targetItem = m_targets.getItemTarget();
4574                if(!targetItem)
4575                    return SPELL_FAILED_ITEM_NOT_FOUND;
4576
4577                if( targetItem->GetProto()->ItemLevel < m_spellInfo->baseLevel )
4578                    return SPELL_FAILED_LOWLEVEL;
4579                // Not allow enchant in trade slot for some enchant type
4580                if( targetItem->GetOwner() != m_caster )
4581                {
4582                    uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
4583                    SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4584                    if(!pEnchant)
4585                        return SPELL_FAILED_ERROR;
4586                    if (pEnchant->slot & ENCHANTMENT_CAN_SOULBOUND)
4587                        return SPELL_FAILED_NOT_TRADEABLE;
4588                }
4589                break;
4590            }
4591            case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY:
4592            {
4593                Item *item = m_targets.getItemTarget();
4594                if(!item)
4595                    return SPELL_FAILED_ITEM_NOT_FOUND;
4596                // Not allow enchant in trade slot for some enchant type
4597                if( item->GetOwner() != m_caster )
4598                {
4599                    uint32 enchant_id = m_spellInfo->EffectMiscValue[i];
4600                    SpellItemEnchantmentEntry const *pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
4601                    if(!pEnchant)
4602                        return SPELL_FAILED_ERROR;
4603                    if (pEnchant->slot & ENCHANTMENT_CAN_SOULBOUND)
4604                        return SPELL_FAILED_NOT_TRADEABLE;
4605                }
4606                break;
4607            }
4608            case SPELL_EFFECT_ENCHANT_HELD_ITEM:
4609                // check item existence in effect code (not output errors at offhand hold item effect to main hand for example
4610                break;
4611            case SPELL_EFFECT_DISENCHANT:
4612            {
4613                if(!m_targets.getItemTarget())
4614                    return SPELL_FAILED_CANT_BE_DISENCHANTED;
4615
4616                // prevent disenchanting in trade slot
4617                if( m_targets.getItemTarget()->GetOwnerGUID() != m_caster->GetGUID() )
4618                    return SPELL_FAILED_CANT_BE_DISENCHANTED;
4619
4620                ItemPrototype const* itemProto = m_targets.getItemTarget()->GetProto();
4621                if(!itemProto)
4622                    return SPELL_FAILED_CANT_BE_DISENCHANTED;
4623
4624                uint32 item_quality = itemProto->Quality;
4625                // 2.0.x addon: Check player enchanting level agains the item desenchanting requirements
4626                uint32 item_disenchantskilllevel = itemProto->RequiredDisenchantSkill;
4627                if (item_disenchantskilllevel == uint32(-1))
4628                    return SPELL_FAILED_CANT_BE_DISENCHANTED;
4629                if (item_disenchantskilllevel > p_caster->GetSkillValue(SKILL_ENCHANTING))
4630                    return SPELL_FAILED_LOW_CASTLEVEL;
4631                if(item_quality > 4 || item_quality < 2)
4632                    return SPELL_FAILED_CANT_BE_DISENCHANTED;
4633                if(itemProto->Class != ITEM_CLASS_WEAPON && itemProto->Class != ITEM_CLASS_ARMOR)
4634                    return SPELL_FAILED_CANT_BE_DISENCHANTED;
4635                if (!itemProto->DisenchantID)
4636                    return SPELL_FAILED_CANT_BE_DISENCHANTED;
4637                break;
4638            }
4639            case SPELL_EFFECT_PROSPECTING:
4640            {
4641                if(!m_targets.getItemTarget())
4642                    return SPELL_FAILED_CANT_BE_PROSPECTED;
4643                //ensure item is a prospectable ore
4644                if(!(m_targets.getItemTarget()->GetProto()->BagFamily & BAG_FAMILY_MASK_MINING_SUPP) || m_targets.getItemTarget()->GetProto()->Class != ITEM_CLASS_TRADE_GOODS)
4645                    return SPELL_FAILED_CANT_BE_PROSPECTED;
4646                //prevent prospecting in trade slot
4647                if( m_targets.getItemTarget()->GetOwnerGUID() != m_caster->GetGUID() )
4648                    return SPELL_FAILED_CANT_BE_PROSPECTED;
4649                //Check for enough skill in jewelcrafting
4650                uint32 item_prospectingskilllevel = m_targets.getItemTarget()->GetProto()->RequiredSkillRank;
4651                if(item_prospectingskilllevel >p_caster->GetSkillValue(SKILL_JEWELCRAFTING))
4652                    return SPELL_FAILED_LOW_CASTLEVEL;
4653                //make sure the player has the required ores in inventory
4654                if(m_targets.getItemTarget()->GetCount() < 5)
4655                    return SPELL_FAILED_PROSPECT_NEED_MORE;
4656
4657                if(!LootTemplates_Prospecting.HaveLootFor(m_targets.getItemTargetEntry()))
4658                    return SPELL_FAILED_CANT_BE_PROSPECTED;
4659
4660                break;
4661            }
4662            case SPELL_EFFECT_WEAPON_DAMAGE:
4663            case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
4664            {
4665                if(m_caster->GetTypeId() != TYPEID_PLAYER) return SPELL_FAILED_TARGET_NOT_PLAYER;
4666                if( m_attackType != RANGED_ATTACK )
4667                    break;
4668                Item *pItem = ((Player*)m_caster)->GetWeaponForAttack(m_attackType);
4669                if(!pItem || pItem->IsBroken())
4670                    return SPELL_FAILED_EQUIPPED_ITEM;
4671
4672                switch(pItem->GetProto()->SubClass)
4673                {
4674                    case ITEM_SUBCLASS_WEAPON_THROWN:
4675                    {
4676                        uint32 ammo = pItem->GetEntry();
4677                        if( !((Player*)m_caster)->HasItemCount( ammo, 1 ) )
4678                            return SPELL_FAILED_NO_AMMO;
4679                    };  break;
4680                    case ITEM_SUBCLASS_WEAPON_GUN:
4681                    case ITEM_SUBCLASS_WEAPON_BOW:
4682                    case ITEM_SUBCLASS_WEAPON_CROSSBOW:
4683                    {
4684                        uint32 ammo = ((Player*)m_caster)->GetUInt32Value(PLAYER_AMMO_ID);
4685                        if(!ammo)
4686                        {
4687                            // Requires No Ammo
4688                            if(m_caster->GetDummyAura(46699))
4689                                break;                      // skip other checks
4690
4691                            return SPELL_FAILED_NO_AMMO;
4692                        }
4693
4694                        ItemPrototype const *ammoProto = objmgr.GetItemPrototype( ammo );
4695                        if(!ammoProto)
4696                            return SPELL_FAILED_NO_AMMO;
4697
4698                        if(ammoProto->Class != ITEM_CLASS_PROJECTILE)
4699                            return SPELL_FAILED_NO_AMMO;
4700
4701                        // check ammo ws. weapon compatibility
4702                        switch(pItem->GetProto()->SubClass)
4703                        {
4704                            case ITEM_SUBCLASS_WEAPON_BOW:
4705                            case ITEM_SUBCLASS_WEAPON_CROSSBOW:
4706                                if(ammoProto->SubClass!=ITEM_SUBCLASS_ARROW)
4707                                    return SPELL_FAILED_NO_AMMO;
4708                                break;
4709                            case ITEM_SUBCLASS_WEAPON_GUN:
4710                                if(ammoProto->SubClass!=ITEM_SUBCLASS_BULLET)
4711                                    return SPELL_FAILED_NO_AMMO;
4712                                break;
4713                            default:
4714                                return SPELL_FAILED_NO_AMMO;
4715                        }
4716
4717                        if( !((Player*)m_caster)->HasItemCount( ammo, 1 ) )
4718                            return SPELL_FAILED_NO_AMMO;
4719                    };  break;
4720                    case ITEM_SUBCLASS_WEAPON_WAND:
4721                    default:
4722                        break;
4723                }
4724                break;
4725            }
4726            default:break;
4727        }
4728    }
4729
4730    return uint8(0);
4731}
4732
4733void Spell::Delayed()
4734{
4735    if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER)
4736        return;
4737
4738    if (m_spellState == SPELL_STATE_DELAYED)
4739        return;                                             // spell is active and can't be time-backed
4740
4741    // spells not loosing casting time ( slam, dynamites, bombs.. )
4742    if(!(m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE))
4743        return;
4744
4745    //check resist chance
4746    int32 resistChance = 100;                               //must be initialized to 100 for percent modifiers
4747    ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this);
4748    resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100;
4749    if (roll_chance_i(resistChance))
4750        return;
4751
4752    int32 delaytime = GetNextDelayAtDamageMsTime();
4753
4754    if(int32(m_timer) + delaytime > m_casttime)
4755    {
4756        delaytime = m_casttime - m_timer;
4757        m_timer = m_casttime;
4758    }
4759    else
4760        m_timer += delaytime;
4761
4762    sLog.outDetail("Spell %u partially interrupted for (%d) ms at damage",m_spellInfo->Id,delaytime);
4763
4764    WorldPacket data(SMSG_SPELL_DELAYED, 8+4);
4765    data.append(m_caster->GetPackGUID());
4766    data << uint32(delaytime);
4767
4768    m_caster->SendMessageToSet(&data,true);
4769}
4770
4771void Spell::DelayedChannel()
4772{
4773    if(!m_caster || m_caster->GetTypeId() != TYPEID_PLAYER || getState() != SPELL_STATE_CASTING)
4774        return;
4775
4776    //check resist chance
4777    int32 resistChance = 100;                               //must be initialized to 100 for percent modifiers
4778    ((Player*)m_caster)->ApplySpellMod(m_spellInfo->Id,SPELLMOD_NOT_LOSE_CASTING_TIME,resistChance, this);
4779    resistChance += m_caster->GetTotalAuraModifier(SPELL_AURA_RESIST_PUSHBACK) - 100;
4780    if (roll_chance_i(resistChance))
4781        return;
4782
4783    int32 delaytime = GetNextDelayAtDamageMsTime();
4784
4785    if(int32(m_timer) < delaytime)
4786    {
4787        delaytime = m_timer;
4788        m_timer = 0;
4789    }
4790    else
4791        m_timer -= delaytime;
4792
4793    sLog.outDebug("Spell %u partially interrupted for %i ms, new duration: %u ms", m_spellInfo->Id, delaytime, m_timer);
4794
4795    for(std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin();ihit != m_UniqueTargetInfo.end();++ihit)
4796    {
4797        if ((*ihit).missCondition == SPELL_MISS_NONE)
4798        {
4799            Unit* unit = m_caster->GetGUID()==ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
4800            if (unit)
4801            {
4802                for (int j=0;j<3;j++)
4803                    if( ihit->effectMask & (1<<j) )
4804                        unit->DelayAura(m_spellInfo->Id, j, delaytime);
4805            }
4806
4807        }
4808    }
4809
4810    for(int j = 0; j < 3; j++)
4811    {
4812        // partially interrupt persistent area auras
4813        DynamicObject* dynObj = m_caster->GetDynObject(m_spellInfo->Id, j);
4814        if(dynObj)
4815            dynObj->Delay(delaytime);
4816    }
4817
4818    SendChannelUpdate(m_timer);
4819}
4820
4821void Spell::UpdatePointers()
4822{
4823    if(m_originalCasterGUID==m_caster->GetGUID())
4824        m_originalCaster = m_caster;
4825    else
4826    {
4827        m_originalCaster = ObjectAccessor::GetUnit(*m_caster,m_originalCasterGUID);
4828        if(m_originalCaster && !m_originalCaster->IsInWorld()) m_originalCaster = NULL;
4829    }
4830
4831    m_targets.Update(m_caster);
4832}
4833
4834bool Spell::IsAffectedBy(SpellEntry const *spellInfo, uint32 effectId)
4835{
4836    return spellmgr.IsAffectedBySpell(m_spellInfo,spellInfo->Id,effectId,spellInfo->EffectItemType[effectId]);
4837}
4838
4839bool Spell::CheckTargetCreatureType(Unit* target) const
4840{
4841    uint32 spellCreatureTargetMask = m_spellInfo->TargetCreatureType;
4842
4843    // Curse of Doom : not find another way to fix spell target check :/
4844    if(m_spellInfo->SpellFamilyName==SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags == 0x0200000000LL)
4845    {
4846        // not allow cast at player
4847        if(target->GetTypeId()==TYPEID_PLAYER)
4848            return false;
4849
4850        spellCreatureTargetMask = 0x7FF;
4851    }
4852
4853    // Dismiss Pet and Taming Lesson skipped
4854    if(m_spellInfo->Id == 2641 || m_spellInfo->Id == 23356)
4855        spellCreatureTargetMask =  0;
4856
4857    if (spellCreatureTargetMask)
4858    {
4859        uint32 TargetCreatureType = target->GetCreatureTypeMask();
4860
4861        return !TargetCreatureType || (spellCreatureTargetMask & TargetCreatureType);
4862    }
4863    return true;
4864}
4865
4866CurrentSpellTypes Spell::GetCurrentContainer()
4867{
4868    if (IsNextMeleeSwingSpell())
4869        return(CURRENT_MELEE_SPELL);
4870    else if (IsAutoRepeat())
4871        return(CURRENT_AUTOREPEAT_SPELL);
4872    else if (IsChanneledSpell(m_spellInfo))
4873        return(CURRENT_CHANNELED_SPELL);
4874    else
4875        return(CURRENT_GENERIC_SPELL);
4876}
4877
4878bool Spell::CheckTarget( Unit* target, uint32 eff, bool hitPhase )
4879{
4880    // Check targets for creature type mask and remove not appropriate (skip explicit self target case, maybe need other explicit targets)
4881    if(m_spellInfo->EffectImplicitTargetA[eff]!=TARGET_SELF && !m_magnetPair.first)
4882    {
4883        if (!CheckTargetCreatureType(target))
4884            return false;
4885    }
4886
4887    // Check targets for not_selectable unit flag and remove
4888    // A player can cast spells on his pet (or other controlled unit) though in any state
4889    if (target != m_caster && target->GetCharmerOrOwnerGUID() != m_caster->GetGUID())
4890    {
4891        // any unattackable target skipped
4892        if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
4893            return false;
4894
4895        // unselectable targets skipped in all cases except TARGET_SCRIPT targeting
4896        // in case TARGET_SCRIPT target selected by server always and can't be cheated
4897        if( target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE) &&
4898            m_spellInfo->EffectImplicitTargetA[eff] != TARGET_SCRIPT &&
4899            m_spellInfo->EffectImplicitTargetB[eff] != TARGET_SCRIPT )
4900            return false;
4901    }
4902
4903    //Check player targets and remove if in GM mode or GM invisibility (for not self casting case)
4904    if( target != m_caster && target->GetTypeId()==TYPEID_PLAYER)
4905    {
4906        if(((Player*)target)->GetVisibility()==VISIBILITY_OFF)
4907            return false;
4908
4909        if(((Player*)target)->isGameMaster() && !IsPositiveSpell(m_spellInfo->Id))
4910            return false;
4911    }
4912
4913    //Check targets for LOS visibility (except spells without range limitations )
4914    switch(m_spellInfo->Effect[eff])
4915    {
4916        case SPELL_EFFECT_SUMMON_PLAYER:                    // from anywhere
4917            break;
4918        case SPELL_EFFECT_DUMMY:
4919            if(m_spellInfo->Id!=20577)                      // Cannibalize
4920                break;
4921            //fall through
4922        case SPELL_EFFECT_RESURRECT_NEW:
4923            // player far away, maybe his corpse near?
4924            if(target!=m_caster && !target->IsWithinLOSInMap(m_caster))
4925            {
4926                if(!m_targets.getCorpseTargetGUID())
4927                    return false;
4928
4929                Corpse *corpse = ObjectAccessor::GetCorpse(*m_caster,m_targets.getCorpseTargetGUID());
4930                if(!corpse)
4931                    return false;
4932
4933                if(target->GetGUID()!=corpse->GetOwnerGUID())
4934                    return false;
4935
4936                if(!corpse->IsWithinLOSInMap(m_caster))
4937                    return false;
4938            }
4939
4940            // all ok by some way or another, skip normal check
4941            break;
4942        default:                                            // normal case
4943            if(target!=m_caster && !target->IsWithinLOSInMap(m_caster))
4944                return false;
4945            break;
4946    }
4947
4948    return true;
4949}
4950
4951Unit* Spell::SelectMagnetTarget()
4952{
4953    Unit* target = m_targets.getUnitTarget();
4954
4955    if(target && target->HasAuraType(SPELL_AURA_SPELL_MAGNET) && !(m_spellInfo->Attributes & 0x10))
4956    {
4957        Unit::AuraList const& magnetAuras = target->GetAurasByType(SPELL_AURA_SPELL_MAGNET);
4958        for(Unit::AuraList::const_iterator itr = magnetAuras.begin(); itr != magnetAuras.end(); ++itr)
4959        {
4960            if(Unit* magnet = (*itr)->GetCaster())
4961            {
4962                if((*itr)->m_procCharges>0 && magnet->IsWithinLOSInMap(m_caster))
4963                {
4964                    (*itr)->SetAuraProcCharges((*itr)->m_procCharges-1);
4965                    m_magnetPair.first = true;
4966                    m_magnetPair.second = magnet;
4967
4968                    target = magnet;
4969                    m_targets.setUnitTarget(target);
4970                    break;
4971                }
4972            }
4973        }
4974    }
4975
4976    return target;
4977}
4978
4979bool Spell::IsNeedSendToClient() const
4980{
4981    return m_spellInfo->SpellVisual!=0 || IsChanneledSpell(m_spellInfo) ||
4982        m_spellInfo->speed > 0.0f || !m_triggeredByAuraSpell && !m_IsTriggeredSpell;
4983}
4984
4985bool Spell::HaveTargetsForEffect( uint8 effect ) const
4986{
4987    for(std::list<TargetInfo>::const_iterator itr= m_UniqueTargetInfo.begin();itr != m_UniqueTargetInfo.end();++itr)
4988        if(itr->effectMask & (1<<effect))
4989            return true;
4990
4991    for(std::list<GOTargetInfo>::const_iterator itr= m_UniqueGOTargetInfo.begin();itr != m_UniqueGOTargetInfo.end();++itr)
4992        if(itr->effectMask & (1<<effect))
4993            return true;
4994
4995    for(std::list<ItemTargetInfo>::const_iterator itr= m_UniqueItemInfo.begin();itr != m_UniqueItemInfo.end();++itr)
4996        if(itr->effectMask & (1<<effect))
4997            return true;
4998
4999    return false;
5000}
5001
5002SpellEvent::SpellEvent(Spell* spell) : BasicEvent()
5003{
5004    m_Spell = spell;
5005}
5006
5007SpellEvent::~SpellEvent()
5008{
5009    if (m_Spell->getState() != SPELL_STATE_FINISHED)
5010        m_Spell->cancel();
5011
5012    if (m_Spell->IsDeletable())
5013    {
5014        delete m_Spell;
5015    }
5016    else
5017    {
5018        sLog.outError("~SpellEvent: %s %u tried to delete non-deletable spell %u. Was not deleted, causes memory leak.",
5019            (m_Spell->GetCaster()->GetTypeId()==TYPEID_PLAYER?"Player":"Creature"), m_Spell->GetCaster()->GetGUIDLow(),m_Spell->m_spellInfo->Id);
5020    }
5021}
5022
5023bool SpellEvent::Execute(uint64 e_time, uint32 p_time)
5024{
5025    // update spell if it is not finished
5026    if (m_Spell->getState() != SPELL_STATE_FINISHED)
5027        m_Spell->update(p_time);
5028
5029    // check spell state to process
5030    switch (m_Spell->getState())
5031    {
5032        case SPELL_STATE_FINISHED:
5033        {
5034            // spell was finished, check deletable state
5035            if (m_Spell->IsDeletable())
5036            {
5037                // check, if we do have unfinished triggered spells
5038
5039                return(true);                               // spell is deletable, finish event
5040            }
5041            // event will be re-added automatically at the end of routine)
5042        } break;
5043
5044        case SPELL_STATE_CASTING:
5045        {
5046            // this spell is in channeled state, process it on the next update
5047            // event will be re-added automatically at the end of routine)
5048        } break;
5049
5050        case SPELL_STATE_DELAYED:
5051        {
5052            // first, check, if we have just started
5053            if (m_Spell->GetDelayStart() != 0)
5054            {
5055                // no, we aren't, do the typical update
5056                // check, if we have channeled spell on our hands
5057                if (IsChanneledSpell(m_Spell->m_spellInfo))
5058                {
5059                    // evented channeled spell is processed separately, casted once after delay, and not destroyed till finish
5060                    // check, if we have casting anything else except this channeled spell and autorepeat
5061                    if (m_Spell->GetCaster()->IsNonMeleeSpellCasted(false, true, true))
5062                    {
5063                        // another non-melee non-delayed spell is casted now, abort
5064                        m_Spell->cancel();
5065                    }
5066                    else
5067                    {
5068                        // do the action (pass spell to channeling state)
5069                        m_Spell->handle_immediate();
5070                    }
5071                    // event will be re-added automatically at the end of routine)
5072                }
5073                else
5074                {
5075                    // run the spell handler and think about what we can do next
5076                    uint64 t_offset = e_time - m_Spell->GetDelayStart();
5077                    uint64 n_offset = m_Spell->handle_delayed(t_offset);
5078                    if (n_offset)
5079                    {
5080                        // re-add us to the queue
5081                        m_Spell->GetCaster()->m_Events.AddEvent(this, m_Spell->GetDelayStart() + n_offset, false);
5082                        return(false);                      // event not complete
5083                    }
5084                    // event complete
5085                    // finish update event will be re-added automatically at the end of routine)
5086                }
5087            }
5088            else
5089            {
5090                // delaying had just started, record the moment
5091                m_Spell->SetDelayStart(e_time);
5092                // re-plan the event for the delay moment
5093                m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + m_Spell->GetDelayMoment(), false);
5094                return(false);                              // event not complete
5095            }
5096        } break;
5097
5098        default:
5099        {
5100            // all other states
5101            // event will be re-added automatically at the end of routine)
5102        } break;
5103    }
5104
5105    // spell processing not complete, plan event on the next update interval
5106    m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + 1, false);
5107    return(false);                                          // event not complete
5108}
5109
5110void SpellEvent::Abort(uint64 /*e_time*/)
5111{
5112    // oops, the spell we try to do is aborted
5113    if (m_Spell->getState() != SPELL_STATE_FINISHED)
5114        m_Spell->cancel();
5115}
Note: See TracBrowser for help on using the browser.