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

Revision 203, 197.3 kB (checked in by yumileroy, 17 years ago)

[svn] Send AttackStart? package when update visibility.
Update DoMeleeAttackIfReady? to support dual wield.
Show player modelid2 instead id3 of triggers. This should fix the bug that gameobject::castspell summon a human model.
Remove the correct flag to make creature attackable. This should fix the bug that Illidan and Magtheridon are unattackable.
Add NullCreatureAI for trinityscript.
Fix channeler's soul transfer.
Some update of black temple scripts.

Original author: megamage
Date: 2008-11-09 14:54:13-06:00

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