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

Revision 285, 197.8 kB (checked in by yumileroy, 17 years ago)

* Added missing part of mangos merge on interrupt channeling on aura cancel
* Removed hacks attempting to do the above only for possessing or farsight spells
* Moved summon as possessed unsummoning into more general area in Spell::cancel
* Added SQL updates for steam tonk and tonk mine scripts

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