OregonCore  revision 3611e8a-git
Your Favourite TBC server
Spell.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Common.h"
19 #include "Database/DatabaseEnv.h"
20 #include "WorldPacket.h"
21 #include "WorldSession.h"
22 #include "GridNotifiers.h"
23 #include "GridNotifiersImpl.h"
24 #include "Opcodes.h"
25 #include "Log.h"
26 #include "UpdateMask.h"
27 #include "World.h"
28 #include "ObjectMgr.h"
29 #include "SpellMgr.h"
30 #include "Player.h"
31 #include "Pet.h"
32 #include "Unit.h"
33 #include "Spell.h"
34 #include "DynamicObject.h"
35 #include "SpellAuras.h"
36 #include "UpdateData.h"
37 #include "ObjectAccessor.h"
38 #include "CellImpl.h"
39 #include "SharedDefines.h"
40 #include "LootMgr.h"
41 #include "VMapFactory.h"
42 #include "Battleground.h"
43 #include "Util.h"
44 #include "TemporarySummon.h"
45 #include "GameEventMgr.h"
46 #include "DisableMgr.h"
47 #include "ConditionMgr.h"
48 
49 #define SPELL_CHANNEL_UPDATE_INTERVAL (1*IN_MILLISECONDS)
50 
52 
53 bool IsQuestTameSpell(uint32 spellId)
54 {
55  SpellEntry const* spellproto = sSpellStore.LookupEntry(spellId);
56  if (!spellproto) return false;
57 
58  return spellproto->Effect[0] == SPELL_EFFECT_THREAT
59  && spellproto->Effect[1] == SPELL_EFFECT_APPLY_AURA && spellproto->EffectApplyAuraName[1] == SPELL_AURA_DUMMY;
60 }
61 
63 {
64  m_unitTarget = NULL;
65  m_itemTarget = NULL;
66  m_GOTarget = NULL;
67 
68  m_unitTargetGUID = 0;
69  m_GOTargetGUID = 0;
71  m_itemTargetGUID = 0;
73 
74  m_srcPos.Relocate(0, 0, 0, 0);
75  m_strTarget = "";
76  m_targetMask = 0;
77 }
78 
80 {
81 }
82 
84 {
85  if (!target)
86  return;
87 
88  m_unitTarget = target;
89  m_unitTargetGUID = target->GetGUID();
91 }
92 
93 void SpellCastTargets::setSrc(float x, float y, float z)
94 {
95  m_srcPos.Relocate(x, y, z);
97 }
98 
100 {
101  if (pos)
102  {
103  m_srcPos.Relocate(pos);
105  }
106 }
107 
108 void SpellCastTargets::setDst(float x, float y, float z, float orientation, uint32 mapId)
109 {
110  m_dstPos.Relocate(x, y, z, orientation);
112  if (mapId != MAPID_INVALID)
113  m_dstPos.m_mapId = mapId;
114 }
115 
117 {
118  if (pos)
119  {
120  m_dstPos.Relocate(pos);
122  }
123 }
124 
126 {
127  m_GOTarget = target;
128  m_GOTargetGUID = target->GetGUID();
129  // m_targetMask |= TARGET_FLAG_OBJECT;
130 }
131 
133 {
134  if (!item)
135  return;
136 
137  m_itemTarget = item;
138  m_itemTargetGUID = item->GetGUID();
139  m_itemTargetEntry = item->GetEntry();
141 }
142 
144 {
145  m_CorpseTargetGUID = corpse->GetGUID();
146 }
147 
149 {
153  NULL;
154 
155  m_itemTarget = NULL;
156  if (caster->GetTypeId() == TYPEID_PLAYER)
157  {
161  {
162  // here it is not guid but slot. Also prevent hacking slots
163  Player* pTrader = caster->ToPlayer()->GetTrader();
164  if (pTrader && m_itemTargetGUID.GetRawValue() < TRADE_SLOT_COUNT)
166  }
167  if (m_itemTarget)
169  }
170 }
171 
173 {
174  data >> m_targetMask;
175 
176  if (m_targetMask == TARGET_FLAG_SELF)
177  return;
178 
179  // TARGET_FLAG_UNK2 is used for non-combat pets, maybe other?
180  if (m_targetMask & (TARGET_FLAG_UNIT | TARGET_FLAG_UNK2))
181  data >> m_unitTargetGUID.ReadAsPacked();
182 
184  data >> m_GOTargetGUID.ReadAsPacked();
185 
186  if ((m_targetMask & (TARGET_FLAG_ITEM | TARGET_FLAG_TRADE_ITEM)) && caster->GetTypeId() == TYPEID_PLAYER)
187  data >> m_itemTargetGUID.ReadAsPacked();
188 
189  if (m_targetMask & TARGET_FLAG_SOURCE_LOCATION)
190  {
192  if (!m_srcPos.IsPositionValid())
193  throw ByteBufferException(false, data.rpos(), 0, data.size());
194  }
195 
196  if (m_targetMask & TARGET_FLAG_DEST_LOCATION)
197  {
199  if (!m_dstPos.IsPositionValid())
200  throw ByteBufferException(false, data.rpos(), 0, data.size());
201  }
202 
203  if (m_targetMask & TARGET_FLAG_STRING)
204  data >> m_strTarget;
205 
206  if (m_targetMask & (TARGET_FLAG_CORPSE | TARGET_FLAG_PVP_CORPSE))
208 
209  // find real units/GOs
210  Update(caster);
211 }
212 
214 {
215  data << uint32(m_targetMask);
216 
218  {
220  {
221  if (m_unitTarget)
222  data << m_unitTarget->GetPackGUID();
223  else
224  data << uint8(0);
225  }
227  {
228  if (m_GOTarget)
229  data << m_GOTarget->GetPackGUID();
230  else
231  data << uint8(0);
232  }
235  else
236  data << uint8(0);
237  }
238 
240  {
241  if (m_itemTarget)
242  data << m_itemTarget->GetPackGUID();
243  else
244  data << uint8(0);
245  }
246 
249 
252 
254  data << m_strTarget;
255 }
256 
257 Spell::Spell(Unit* Caster, SpellEntry const* info, bool triggered, uint64 originalCasterGUID, Spell** triggeringContainer, bool skipCheck)
258  : m_spellInfo(info)
259  , m_caster(Caster)
260  , m_spellValue(new SpellValue(m_spellInfo))
261 {
262  m_customAttr = sSpellMgr.GetSpellCustomAttr(m_spellInfo->Id);
263  m_skipCheck = skipCheck;
264  m_selfContainer = NULL;
265  m_triggeringContainer = triggeringContainer;
267  m_executedCurrently = false;
269  m_delayStart = 0;
271  m_destroyed = false;
272 
274 
275  // Get data for type of attack
276  switch (m_spellInfo->DmgClass)
277  {
281  else
283  break;
286  break;
287  default:
288  // Wands
291  else
293  break;
294  }
295 
296  m_spellSchoolMask = GetSpellSchoolMask(info); // Can be override for some spell (wand shoot for example)
297 
299  // wand case
302  m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetProto()->Damage->DamageType);
303 
304  // Set health leech amount to zero
305  m_healthLeech = 0;
306 
307  if (originalCasterGUID)
308  m_originalCasterGUID = originalCasterGUID;
309  else
311 
314  else
315  {
318  m_originalCaster = NULL;
319  }
320 
321  for (int i = 0; i < 3; ++i)
323 
325 
327  m_TriggerSpells.clear();
328  m_IsTriggeredSpell = bool(triggered || info->AttributesEx4 & SPELL_ATTR4_TRIGGERED);
329  //m_AreaAura = false;
330  m_CastItem = NULL;
331  m_castItemGUID = 0;
332 
333  unitTarget = NULL;
334  itemTarget = NULL;
335  gameObjTarget = NULL;
336  focusObject = NULL;
337  m_cast_count = 0;
338  m_triggeredByAuraSpell = NULL;
339 
340  //Auto Shot & Shoot
342 
343  m_powerCost = 0; // setup to correct value in Spell::prepare, don't must be used before.
344  m_casttime = 0; // setup to correct value in Spell::prepare, don't must be used before.
345  m_timer = 0; // will set to castime in prepare
346 
348 
349  // Determine if spell can be reflected back to the caster
350  // Patch 1.2 notes: Spell Reflection no longer reflects abilities
354 
357 
359 }
360 
362 {
363  m_destroyed = true;
364 
365  delete m_spellValue;
366 }
367 
368 void ResizeUnitListByDistance(std::list<Unit*> &_list, WorldObject* source, uint32 _size, bool _keepnearest)
369 {
370  float d;
371  std::list<Unit*>::iterator _i;
372  ASSERT(_size >= 0);
373  while(_list.size() > _size)
374  {
375  d = source->GetDistance((*_list.begin()));
376  _i = _list.begin();
377  for(std::list<Unit*>::iterator itr = _list.begin(); itr != _list.end(); itr++)
378  {
379  if((_keepnearest && source->GetDistance(*itr) > d) || (!_keepnearest && source->GetDistance(*itr) < d))
380  {
381  d = source->GetDistance(*itr);
382  _i = itr;
383  }
384  }
385  _list.erase(_i);
386  }
387 }
388 
390 {
391  for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
392  {
393  // not call for empty effect.
394  // Also some spells use not used effect targets for store targets for dummy effect in triggered spells
395  if (!m_spellInfo->Effect[i])
396  continue;
397 
398  uint32 effectTargetType = sSpellMgr.EffectTargetType[m_spellInfo->Effect[i]];
399 
400  // is it possible that areaaura is not applied to caster?
401  if (effectTargetType == SPELL_REQUIRE_NONE)
402  continue;
403 
406 
407  if (targetA)
408  SetTargetMap(i, targetA);
409  if (targetB) // In very rare case !A && B
410  SetTargetMap(i, targetB);
411 
412  if (effectTargetType != SPELL_REQUIRE_UNIT)
413  {
414  if (effectTargetType == SPELL_REQUIRE_CASTER)
416  else if (effectTargetType == SPELL_REQUIRE_ITEM)
417  {
418  if (m_targets.getItemTarget())
420  }
421  continue;
422  }
423 
424  if (!targetA && !targetB)
425  {
426  // add here custom effects that need default target.
427  // FOR EVERY TARGET TYPE THERE IS A DIFFERENT FILL!!
428  switch (m_spellInfo->Effect[i])
429  {
430  case SPELL_EFFECT_DUMMY:
431  {
432  switch (m_spellInfo->Id)
433  {
434  case 20577: // Cannibalize
435  {
436  // non-standard target selection
437  SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
438  float max_range = GetSpellMaxRange(srange);
439  WorldObject* result = NULL;
440 
441  Oregon::CannibalizeObjectCheck u_check(m_caster, max_range);
443  m_caster->VisitNearbyGridObject(max_range, searcher);
444  if (!result)
445  m_caster->VisitNearbyWorldObject(max_range, searcher);
446 
447 
448  if (result)
449  {
450  switch (result->GetTypeId())
451  {
452  case TYPEID_UNIT:
453  case TYPEID_PLAYER:
454  AddUnitTarget((Unit*)result, i);
455  break;
456  case TYPEID_CORPSE:
457  m_targets.setCorpseTarget((Corpse*)result);
458  if (Player* owner = ObjectAccessor::FindPlayer(((Corpse*)result)->GetOwnerGUID()))
459  AddUnitTarget(owner, i);
460  break;
461  }
462  }
463  else
464  {
465  // clear cooldown at fail
466  if (m_caster->GetTypeId() == TYPEID_PLAYER)
469  finish(false);
470  }
471  break;
472  }
473  default:
474  if (m_targets.getUnitTarget())
476  break;
477  }
478  break;
479  }
480  case SPELL_EFFECT_BIND:
488  if (m_targets.getUnitTarget())
490  else
492  break;
495  {
496  Player* target = sObjectMgr.GetPlayer(m_caster->ToPlayer()->GetSelection());
497  if (target)
498  AddUnitTarget(target, i);
499  }
500  break;
502  if (m_targets.getUnitTarget())
505  {
507  if (corpse)
508  {
509  Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID());
510  if (owner)
511  AddUnitTarget(owner, i);
512  }
513  }
514  break;
517  case SPELL_EFFECT_STUCK:
520  break;
522  if (Guardian* pet = m_caster->GetGuardianPet())
523  AddUnitTarget(pet, i);
524  break;
525  /*case SPELL_EFFECT_ENCHANT_ITEM:
526  case SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY:
527  case SPELL_EFFECT_DISENCHANT:
528  case SPELL_EFFECT_FEED_PET:
529  case SPELL_EFFECT_PROSPECTING:
530  if (m_targets.getItemTarget())
531  AddItemTarget(m_targets.getItemTarget(), i);
532  break;*/
535  break;
537  // AreaAura
538  if (m_spellInfo->Attributes == 0x9050000 || m_spellInfo->Attributes == 0x10000)
540  break;
542  if (m_targets.getUnitTarget())
544  else if (m_targets.getCorpseTargetGUID())
545  {
547  if (corpse)
548  {
549  Player* owner = ObjectAccessor::FindPlayer(corpse->GetOwnerGUID());
550  if (owner)
551  AddUnitTarget(owner, i);
552  }
553  }
554  break;
556  if (!m_caster->ToPlayer())
557  break;
558 
559  // Special message for this Spell (if not ready)
561  {
563  finish(false);
564  return;
565  }
566 
567  if (sObjectMgr.GetRAFLinkedBuddyForPlayer(m_caster->ToPlayer()))
569  break;
570  default:
571  break;
572  }
573  }
574  }
575 
576  if (m_targets.HasDst())
577  {
578  if (m_spellInfo->speed > 0.0f)
579  {
580  float dist = m_caster->GetDistance(m_targets.m_dstPos);
581  if (dist < 5.0f) dist = 5.0f;
582  m_delayMoment = (uint64) floor(dist / m_spellInfo->speed * 1000.0f);
583  }
584  }
585 
586  // m_targets is originally sent by client and its values are used
587  // in single target casts. It may occur that we have set implicit
588  // targets but we need to change m_targets too for those checks
589 
590  if (!m_targets.getUnitTarget() && m_UniqueTargetInfo.size())
591  if (uint64 targetGUID = (*m_UniqueTargetInfo.begin()).targetGUID)
592  if (Unit* target = m_caster->GetGUID() == targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, targetGUID))
593  m_targets.setUnitTarget(target);
594 
595  if (!m_targets.getGOTarget() && m_UniqueGOTargetInfo.size())
596  if (uint64 targetGUID = (*m_UniqueGOTargetInfo.begin()).targetGUID)
597  if (GameObject* target = m_caster->GetMap()->GetGameObject(targetGUID))
598  m_targets.setGOTarget(target);
599 
600  if (!m_targets.getItemTarget() && m_UniqueItemInfo.size())
601  if (Item* target = (*m_UniqueItemInfo.begin()).item)
602  m_targets.setItemTarget(target);
603 }
604 
606 {
607  //==========================================================================================
608  // Now fill data for trigger system, need know:
609  // can spell trigger another or not (m_canTrigger)
610  // Create base triggers flags for Attacker and Victim (m_procAttacker and m_procVictim)
611  //==========================================================================================
612 
613  // Fill flag can spell trigger or not
614  if (!m_IsTriggeredSpell)
615  m_canTrigger = true; // Normal cast - can trigger
616  else if (!m_triggeredByAuraSpell)
617  m_canTrigger = true; // Triggered from SPELL_EFFECT_TRIGGER_SPELL - can trigger
618  else // Exceptions (some periodic triggers)
619  {
620  m_canTrigger = false; // Triggered spells can`t trigger another
621  switch (m_spellInfo->SpellFamilyName)
622  {
623  case SPELLFAMILY_MAGE: // Arcane Missles / Blizzard / Molten Armor triggers need do it
624  if (m_spellInfo->SpellFamilyFlags & 0x0000000800200080LL) m_canTrigger = true;
625  break;
626  case SPELLFAMILY_WARLOCK: // For Hellfire Effect / Rain of Fire / Soul Fire triggers need do it
627  if (m_spellInfo->SpellFamilyFlags & 0x0000800000000060LL) m_canTrigger = true;
628  if (m_spellInfo->SpellFamilyFlags & 0x0000008000000060LL)
629  {
632  m_canTrigger = true;
633  }
634  break;
635  case SPELLFAMILY_HUNTER: // Hunter Explosive Trap Effect/Immolation Trap Effect/Frost Trap Aura/Snake Trap Effect
636  if (m_spellInfo->SpellFamilyFlags & 0x0000200000000014LL) m_canTrigger = true;
637  break;
638  case SPELLFAMILY_PALADIN: // For Holy Shock, SoC and SoB triggers need to do it
639  if (m_spellInfo->SpellFamilyFlags & 0x0001040002200000LL) m_canTrigger = true;
640  break;
641  case SPELLFAMILY_ROGUE: // mutilate mainhand + offhand
642  if (m_spellInfo->SpellFamilyFlags & 0x600000000LL) m_canTrigger = true;
643  break;
644  case SPELLFAMILY_SHAMAN:
645  // Lightning Shield
646  if (m_spellInfo->SpellFamilyFlags & 0x0000000000000400LL) m_canTrigger = true;
647  break;
648  }
649  }
650 
652  m_canTrigger = false; // Do not trigger from item cast spell(except potions)
653 
655  // Get data for type of attack and fill base info for trigger
656  switch (m_spellInfo->DmgClass)
657  {
660  if (m_attackType == OFF_ATTACK)
662  else
665  break;
667  // Auto attack
669  {
672  }
673  else // Ranged spell attack
674  {
677  }
678  break;
679  default:
680  if (IsPositiveSpell(m_spellInfo->Id)) // Check for positive spell
681  {
684  }
685  else if (m_spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG) // Wands auto attack
686  {
689  }
690  else // Negative spell
691  {
694  }
695  break;
696  }
697 
700  m_canTrigger = true;
701 
703  m_canTrigger = false;
704 
705  // Hunter traps spells (for Entrapment trigger)
706  // Gives your Immolation Trap, Frost Trap, Explosive Trap, and Snake Trap ....
709 }
710 
712 {
713  // m_UniqueTargetInfo.clear();
714  // m_UniqueGOTargetInfo.clear();
715 
716  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
717  ihit->deleted = true;
718 
719  for (std::list<GOTargetInfo>::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
720  ihit->deleted = true;
721 
722  m_UniqueItemInfo.clear();
723  m_countOfHit = 0;
724  m_countOfMiss = 0;
725  m_delayMoment = 0;
726 }
727 
728 void Spell::AddUnitTarget(Unit* pVictim, uint32 effIndex)
729 {
730  if (m_spellInfo->Effect[effIndex] == 0)
731  return;
732 
733  if (!CheckTarget(pVictim, effIndex))
734  return;
735 
736  // Lookup target in already in list
737  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
738  {
739  if (ihit->deleted)
740  continue;
741 
742  if (pVictim->GetGUID() == ihit->targetGUID) // Found in list
743  {
744  ihit->effectMask |= 1 << effIndex; // Add only effect
745  return;
746  }
747  }
748 
749  // Get spell hit result on target
750  TargetInfo target;
751  target.targetGUID = pVictim->GetGUID(); // Store target GUID
752  target.effectMask = 1 << effIndex;
753  target.processed = false; // Effects not apply on target
754  target.damage = 0;
755  target.crit = false;
756  target.deleted = false;
757 
758  // Add target to list
759  m_UniqueTargetInfo.push_back(target);
760 }
761 
763 {
764  for (std::list<TargetInfo>::iterator it = m_UniqueTargetInfo.begin(); it != m_UniqueTargetInfo.end(); ++it)
765  {
766  TargetInfo& target = *it;
767 
768  Unit* pVictim = m_caster->GetGUID() == target.targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target.targetGUID);
769 
770  if (!pVictim)
771  continue;
772 
773  // Remove effects the target is immune to
774  for (uint32 effIndex = 0; effIndex < 3; ++effIndex)
775  {
776  if (target.effectMask & (1 << effIndex))
777  if (pVictim->IsImmuneToSpellEffect(m_spellInfo, effIndex, false))
778  target.effectMask &= ~(1 << effIndex);
779 
781  if (target.effectMask & (1 << effIndex))
782  m_needAliveTargetMask |= (1 << effIndex);
783  }
784 
785  // Calculate hit result
786  if (m_originalCaster)
787  {
788  bool canMiss = (m_triggeredByAuraSpell || !m_IsTriggeredSpell);
792  }
793  else
794  target.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE;
795 
796  if (target.missCondition == SPELL_MISS_NONE)
797  ++m_countOfHit;
798  else
799  ++m_countOfMiss;
800 
801  // Spell have speed - need calculate incoming time
802  if (m_spellInfo->speed > 0.0f)
803  {
804  // calculate spell incoming interval
805  float dist = m_caster->GetDistance(pVictim->GetPositionX(), pVictim->GetPositionY(), pVictim->GetPositionZ());
806 
807  if (dist < 5.0f)
808  dist = 5.0f;
809  target.timeDelay = (uint64)std::floor(dist / m_spellInfo->speed * 1000.0f);
810 
811  // Calculate minimum incoming time
812  if (m_delayMoment == 0 || m_delayMoment > target.timeDelay)
813  m_delayMoment = target.timeDelay;
814  }
815  else
816  target.timeDelay = 0LL;
817 
818  // If target reflect spell back to caster
819  if (target.missCondition == SPELL_MISS_REFLECT)
820  {
821  // Calculate reflected spell result on caster
823 
824  if (target.reflectResult == SPELL_MISS_REFLECT) // Impossible reflect again, so simply deflect spell
826 
827  // Increase time interval for reflected spells by 1.5
828  target.timeDelay += target.timeDelay >> 1;
829  }
830  else
832  }
833 }
834 
835 void Spell::AddUnitTarget(uint64 unitGUID, uint32 effIndex)
836 {
837  Unit* unit = m_caster->GetGUID() == unitGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, unitGUID);
838  if (unit)
839  AddUnitTarget(unit, effIndex);
840 }
841 
842 void Spell::AddGOTarget(GameObject* pVictim, uint32 effIndex)
843 {
844  if (m_spellInfo->Effect[effIndex] == 0)
845  return;
846 
847  uint64 targetGUID = pVictim->GetGUID();
848 
849  // Lookup target in already in list
850  for (std::list<GOTargetInfo>::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
851  {
852  if (ihit->deleted)
853  continue;
854 
855  if (targetGUID == ihit->targetGUID) // Found in list
856  {
857  ihit->effectMask |= (1 << effIndex); // Add only effect mask
858  return;
859  }
860  }
861 
862  // This is new target calculate data for him
863 
864  GOTargetInfo target;
865  target.targetGUID = targetGUID;
866  target.effectMask = (1 << effIndex);
867  target.processed = false; // Effects not apply on target
868  target.deleted = false;
869 
870  // Spell have speed - need calculate incoming time
871  if (m_spellInfo->speed > 0.0f)
872  {
873  // calculate spell incoming interval
874  float dist = m_caster->GetDistance(pVictim->GetPositionX(), pVictim->GetPositionY(), pVictim->GetPositionZ());
875  if (dist < 5.0f)
876  dist = 5.0f;
877  target.timeDelay = (uint64) floor(dist / m_spellInfo->speed * 1000.0f);
878  if (m_delayMoment == 0 || m_delayMoment > target.timeDelay)
879  m_delayMoment = target.timeDelay;
880  }
881  else
882  target.timeDelay = 0LL;
883 
884  ++m_countOfHit;
885 
886  // Add target to list
887  m_UniqueGOTargetInfo.push_back(target);
888 }
889 
890 void Spell::AddGOTarget(uint64 goGUID, uint32 effIndex)
891 {
892  GameObject* go = m_caster->GetMap()->GetGameObject(goGUID);
893  if (go)
894  AddGOTarget(go, effIndex);
895 }
896 
897 void Spell::AddItemTarget(Item* pitem, uint32 effIndex)
898 {
899  if (m_spellInfo->Effect[effIndex] == 0)
900  return;
901 
902  // Lookup target in already in list
903  for (std::list<ItemTargetInfo>::iterator ihit = m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
904  {
905  if (pitem == ihit->item) // Found in list
906  {
907  ihit->effectMask |= (1 << effIndex); // Add only effect mask
908  return;
909  }
910  }
911 
912  // This is new target add data
913 
914  ItemTargetInfo target;
915  target.item = pitem;
916  target.effectMask = (1 << effIndex);
917  m_UniqueItemInfo.push_back(target);
918 }
919 
921 {
922  if (!target || target == (TargetInfo*)0x10 || target->processed || m_spellInfo->Id > MAX_SPELL_ID) // Check target
923  return;
924 
925  target->processed = true; // Target checked in apply effects procedure
926 
927  // Get mask of effects for target
928  uint8 mask = target->effectMask;
929 
930  Unit* unit = m_caster->GetGUID() == target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target->targetGUID);
931 
932  if (!unit)
933  {
934  uint8 farMask = 0;
935  // create far target mask
936  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
938  if ((1 << i) & mask)
939  farMask |= (1 << i);
940 
941  if (!farMask)
942  return;
943  // find unit in world
944  unit = ObjectAccessor::FindUnit(target->targetGUID);
945  if (!unit)
946  return;
947 
948  // do far effects on the unit
949  // can't use default call because of threading, do stuff as fast as possible
950  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
951  if (farMask & (1 << i))
952  HandleEffects(unit, NULL, NULL, i);
953  return;
954  }
955 
957  return; // No missinfo in that case
958 
959  // Get original caster (if exist) and calculate damage/healing from him data
961 
962  // Skip if m_originalCaster not avaiable
963  if (!caster)
964  return;
965 
966  SpellMissInfo missInfo = target->missCondition;
967 
968  // Need init unitTarget by default unit (can changed in code on reflect)
969  // Or on missInfo != SPELL_MISS_NONE unitTarget undefined (but need in trigger subsystem)
970  unitTarget = unit;
971 
972  // Reset damage/healing counter
973  m_damage = target->damage;
974  m_healing = -target->damage;
975 
976  // Fill base trigger info
977  uint32 procAttacker = m_procAttacker;
978  uint32 procVictim = m_procVictim;
979  uint32 procEx = PROC_EX_NONE;
980 
981  if (missInfo == SPELL_MISS_NONE) // In case spell hit target, do all effect on that target
982  DoSpellHitOnUnit(unit, mask);
983  else if (missInfo == SPELL_MISS_REFLECT) // In case spell reflect from target, do all effect on caster (if hit)
984  {
985  if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him
986  {
987  DoSpellHitOnUnit(m_caster, mask);
988  caster = unit;
989  }
990  }
991 
992  // Do not take combo points on dodge and miss
994  if (missInfo != SPELL_MISS_NONE)
995  m_needComboPoints = false;
996 
997  // All calculated do it!
998  // Do healing and triggers
999  if (m_healing > 0)
1000  {
1001  bool crit = caster->isSpellCrit(NULL, m_spellInfo, m_spellSchoolMask);
1002  uint32 addhealth = m_healing;
1003  if (crit)
1004  {
1005  procEx |= PROC_EX_CRITICAL_HIT;
1006  addhealth = caster->SpellCriticalBonus(m_spellInfo, addhealth, NULL);
1007  }
1008  else
1009  procEx |= PROC_EX_NORMAL_HIT;
1010 
1011  caster->SendHealSpellLog(unitTarget, m_spellInfo->Id, addhealth, crit);
1012 
1013  // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
1014  if (missInfo != SPELL_MISS_REFLECT)
1015  caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_canTrigger);
1016 
1017  int32 gain = unitTarget->ModifyHealth(int32(addhealth));
1018  if (m_IsTriggeredSpell)
1019  /* @todo: Test me
1020  spells like earth shield and prayer of mending
1021  should give threat to the target they were casted on */
1022  unitTarget->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, m_spellInfo);
1023  else
1024  caster->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, m_spellInfo);
1025 
1026  if (caster->GetTypeId() == TYPEID_PLAYER)
1027  if (Battleground* bg = caster->ToPlayer()->GetBattleground())
1028  bg->UpdatePlayerScore(caster->ToPlayer(), SCORE_HEALING_DONE, gain);
1029 
1030  }
1031  // Do damage and triggers
1032  else if (m_damage > 0)
1033  {
1034  // Fill base damage struct (unitTarget - is real spell target)
1036 
1037  // Add bonuses and fill damageInfo struct
1038  caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit);
1039 
1040  // Send log damage message to client
1041  caster->SendSpellNonMeleeDamageLog(&damageInfo);
1042 
1043  procEx = createProcExtendMask(&damageInfo, missInfo);
1044  procVictim |= PROC_FLAG_TAKEN_DAMAGE;
1045 
1046  caster->DealSpellDamage(&damageInfo, true);
1047 
1048  // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
1049  if (missInfo != SPELL_MISS_REFLECT)
1050  {
1051  caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo, m_canTrigger);
1053  caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx, m_spellInfo);
1054  }
1055 
1056  // Judgement of Blood
1058  {
1059  int32 damagePoint = damageInfo.damage * 33 / 100;
1060  m_caster->CastCustomSpell(m_caster, 32220, &damagePoint, NULL, NULL, true);
1061  }
1062  // Bloodthirst
1063  else if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR && m_spellInfo->SpellFamilyFlags & 0x40000000000LL)
1064  {
1065  uint32 BTAura = 0;
1066  switch (m_spellInfo->Id)
1067  {
1068  case 23881:
1069  BTAura = 23885;
1070  break;
1071  case 23892:
1072  BTAura = 23886;
1073  break;
1074  case 23893:
1075  BTAura = 23887;
1076  break;
1077  case 23894:
1078  BTAura = 23888;
1079  break;
1080  case 25251:
1081  BTAura = 25252;
1082  break;
1083  case 30335:
1084  BTAura = 30339;
1085  break;
1086  default:
1087  sLog.outError("Spell::EffectSchoolDMG: Spell %u not handled in BTAura", m_spellInfo->Id);
1088  break;
1089  }
1090  if (BTAura)
1091  m_caster->CastSpell(m_caster, BTAura, true);
1092  }
1093  }
1094  // Passive spell hits/misses or active spells only misses (only triggers)
1095  else
1096  {
1097  // Fill base damage struct (unitTarget - is real spell target)
1099  procEx = createProcExtendMask(&damageInfo, missInfo);
1100  // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
1101  if (missInfo != SPELL_MISS_REFLECT)
1102  caster->ProcDamageAndSpell(unit, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_canTrigger);
1103 
1104  // Failed Pickpocket, reveal rogue
1106  {
1110  }
1111  }
1112 
1113  // Call scripted function for AI if this spell is casted upon a creature (except pets)
1114  if (IS_CREATURE_GUID(target->targetGUID))
1115  {
1116  // cast at creature (or GO) quest objectives update at successful cast finished (+channel finished)
1117  // ignore autorepeat/melee casts for speed (not exist quest for spells (hm...)
1120  }
1121 
1122  if (missInfo != SPELL_MISS_EVADE && missInfo != SPELL_MISS_REFLECT
1123  && m_caster && !m_caster->IsFriendlyTo(unit) &&
1125  {
1127 
1129  if (!unit->IsStandState())
1131  }
1132 
1133  if (unit->IsPvP() && m_caster->GetTypeId() == TYPEID_PLAYER && (unit->GetTypeId() == TYPEID_PLAYER || unit->IsInCombat()))
1134  m_caster->ToPlayer()->UpdatePvP(true);
1135 }
1136 
1137 void Spell::DoSpellHitOnUnit(Unit* unit, const uint32 effectMask)
1138 {
1139  if (!unit || !effectMask)
1140  return;
1141 
1142  // Recheck immune (only for delayed spells)
1143  if (m_spellInfo->speed &&
1145  && (unit->IsImmunedToDamage(GetSpellSchoolMask(m_spellInfo), true) ||
1146  unit->IsImmuneToSpell(m_spellInfo, true)))
1147  {
1149  m_damage = 0;
1150  return;
1151  }
1152 
1153  if (m_caster != unit)
1154  {
1155  if (unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID())
1156  {
1158  {
1159  if (! (sSpellMgr.GetSpellCustomAttr(m_spellInfo->Id) & SPELL_ATTR_CU_ANY_TARGET))
1160  {
1162  m_damage = 0;
1163  return;
1164  }
1165  }
1166  }
1167  if (m_caster->IsValidAttackTarget(unit))
1168  {
1172  }
1173  else if (m_caster->IsFriendlyTo(unit))
1174  {
1175  // for delayed spells ignore negative spells (after duel end) for friendly targets
1176  // @todo this cause soul transfer bugged
1177  if (m_spellInfo->speed > 0.0f && unit->GetTypeId() == TYPEID_PLAYER && !IsPositiveSpell(m_spellInfo->Id))
1178  {
1180  m_damage = 0;
1181  return;
1182  }
1183 
1184  // assisting case, healing and resurrection
1186  {
1188  if (m_caster->GetTypeId() == TYPEID_PLAYER)
1189  m_caster->ToPlayer()->UpdatePvP(true);
1190  }
1192  {
1193  m_caster->SetInCombatState(unit->GetCombatTimer() > 0, unit);
1195  }
1196  }
1197  }
1198 
1199  uint8 aura_effmask = 0;
1200  for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
1201  if (effectMask & (1 << i) && m_spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AURA)
1202  aura_effmask |= 1 << i;
1203 
1204  // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add
1206  if (m_diminishGroup && aura_effmask)
1207  {
1209  // send immunity message if target is immune
1211  {
1213  return;
1214  }
1215 
1217  // Increase Diminishing on unit, current informations for actually casts will use values above
1218  if ((type == DRTYPE_PLAYER && (unit->GetTypeId() == TYPEID_PLAYER || unit->IsPet() || unit->ToCreature()->isPossessedByPlayer())) || type == DRTYPE_ALL)
1220  }
1221 
1222  for (uint32 effectNumber = 0; effectNumber < 3; effectNumber++)
1223  if (effectMask & (1 << effectNumber))
1224  HandleEffects(unit, NULL, NULL, effectNumber);
1225 
1226  if (unit->GetTypeId() == TYPEID_UNIT && unit->ToCreature()->IsAIEnabled)
1227  unit->ToCreature()->AI()->SpellHit(m_caster, m_spellInfo);
1228 
1231 
1232  // trigger only for first effect targets
1233  if (m_ChanceTriggerSpells.size() && (effectMask & 0x1))
1234  {
1235  int _duration = 0;
1236  for (ChanceTriggerSpells::const_iterator i = m_ChanceTriggerSpells.begin(); i != m_ChanceTriggerSpells.end(); ++i)
1237  {
1238  if (roll_chance_i(i->second))
1239  {
1240  m_caster->CastSpell(unit, i->first, true);
1241  // SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration
1242  // set duration equal to triggering spell
1243  if (GetSpellDuration(i->first) == -1)
1244  {
1245  // get duration from aura-only once
1246  if (!_duration)
1247  {
1249  _duration = aur ? aur->GetAuraDuration() : -1;
1250  }
1251  unit->SetAurasDurationByCasterSpell(i->first->Id, m_caster->GetGUID(), _duration);
1252  }
1253  }
1254  }
1255  }
1256 
1258  {
1259  if (const std::vector<int32>* spell_triggered = sSpellMgr.GetSpellLinked(m_spellInfo->Id + SPELL_LINK_HIT))
1260  {
1261  for (std::vector<int32>::const_iterator i = spell_triggered->begin(); i != spell_triggered->end(); ++i)
1262  if (*i < 0)
1263  unit->RemoveAurasDueToSpell(-(*i));
1264  else
1265  unit->CastSpell(unit, *i, true, 0, 0, m_caster->GetGUID());
1266  }
1267  }
1268 }
1269 
1271 {
1272  if (!target || target == (GOTargetInfo*)0x10 || target->processed || m_spellInfo->Id > MAX_SPELL_ID) // Check target
1273  return;
1274 
1275  target->processed = true; // Target checked in apply effects procedure
1276 
1277  uint32 effectMask = target->effectMask;
1278  if (!effectMask)
1279  return;
1280 
1281  GameObject* go = m_caster->GetMap()->GetGameObject(target->targetGUID);
1282  if (!go)
1283  return;
1284 
1285  for (uint32 effectNumber = 0; effectNumber < 3; effectNumber++)
1286  if (effectMask & (1 << effectNumber))
1287  HandleEffects(NULL, NULL, go, effectNumber);
1288 
1289  sLog.outString("CASTED %u on GUID: " UI64FMTD ", entry: %u", m_spellInfo->Id, go->GetGUID(), go->GetGOInfo()->id);
1290 
1291  // cast at creature (or GO) quest objectives update at successful cast finished (+channel finished)
1292  // ignore autorepeat/melee casts for speed (not exist quest for spells (hm...)
1295 }
1296 
1298 {
1299  uint32 effectMask = target->effectMask;
1300  if (!target->item || !effectMask)
1301  return;
1302 
1303  for (uint32 effectNumber = 0; effectNumber < 3; effectNumber++)
1304  if (effectMask & (1 << effectNumber))
1305  HandleEffects(NULL, target->item, NULL, effectNumber);
1306 }
1307 
1309 {
1310  // Not need check return true
1311  if (m_needAliveTargetMask == 0)
1312  return true;
1313 
1314  uint8 needAliveTargetMask = m_needAliveTargetMask;
1315 
1316  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
1317  {
1318  if (ihit->deleted)
1319  continue;
1320 
1321  if (ihit->missCondition == SPELL_MISS_NONE && (needAliveTargetMask & ihit->effectMask))
1322  {
1323  Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
1324 
1325  if (unit && unit->IsAlive())
1326  needAliveTargetMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target
1327  }
1328  }
1329 
1330  // is all effects from m_needAliveTargetMask have alive targets
1331  return needAliveTargetMask == 0;
1332 }
1333 
1334 // Helper for Chain Healing
1335 // Spell target first
1336 // Raidmates then descending by injury suffered (MaxHealth - Health)
1337 // Other players/mobs then descending by injury suffered (MaxHealth - Health)
1338 struct ChainHealingOrder : public std::binary_function<const Unit*, const Unit*, bool>
1339 {
1341  ChainHealingOrder(Unit const* Target) : MainTarget(Target) {};
1342  // functor for operator ">"
1343  bool operator()(Unit const* _Left, Unit const* _Right) const
1344  {
1345  return (ChainHealingHash(_Left) < ChainHealingHash(_Right));
1346  }
1347 
1349  {
1350  /*if (Target == MainTarget)
1351  return 0;
1352  else*/ if (Target->GetTypeId() == TYPEID_PLAYER && MainTarget->GetTypeId() == TYPEID_PLAYER &&
1353  Target->ToPlayer()->IsInSameRaidWith((Player const*)MainTarget))
1354  {
1355  if (Target->GetHealth() == Target->GetMaxHealth())
1356  return 40000;
1357  else
1358  return 20000 - Target->GetMaxHealth() + Target->GetHealth();
1359  }
1360  else
1361  return 40000 - Target->GetMaxHealth() + Target->GetHealth();
1362  }
1363 };
1364 
1365 // Helper for targets nearest to the spell target
1366 // The spell target is always first unless there is a target at _completely_ the same position (unbelievable case)
1367 struct TargetDistanceOrder : public std::binary_function<const Unit, const Unit, bool>
1368 {
1370  TargetDistanceOrder(const Unit* Target) : MainTarget(Target) {};
1371  // functor for operator ">"
1372  bool operator()(const Unit* _Left, const Unit* _Right) const
1373  {
1374  return (MainTarget->GetDistance(_Left) < MainTarget->GetDistance(_Right));
1375  }
1376 };
1377 
1378 void Spell::SearchChainTarget(std::list<Unit*>& TagUnitMap, float max_range, uint32 num, SpellTargets TargetType)
1379 {
1380  Unit* cur = m_targets.getUnitTarget();
1381  if (!cur)
1382  return;
1383 
1384  //FIXME: This very like horrible hack and wrong for most spells
1386  max_range += num * CHAIN_SPELL_JUMP_RADIUS;
1387 
1388  std::list<Unit*> tempUnitMap;
1389  if (TargetType == SPELL_TARGETS_CHAINHEAL)
1390  {
1391  SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, SPELL_TARGETS_ALLY);
1392  tempUnitMap.sort(ChainHealingOrder(m_caster));
1393  //if (cur->GetHealth() == cur->GetMaxHealth() && tempUnitMap.size())
1394  // cur = tempUnitMap.front();
1395  }
1396  else
1397  SearchAreaTarget(tempUnitMap, max_range, PUSH_CHAIN, TargetType);
1398  tempUnitMap.remove(cur);
1399 
1400  while (num)
1401  {
1402  TagUnitMap.push_back(cur);
1403  --num;
1404 
1405  if (tempUnitMap.empty())
1406  break;
1407 
1408  std::list<Unit*>::iterator next;
1409 
1410  if (TargetType == SPELL_TARGETS_CHAINHEAL)
1411  {
1412  next = tempUnitMap.begin();
1413  while (cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS
1414  || !cur->IsWithinLOSInMap(*next))
1415  {
1416  ++next;
1417  if (next == tempUnitMap.end())
1418  return;
1419  }
1420  }
1421  else
1422  {
1423  tempUnitMap.sort(TargetDistanceOrder(cur));
1424  next = tempUnitMap.begin();
1425 
1426  if (cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
1427  break;
1429  && !m_caster->isInFrontInMap(*next, max_range))
1430  || !m_caster->CanSeeOrDetect(*next)
1431  || !cur->IsWithinLOSInMap(*next))
1432  {
1433  ++next;
1434  if (next == tempUnitMap.end() || cur->GetDistance(*next) > CHAIN_SPELL_JUMP_RADIUS)
1435  return;
1436  }
1437  }
1438 
1439  cur = *next;
1440  tempUnitMap.erase(next);
1441  }
1442 }
1443 
1444 void Spell::SearchAreaTarget(std::list<Unit*>& TagUnitMap, float radius, const uint32 type, SpellTargets TargetType, uint32 entry)
1445 {
1446  Position* pos;
1447  switch (type)
1448  {
1449  case PUSH_DST_CENTER:
1450  CheckDst();
1451  pos = &m_targets.m_dstPos;
1452  break;
1453  case PUSH_SRC_CENTER:
1454  CheckSrc();
1455  pos = &m_targets.m_srcPos;
1456  break;
1457  case PUSH_CHAIN:
1458  {
1459  Unit* target = m_targets.getUnitTarget();
1460  if (!target)
1461  {
1462  sLog.outError("SPELL: cannot find unit target for spell ID %u\n", m_spellInfo->Id);
1463  return;
1464  }
1465  pos = target;
1466  break;
1467  }
1468  default:
1469  pos = m_caster;
1470  break;
1471  }
1472 
1473  Oregon::SpellNotifierCreatureAndPlayer notifier(*this, TagUnitMap, radius, type, TargetType, pos, entry);
1474  if ((m_spellInfo->AttributesEx3 & SPELL_ATTR3_PLAYERS_ONLY) || (TargetType == SPELL_TARGETS_ENTRY && !entry))
1475  {
1476  m_caster->GetMap()->VisitWorld(pos->m_positionX, pos->m_positionY, radius, notifier);
1477  TagUnitMap.remove_if(Oregon::ObjectTypeIdCheck(TYPEID_PLAYER, false)); // above line will select also pets and totems, remove them
1478  }
1479  else
1480  m_caster->GetMap()->VisitAll(pos->m_positionX, pos->m_positionY, radius, notifier);
1481 }
1482 
1484 {
1485  switch (TargetType)
1486  {
1487  case SPELL_TARGETS_ENTRY:
1488  {
1489  ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
1490  if (conditions.empty())
1491  {
1492  sLog.outDebug("Spell (ID: %u) (caster Entry: %u) does not have record in `conditions` for spell script target (ConditionSourceType 13)", m_spellInfo->Id, m_caster->GetEntry());
1494  return SearchNearbyTarget(range, SPELL_TARGETS_ALLY);
1495  else
1496  return SearchNearbyTarget(range, SPELL_TARGETS_ENEMY);
1497  }
1498 
1499  Creature* creatureScriptTarget = NULL;
1500  GameObject* goScriptTarget = NULL;
1501 
1502  for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
1503  {
1504  if ((*i_spellST)->Type != CONDITION_SPELL_SCRIPT_TARGET)
1505  continue;
1506  switch((*i_spellST)->ConditionValue1)
1507  {
1509  if ((*i_spellST)->ConditionValue2)
1510  {
1511  if (GameObject *go = m_caster->FindNearestGameObject((*i_spellST)->ConditionValue2, range))
1512  {
1513  // remember found target and range, next attempt will find more near target with another entry
1514  goScriptTarget = go;
1515  creatureScriptTarget = NULL;
1516  range = m_caster->GetDistance(goScriptTarget);
1517  }
1518  }
1519  else if (focusObject) //Focus Object
1520  {
1521  float frange = m_caster->GetDistance(focusObject);
1522  if (range >= frange)
1523  {
1524  creatureScriptTarget = NULL;
1525  goScriptTarget = focusObject;
1526  range = frange;
1527  }
1528  }
1529  break;
1532  default:
1533  if (Creature *cre = m_caster->FindNearestCreature((*i_spellST)->ConditionValue2, range, (*i_spellST)->ConditionValue1 != SPELL_TARGET_TYPE_DEAD))
1534  {
1535  creatureScriptTarget = cre;
1536  goScriptTarget = NULL;
1537  range = m_caster->GetDistance(creatureScriptTarget);
1538  }
1539  break;
1540  }
1541  }
1542 
1543  if (creatureScriptTarget)
1544  return creatureScriptTarget;
1545  else
1546  return goScriptTarget;
1547  }
1548  default:
1549  case SPELL_TARGETS_ENEMY:
1550  {
1551  Unit* target = NULL;
1554  m_caster->VisitNearbyObject(range, searcher);
1555  return target;
1556  }
1557  case SPELL_TARGETS_ALLY:
1558  {
1559  Unit* target = NULL;
1562  m_caster->VisitNearbyObject(range, searcher);
1563  return target;
1564  }
1565  }
1566 }
1567 
1569 {
1570  SpellNotifyPushType pushType = PUSH_NONE;
1571  Player* modOwner = NULL;
1572  if (m_originalCaster)
1573  modOwner = m_originalCaster->GetSpellModOwner();
1574 
1575  switch (sSpellMgr.SpellTargetType[cur])
1576  {
1578  {
1579  switch (cur)
1580  {
1581  case TARGET_NONE:
1582  case TARGET_UNIT_CASTER:
1583  AddUnitTarget(m_caster, i);
1584  break;
1586  {
1587  float min_dis = GetSpellMinRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
1588  float max_dis = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
1589  float dis = rand_norm() * (max_dis - min_dis) + min_dis;
1590  float x, y, z, angle;
1591  angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
1592  m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle);
1593 
1594  float ground = z;
1595  float liquidLevel = m_caster->GetMap()->GetWaterOrGroundLevel(x, y, z, &ground);
1596  if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level
1597  {
1599  SendChannelUpdate(0);
1600  finish(false);
1601  return;
1602  }
1603 
1604  if (ground + 0.75 > liquidLevel)
1605  {
1607  SendChannelUpdate(0);
1608  finish(false);
1609  return;
1610  }
1611 
1612  m_targets.setDst(x, y, liquidLevel, m_caster->GetOrientation());
1613 
1614  break;
1615  }
1616  case TARGET_UNIT_MASTER:
1617  if (Unit* owner = m_caster->GetCharmerOrOwner())
1618  AddUnitTarget(owner, i);
1619  break;
1620  case TARGET_UNIT_PET:
1621  if (Player* plr = m_caster->ToPlayer())
1622  {
1623  if (Pet* pet = plr->GetPet())
1624  {
1625  AddUnitTarget(pet, i);
1626  break;
1627  }
1628  }
1629 
1630  if (Guardian* pet = m_caster->GetGuardianPet())
1631  AddUnitTarget(pet, i);
1632  break;
1635  pushType = PUSH_CASTER_CENTER;
1636  break;
1637  }
1638  break;
1639  }
1640 
1642  {
1643  Unit* target = m_targets.getUnitTarget();
1644  if (!target)
1645  {
1646  if (Player* player = m_caster->ToPlayer())
1647  target = ObjectAccessor::GetUnit(*player, player->GetSelection());
1648  else
1649  target = m_caster->GetVictim();
1650 
1651  if (target)
1652  m_targets.setUnitTarget(target);
1653  else
1654  {
1655  sLog.outError("SPELL: no unit target for spell ID %u", m_spellInfo->Id);
1656  break;
1657  }
1658  }
1659 
1660  switch (cur)
1661  {
1663  if ((m_spellInfo->AttributesEx & (0x8 | 0x80)) == 0)
1664  {
1665  // try to select magnet target first
1667  // if not found (target is not changed) search for SPELL_AURA_ADD_CASTER_HIT_TRIGGER
1669  }
1670  case TARGET_UNIT_CHAINHEAL:
1671  pushType = PUSH_CHAIN;
1672  break;
1674  AddUnitTarget(target, i);
1675  break;
1677  case TARGET_UNIT_TARGET_ANY: // SelectMagnetTarget()?
1680  if (IsValidSingleTargetSpell(target))
1681  AddUnitTarget(target, i);
1682  break;
1685  pushType = PUSH_CASTER_CENTER; // not real
1686  break;
1687  }
1688  break;
1689  }
1690 
1692  {
1693  float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
1694  if (modOwner)
1695  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
1696 
1697  WorldObject* target = NULL;
1698 
1699  switch (cur)
1700  {
1702  target = SearchNearbyTarget(range, SPELL_TARGETS_ENEMY);
1703  break;
1705  case TARGET_UNIT_NEARBY_PARTY: // TODO: fix party/raid targets
1707  target = SearchNearbyTarget(range, SPELL_TARGETS_ALLY);
1708  break;
1710  target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY);
1711  break;
1712  }
1713 
1714  if (!target)
1715  return;
1716  else if (target->GetTypeId() == TYPEID_UNIT || target->GetTypeId() == TYPEID_PLAYER)
1717  {
1718  pushType = PUSH_CHAIN;
1719  m_targets.setUnitTarget((Unit*)target);
1720  }
1721  else if (target->GetTypeId() == TYPEID_GAMEOBJECT)
1722  AddGOTarget((GameObject*)target, i);
1723 
1724  break;
1725  }
1726 
1727  case TARGET_TYPE_AREA_SRC:
1728  pushType = PUSH_SRC_CENTER;
1729  break;
1730 
1731  case TARGET_TYPE_AREA_DST:
1732  pushType = PUSH_DST_CENTER;
1733  break;
1734 
1735  case TARGET_TYPE_AREA_CONE:
1737  pushType = PUSH_IN_BACK;
1739  pushType = PUSH_IN_LINE;
1740  else
1741  pushType = PUSH_IN_FRONT;
1742  break;
1743 
1744  case TARGET_TYPE_DEST_CASTER: //4+8+2
1745  {
1746  if (cur == TARGET_SRC_CASTER)
1747  {
1749  break;
1750  }
1751  else if (cur == TARGET_DST_CASTER)
1752  {
1754  break;
1755  }
1756 
1757  float angle, dist;
1758 
1759  float objSize = m_caster->GetObjectSize();
1760  dist = GetSpellRadius(m_spellInfo, i, true);
1761  if (dist < objSize)
1762  dist = objSize;
1763  else if (cur == TARGET_DEST_CASTER_RANDOM)
1764  dist = objSize + (dist - objSize) * rand_norm();
1765 
1766  switch (cur)
1767  {
1769  angle = static_cast<float>(-M_PI / 4);
1770  break;
1772  angle = static_cast<float>(-3 * M_PI / 4);
1773  break;
1775  angle = static_cast<float>(3 * M_PI / 4);
1776  break;
1778  angle = static_cast<float>(M_PI / 4);
1779  break;
1780  case TARGET_MINION:
1783  angle = 0.0f;
1784  break;
1786  angle = static_cast<float>(M_PI);
1787  break;
1789  angle = static_cast<float>(-M_PI / 2);
1790  break;
1792  angle = static_cast<float>(M_PI / 2);
1793  break;
1794  default:
1795  angle = (float)rand_norm() * static_cast<float>(2 * M_PI);
1796  break;
1797  }
1798 
1799  Position pos;
1800  switch (cur)
1801  {
1807  pos = m_caster->GetFirstCollisionPosition(dist, angle);
1808  break;
1809  default:
1810  pos = m_caster->GetNearPosition(dist, angle);
1811  break;
1812  }
1813  m_targets.setDst(&pos); // also flag
1814  break;
1815  }
1816 
1817  case TARGET_TYPE_DEST_TARGET: //2+8+2
1818  {
1819  Unit* target = m_targets.getUnitTarget();
1820  if (!target)
1821  {
1822  sLog.outError("SPELL: no unit target for spell ID %u\n", m_spellInfo->Id);
1823  break;
1824  }
1825 
1826  if (cur == TARGET_DST_TARGET_ENEMY || cur == TARGET_DEST_TARGET_ANY)
1827  {
1828  m_targets.setDst(target);
1829  break;
1830  }
1831 
1832  float angle, dist;
1833 
1834  float objSize = target->GetObjectSize();
1835  dist = GetSpellRadius(m_spellInfo, i, false);
1836  if (dist < objSize)
1837  dist = objSize;
1838  else if (cur == TARGET_DEST_CASTER_RANDOM)
1839  dist = objSize + (dist - objSize) * rand_norm();
1840 
1841  switch (cur)
1842  {
1844  angle = 0.0f;
1845  break;
1847  angle = M_PI;
1848  break;
1850  angle = M_PI / 2;
1851  break;
1853  angle = -M_PI / 2;
1854  break;
1856  angle = -M_PI / 4;
1857  break;
1859  angle = -3 * M_PI / 4;
1860  break;
1862  angle = 3 * M_PI / 4;
1863  break;
1865  angle = M_PI / 4;
1866  break;
1867  default:
1868  angle = rand_norm() * 2 * M_PI;
1869  break;
1870  }
1871 
1872  Position pos;
1873  switch (cur)
1874  {
1883  {
1884  target->GetContactPoint(m_caster, pos.m_positionX, pos.m_positionY, pos.m_positionZ, dist);
1885  pos = target->GetFirstCollisionPosition(dist, angle);
1886  }
1887  break;
1888  default:
1889  pos = target->GetNearPosition(dist, angle);
1890  break;
1891  }
1892  m_targets.setDst(&pos);
1893  break;
1894  }
1895 
1896  case TARGET_TYPE_DEST_DEST: //5+8+1
1897  {
1898  if (!m_targets.HasDst())
1899  {
1900  sLog.outError("SPELL: no destination for spell ID %u\n", m_spellInfo->Id);
1901  break;
1902  }
1903 
1904  float angle;
1905  switch (cur)
1906  {
1910  case TARGET_DEST_DEST:
1911  case TARGET_DEST_TRAJ:
1912  return;
1914  angle = 0.0f;
1915  break;
1916  case TARGET_DEST_DEST_BACK:
1917  angle = M_PI;
1918  break;
1920  angle = M_PI / 2;
1921  break;
1922  case TARGET_DEST_DEST_LEFT:
1923  angle = -M_PI / 2;
1924  break;
1926  angle = -M_PI / 4;
1927  break;
1929  angle = -3 * M_PI / 4;
1930  break;
1932  angle = 3 * M_PI / 4;
1933  break;
1935  angle = float(M_PI) / 4;
1936  break;
1937  default:
1938  angle = rand_norm() * 2 * M_PI;
1939  break;
1940  }
1941 
1942  float dist;
1943  dist = GetSpellRadius(m_spellInfo, i, true);
1944  if (cur == TARGET_DEST_DEST_RANDOM)
1945  dist *= rand_norm();
1946 
1947  // must has dst, no need to set flag
1949  break;
1950  }
1951 
1953  {
1954  switch (cur)
1955  {
1956  case TARGET_DST_DB:
1957  if (SpellTargetPosition const* st = sSpellMgr.GetSpellTargetPosition(m_spellInfo->Id))
1958  {
1960  m_targets.setDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId);
1961  else if (st->target_mapId == m_caster->GetMapId())
1962  m_targets.setDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
1963  }
1964  else
1965  sLog.outError("SPELL: unknown target coordinates for spell ID %u\n", m_spellInfo->Id);
1966  break;
1967  case TARGET_DST_HOME:
1968  if (m_caster->GetTypeId() == TYPEID_PLAYER)
1970  break;
1972  {
1973  float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
1974  if (modOwner)
1975  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
1976 
1977  if (WorldObject* target = SearchNearbyTarget(range, SPELL_TARGETS_ENTRY))
1978  m_targets.setDst(target);
1979  break;
1980  }
1981  }
1982  break;
1983  }
1984 
1985  case TARGET_TYPE_CHANNEL:
1986  {
1988  {
1989  sLog.outDebug("SPELL: no current channeled spell for spell ID %u - spell triggering this spell was interrupted.", m_spellInfo->Id);
1990  break;
1991  }
1992 
1993  switch (cur)
1994  {
1995  case TARGET_UNIT_CHANNEL:
1997  AddUnitTarget(target, i);
1998  else
1999  sLog.outError("SPELL: cannot find channel spell target for spell ID %u", m_spellInfo->Id);
2000  break;
2001  case TARGET_DEST_CHANNEL:
2004  else
2005  sLog.outError("SPELL: cannot find channel spell destination for spell ID %u", m_spellInfo->Id);
2006  break;
2007  }
2008  break;
2009  }
2010 
2011  default:
2012  {
2013  switch (cur)
2014  {
2015  case TARGET_GAMEOBJECT:
2017  if (m_targets.getGOTarget())
2019  else
2020  {
2022  {
2023  if (obj->GetTypeId() != TYPEID_GAMEOBJECT)
2024  break;
2025  AddGOTarget(obj->ToGameObject(), i);
2026  }
2027  }
2028  break;
2030  if (m_targets.getGOTargetGUID())
2032  else if (m_targets.getItemTarget())
2034  break;
2035  default:
2036  sLog.outError("SPELL (caster[type: %u; guidlow: %u], spell: %u): unhandled spell target (%u)",
2038  break;
2039  }
2040  break;
2041  }
2042  }
2043 
2044  if (pushType == PUSH_CHAIN) // Chain
2045  {
2046  Unit* target = m_targets.getUnitTarget();
2047  if (!target)
2048  {
2049  sLog.outError("SPELL: no chain unit target for spell ID %u", m_spellInfo->Id);
2050  return;
2051  }
2052 
2053  //Chain: 2, 6, 22, 25, 45, 77
2054  uint32 maxTargets = m_spellInfo->EffectChainTarget[i];
2055  if (modOwner)
2056  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this);
2057 
2058  if (maxTargets > 1)
2059  {
2060  //otherwise, this multiplier is used for something else
2061  m_damageMultipliers[i] = 1.0f;
2062  m_applyMultiplierMask |= 1 << i;
2063 
2064  float range = GetSpellMaxRange(sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex));
2065  if (modOwner)
2066  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
2067 
2068  std::list<Unit*> unitList;
2069 
2070  switch (cur)
2071  {
2074  case TARGET_UNIT_NEARBY_ENTRY: // fix me
2075  SearchChainTarget(unitList, range, maxTargets, SPELL_TARGETS_ENEMY);
2076  break;
2077  case TARGET_UNIT_CHAINHEAL:
2078  case TARGET_UNIT_NEARBY_ALLY: // fix me
2081  SearchChainTarget(unitList, range, maxTargets, SPELL_TARGETS_CHAINHEAL);
2082  break;
2083  }
2084 
2085  for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); ++itr)
2086  AddUnitTarget(*itr, i);
2087  }
2088  else
2089  AddUnitTarget(target, i);
2090  }
2091  else if (pushType)
2092  {
2093  // Dummy, just for client
2094  if (sSpellMgr.EffectTargetType[m_spellInfo->Effect[i]] == SPELL_REQUIRE_DEST)
2095  return;
2096 
2097  float radius = GetSpellRadius(m_spellInfo, i, true);
2098  if (modOwner)
2099  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RADIUS, radius, this);
2100 
2101  std::list<Unit*> unitList;
2102 
2103  switch (cur)
2104  {
2109  SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENEMY);
2110  radius = GetSpellRadius(m_spellInfo, i, false);
2111  break;
2114  case TARGET_UNIT_CONE_ALLY:
2115  SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ALLY);
2116  break;
2119  m_caster->GetPartyMember(unitList, radius); //fix me
2120  break;
2121  case TARGET_GAMEOBJECT_SRC_AREA: // fix me
2123  break;
2126  case TARGET_UNIT_CONE_ENTRY: // fix me
2127  {
2128  ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
2130  if (conditions.empty())
2131  {
2132  sLog.outErrorDb("Spell (ID: %u) (caster Entry: %u) does not have record in spell_script_target", m_spellInfo->Id, m_caster->GetEntry());
2133 
2134  if (IsPositiveEffect(m_spellInfo->Id, i))
2135  SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ALLY);
2136  else
2137  SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENEMY);
2138  }
2139  // let it be done in one check?
2140  else
2141  {
2142  for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
2143  {
2144  if ((*i_spellST)->Type != CONDITION_SPELL_SCRIPT_TARGET)
2145  continue;
2146  if ((*i_spellST)->ConditionValue1 == SPELL_TARGET_TYPE_CREATURE)
2147  SearchAreaTarget(unitList, radius, pushType, SPELL_TARGETS_ENTRY, (*i_spellST)->ConditionValue2);
2148  }
2149  }
2150  break;
2151  }
2153  m_targets.getUnitTarget()->GetPartyMember(unitList, radius);
2154  break;
2156  m_caster->GetPartyMember(unitList, radius);
2157  break;
2159  m_caster->GetRaidMember(unitList, radius);
2160  break;
2162  {
2164  ? m_targets.getUnitTarget()->ToPlayer() : NULL;
2165 
2166  Group* pGroup = targetPlayer ? targetPlayer->GetGroup() : NULL;
2167  if (pGroup)
2168  {
2169  for (GroupReference* itr = pGroup->GetFirstMember(); itr != NULL; itr = itr->next())
2170  {
2171  Player* Target = itr->GetSource();
2172 
2173  // IsHostileTo check duel and controlled by enemy
2174  if (Target && targetPlayer->IsWithinDistInMap(Target, radius) &&
2175  targetPlayer->getClass() == Target->getClass() &&
2176  !m_caster->IsHostileTo(Target))
2177  AddUnitTarget(Target, i);
2178  }
2179  }
2180  else if (m_targets.getUnitTarget())
2182  break;
2183  }
2184  }
2185 
2186  if (!unitList.empty())
2187  {
2189  {
2190  if (m_spellInfo->Id == 5246) //Intimidating Shout
2191  unitList.remove(m_targets.getUnitTarget());
2192 
2193  if(sSpellMgr.SpellTargetType[cur] == TARGET_TYPE_AREA_CONE)
2195  else
2197  }
2198  else if (m_spellInfo->Id == 27285) // Seed of Corruption proc spell
2199  unitList.remove(m_targets.getUnitTarget());
2200 
2201  bool massbuff = IsPositiveSpell(m_spellInfo->Id) && sSpellMgr.IsNoStackSpellDueToSpell(m_spellInfo->Id, m_spellInfo->Id, false);
2202 
2203  for (std::list<Unit*>::iterator itr = unitList.begin(); itr != unitList.end(); )
2204  {
2205  // for mass-buffs skip targets that have higher ranks already applied.on them
2206  if (*itr != m_caster && massbuff)
2207  {
2208  if ((*itr)->HasHigherRankOfAura(m_spellInfo->Id, i))
2209  {
2210  itr = unitList.erase(itr);
2211  continue;
2212  }
2213  }
2214 
2215  AddUnitTarget(*itr, i);
2216  ++itr;
2217  }
2218  }
2219  }
2220 }
2221 
2222 void Spell::prepare(SpellCastTargets* targets, Aura* triggeredByAura)
2223 {
2224  if (m_CastItem)
2226  else
2227  m_castItemGUID = 0;
2228 
2229  m_targets = *targets;
2230 
2232 
2235 
2236  if (triggeredByAura)
2237  m_triggeredByAuraSpell = triggeredByAura->GetSpellProto();
2238 
2239  // create and add update event for this spell
2240  SpellEvent* Event = new SpellEvent(this);
2242 
2243  //Prevent casting at cast another spell (ServerSide check)
2244  if (!m_IsTriggeredSpell && m_caster->IsNonMeleeSpellCast(false, true, true) && m_cast_count)
2245  {
2247  finish(false);
2248  return;
2249  }
2250 
2251  if (sDisableMgr.IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, m_caster))
2252  {
2254  finish(false);
2255  return;
2256  }
2257 
2258  // Fill cost data (not use power for item casts)
2260 
2261  FillTargetMap();
2262 
2263  SpellCastResult result = CheckCast(true);
2264  if (result != SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering
2265  {
2266  if (triggeredByAura && !triggeredByAura->IsPassive() && !IsPassiveSpell(m_spellInfo))
2267  {
2268  SendChannelUpdate(0);
2269  triggeredByAura->SetAuraDuration(0);
2270  }
2271 
2272  SendCastResult(result);
2273 
2274  finish(false);
2275  return;
2276  }
2277 
2278  // Prepare data for triggers
2280 
2281  // Set combo point requirement
2283  m_needComboPoints = false;
2284 
2285  // calculate cast time (calculated after first CanCast check to prevent charge counting for first CanCast fail)
2287 
2288  // don't allow channeled spells / spells with cast time to be casted while moving
2289  // (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in)
2291  {
2293  finish(false);
2294  return;
2295  }
2296 
2297  // Set cast time to 0 if .cheat casttime is enabled.
2298  if (m_caster->GetTypeId() == TYPEID_PLAYER)
2299  {
2301  m_casttime = 0;
2302  }
2303 
2304  // set timer base at cast time
2305  ReSetTimer();
2306 
2307  if (m_IsTriggeredSpell)
2308  cast(true);
2309  else
2310  {
2311  // stealth must be removed at cast starting (at show channel bar)
2312  // skip triggered spell (item equip spell casting and other not explicit character casts/item uses)
2315 
2317  SendSpellStart();
2318 
2319  if (m_caster->GetTypeId() == TYPEID_PLAYER)
2321 
2322  // item: first cast may destroy item and second cast causes crash
2324  cast(true);
2325  }
2326 }
2327 
2328 void Spell::cancel(bool sendInterrupt)
2329 {
2331  return;
2332 
2333  SetReferencedFromCurrent(false);
2334  if (m_selfContainer && *m_selfContainer == this)
2335  *m_selfContainer = NULL;
2336 
2337  uint32 oldState = m_spellState;
2339 
2340  m_autoRepeat = false;
2341  switch (oldState)
2342  {
2343  case SPELL_STATE_PREPARING:
2344  case SPELL_STATE_DELAYED:
2345  {
2346  SendInterrupted(0);
2347  if (sendInterrupt)
2349  }
2350  break;
2351 
2352  case SPELL_STATE_CASTING:
2353  {
2354  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
2355  {
2356  if (ihit->deleted)
2357  continue;
2358 
2359  if (ihit->missCondition == SPELL_MISS_NONE)
2360  {
2361  Unit* unit = m_caster->GetGUID() == (*ihit).targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
2362  if (unit && unit->IsAlive())
2364  }
2365  }
2366 
2368  SendChannelUpdate(0);
2369 
2370  // Do not send interrupt for channeling spells to avoid a visual bug
2371  // that happens when a caster recasts the spell before the channeling ended
2373  {
2374  SendInterrupted(0);
2375  if (sendInterrupt)
2377  }
2378  }
2379  break;
2380  default:
2381  {
2382  } break;
2383  }
2384 
2385  if (m_caster->GetTypeId() == TYPEID_PLAYER)
2387 
2389  if (IsChanneledSpell(m_spellInfo)) // if not channeled then the object for the current cast wasn't summoned yet
2390  {
2392 
2393  // reset cooldown state for disabled while active spells
2394  if (m_caster->GetTypeId() == TYPEID_PLAYER)
2395  {
2398  }
2399  }
2400 
2401  //set state back so finish will be processed
2402  m_spellState = oldState;
2403 
2404  finish(false);
2405 }
2406 
2407 void Spell::cast(bool skipCheck)
2408 {
2409  if (m_spellInfo->Id > MAX_SPELL_ID)
2410  return;
2411 
2412  // update pointers base at GUIDs to prevent access to non-existed already object
2413  UpdatePointers();
2414 
2415  // cancel at lost main target unit
2417  {
2418  cancel();
2419  return;
2420  }
2421 
2422  SetExecutedCurrently(true);
2423  SpellCastResult castResult = SPELL_CAST_OK;
2424 
2427 
2428  if (!m_IsTriggeredSpell)
2429  {
2430  castResult = CheckPower();
2431  if (castResult != SPELL_CAST_OK)
2432  {
2433  SendCastResult(castResult);
2434  finish(false);
2435  SetExecutedCurrently(false);
2436  return;
2437  }
2438  }
2439 
2440  // triggered cast called from Spell::prepare where it was already checked
2441  if (!skipCheck)
2442  {
2443  FillTargetMap();
2444 
2445  castResult = CheckCast(false);
2446  if (castResult != SPELL_CAST_OK)
2447  {
2448  SendCastResult(castResult);
2449  SendInterrupted(0);
2450  finish(false);
2451  SetExecutedCurrently(false);
2452  return;
2453  }
2454  }
2455  // Check if some auras need to be interrupted when casting combat auto-repeating spells
2458 
2459  if (m_spellState == SPELL_STATE_FINISHED) // stop cast if spell marked as finish somewhere in Take*/FillTargetMap
2460  {
2461  SendInterrupted(0);
2462  finish(false);
2463  SetExecutedCurrently(false);
2464  return;
2465  }
2466 
2469  pet->DespawnOrUnsummon();
2470 
2471  // traded items have trade slot instead of guid in m_itemTargetGUID
2472  // set to real guid to be sent later to the client
2474 
2475  if (!m_IsTriggeredSpell)
2476  TakeReagents(); // we must remove reagents before HandleEffects to allow place crafted item in same slot
2477 
2478  // CAST SPELL
2480 
2481  // calc miss, reflect, parry, etc.
2483 
2484  SendSpellGo(); // we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()...
2485 
2486  //handle SPELL_AURA_ADD_TARGET_TRIGGER auras
2487  //are there any spells need to be triggered after hit?
2489  for (Unit::AuraList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i)
2490  {
2491  SpellEntry const* auraSpellInfo = (*i)->GetSpellProto();
2492  uint32 auraSpellIdx = (*i)->GetEffIndex();
2493  if (IsAffectedBy(auraSpellInfo, auraSpellIdx))
2494  {
2495  if (SpellEntry const* spellInfo = sSpellStore.LookupEntry(auraSpellInfo->EffectTriggerSpell[auraSpellIdx]))
2496  {
2497  // Calculate chance at that moment (can be depend for example from combo points)
2498  int32 chance = m_caster->CalculateSpellDamage(auraSpellInfo, auraSpellIdx, (*i)->GetBasePoints(), NULL);
2499  m_ChanceTriggerSpells.push_back(std::make_pair(spellInfo, chance * (*i)->GetStackAmount()));
2500  }
2501  }
2502  }
2503 
2506 
2507  // Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
2508  // @TODO: Find similarities for spells such as Ruthlessness and run the proper check here
2509  if ((m_spellInfo->speed > 0.0f && !IsChanneledSpell(m_spellInfo)) || m_spellInfo->Id == 14157)
2510  {
2511  // Okay, maps created, now prepare flags
2512  m_immediateHandled = false;
2514  SetDelayStart(0);
2515 
2516  if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCast(false, false, true))
2518  }
2519  else
2520  {
2521  // Immediate spell, no big deal
2522  handle_immediate();
2523  }
2524 
2525  // combo points should not be taken before SPELL_AURA_ADD_TARGET_TRIGGER auras are handled
2526  if (!m_IsTriggeredSpell)
2527  TakePower();
2528 
2530  {
2531  if (const std::vector<int32>* spell_triggered = sSpellMgr.GetSpellLinked(m_spellInfo->Id))
2532  {
2533  for (std::vector<int32>::const_iterator i = spell_triggered->begin(); i != spell_triggered->end(); ++i)
2534  if (*i < 0)
2536  else
2538  }
2539  }
2540 
2541  // Clear spell cooldowns after every spell is cast if .cheat cooldown is enabled.
2542  if (m_caster->GetTypeId() == TYPEID_PLAYER)
2543  {
2546  }
2547 
2548  SetExecutedCurrently(false);
2549 }
2550 
2552 {
2553  if (m_spellInfo->Id > MAX_SPELL_ID)
2554  return;
2555 
2556  // start channeling if applicable
2558  {
2559  int32 duration = GetSpellDuration(m_spellInfo);
2561  duration = m_spellValue->Duration;
2562  if (duration > 0)
2563  {
2564  if (m_targets.getUnitTarget())
2565  {
2568  }
2569 
2570  // Apply duration mod
2571  if (Player* modOwner = m_caster->GetSpellModOwner())
2572  modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
2573 
2574  // Apply haste mods
2575  m_caster->ModSpellDurationTime(m_spellInfo, duration, this);
2576 
2579  SendChannelStart(duration);
2580  }
2581  else if (duration == -1)
2582  {
2585  SendChannelStart(duration);
2586  }
2587 
2588  // Interrupt movement at channeled spells for creature case
2590  m_caster->StopMoving();
2591  }
2592 
2593  // process immediate effects (items, ground, etc.) also initialize some variables
2595 
2596  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
2597  {
2598  if (m_destroyed || ihit == m_UniqueTargetInfo.end() || m_UniqueTargetInfo.size() == 0)
2599  break;
2600 
2601  if (ihit->deleted)
2602  continue;
2603 
2604  DoAllEffectOnTarget(&(*ihit));
2605  }
2606 
2607  for (std::list<GOTargetInfo>::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
2608  {
2609  if (m_destroyed || ihit == m_UniqueGOTargetInfo.end() || m_UniqueGOTargetInfo.size() == 0)
2610  break;
2611 
2612  if (ihit->deleted)
2613  continue;
2614 
2615  DoAllEffectOnTarget(&(*ihit));
2616  }
2617 
2618  // spell is finished, perform some last features of the spell here
2620 
2622  finish(true); // successfully finish spell cast (not last in case autorepeat or channel spell)
2623 }
2624 
2626 {
2627  UpdatePointers();
2628  uint64 next_time = 0;
2629 
2630  if (!m_immediateHandled)
2631  {
2633  m_immediateHandled = true;
2634  }
2635 
2636  bool single_missile = (m_targets.m_targetMask & TARGET_FLAG_DEST_LOCATION);
2637 
2638  // 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)
2639  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
2640  {
2641  if (ihit->deleted)
2642  continue;
2643 
2644  if (ihit->processed == false)
2645  {
2646  if (single_missile || ihit->timeDelay <= t_offset)
2647  {
2648  ihit->timeDelay = t_offset;
2649  DoAllEffectOnTarget(&(*ihit));
2650  }
2651  else if (next_time == 0 || ihit->timeDelay < next_time)
2652  next_time = ihit->timeDelay;
2653  }
2654  }
2655 
2656  // now recheck gameobject targeting correctness
2657  for (std::list<GOTargetInfo>::iterator ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit)
2658  {
2659  if (ighit->deleted)
2660  continue;
2661 
2662  if (!ighit->processed)
2663  {
2664  if (single_missile || ighit->timeDelay <= t_offset)
2665  DoAllEffectOnTarget(&(*ighit));
2666  else if (next_time == 0 || ighit->timeDelay < next_time)
2667  next_time = ighit->timeDelay;
2668  }
2669  }
2670  // All targets passed - need finish phase
2671  if (next_time == 0)
2672  {
2673  // spell is finished, perform some last features of the spell here
2675 
2676  finish(true); // successfully finish spell cast
2677 
2678  // return zero, spell is finished now
2679  return 0;
2680  }
2681  else
2682  {
2683  // spell is unfinished, return next execution time
2684  return next_time;
2685  }
2686 }
2687 
2689 {
2690  // handle some immediate features of the spell here
2691 
2694 
2696  TakeCastItem();
2697 
2699  for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
2700  {
2701  if (m_spellInfo->Effect[j] == 0)
2702  continue;
2703 
2704  // apply Send Event effect to ground in case empty target lists
2706  {
2707  HandleEffects(NULL, NULL, NULL, j);
2708  continue;
2709  }
2710 
2711  // Don't do spell log, if is school damage spell
2713  m_needSpellLog = false;
2714  }
2715 
2716  // initialize Diminishing Returns Data
2719 
2720  // process items
2721  for (std::list<ItemTargetInfo>::iterator ihit = m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
2722  DoAllEffectOnTarget(&(*ihit));
2723 
2724  if (!m_originalCaster)
2725  return;
2726  // process ground
2727  for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
2728  {
2729  if (sSpellMgr.EffectTargetType[m_spellInfo->Effect[j]] == SPELL_REQUIRE_DEST)
2730  {
2731  if (!m_targets.HasDst()) // FIXME: this will ignore dest set in effect
2733  HandleEffects(m_originalCaster, NULL, NULL, j);
2734  }
2735  else if (sSpellMgr.EffectTargetType[m_spellInfo->Effect[j]] == SPELL_REQUIRE_NONE)
2736  HandleEffects(m_originalCaster, NULL, NULL, j);
2737  }
2738 }
2739 
2741 {
2742  // Take for real after all targets are processed
2743  if (m_needComboPoints)
2744  if (Player* player = m_caster->ToPlayer())
2745  player->ClearComboPoints();
2746 
2747  // spell log
2748  if (m_needSpellLog)
2749  SendLogExecute();
2750 }
2751 
2753 {
2754  if (m_caster->GetTypeId() != TYPEID_PLAYER)
2755  return;
2756 
2757  Player* _player = m_caster->ToPlayer();
2758  // Add cooldown for max (disable spell)
2759  // Cooldown started on SendCooldownEvent call
2761  return;
2762 
2763  // init cooldown values
2764  uint32 cat = 0;
2765  int32 rec = -1;
2766  int32 catrec = -1;
2767 
2768  // some special item spells without correct cooldown in SpellInfo
2769  // cooldown information stored in item prototype
2770  // This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client.
2771 
2772  if (m_CastItem)
2773  {
2774  ItemTemplate const* proto = m_CastItem->GetProto();
2775  if (proto)
2776  {
2777  for (int idx = 0; idx < 5; ++idx)
2778  {
2779  if (proto->Spells[idx].SpellId == m_spellInfo->Id)
2780  {
2781  cat = proto->Spells[idx].SpellCategory;
2782  rec = proto->Spells[idx].SpellCooldown;
2783  catrec = proto->Spells[idx].SpellCategoryCooldown;
2784  break;
2785  }
2786  }
2787  }
2788  }
2789 
2790  // if no cooldown found above then base at DBC data
2791  if (rec < 0 && catrec < 0)
2792  {
2793  cat = m_spellInfo->Category;
2794  rec = m_spellInfo->RecoveryTime;
2796  }
2797 
2798  // shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK)
2799  // prevent 0 cooldowns set by another way
2800  if (rec <= 0 && catrec <= 0 && (cat == 76 || cat == 351))
2801  rec = _player->GetAttackTime(RANGED_ATTACK);
2802 
2803  // Now we have cooldown data (if found any), time to apply mods
2804  if (rec > 0)
2805  _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, rec, this);
2806 
2807  if (catrec > 0)
2808  _player->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COOLDOWN, catrec, this);
2809 
2810  // replace negative cooldowns by 0
2811  if (rec < 0) rec = 0;
2812  if (catrec < 0) catrec = 0;
2813 
2814  // no cooldown after applying spell mods
2815  if (rec == 0 && catrec == 0)
2816  return;
2817 
2818  time_t curTime = time(NULL);
2819 
2820  time_t catrecTime = catrec ? curTime + catrec / IN_MILLISECONDS : 0; // in secs
2821  time_t recTime = rec ? curTime + rec / IN_MILLISECONDS : catrecTime; // in secs
2822 
2823  // self spell cooldown
2824  if (recTime > 0)
2825  _player->AddSpellCooldown(m_spellInfo->Id, m_CastItem ? m_CastItem->GetEntry() : 0, recTime);
2826 
2827  // category spells
2828  if (catrec > 0)
2829  {
2830  SpellCategoryStore::const_iterator i_scstore = sSpellCategoryStore.find(cat);
2831  if (i_scstore != sSpellCategoryStore.end())
2832  {
2833  for (SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset)
2834  {
2835  if (*i_scset == m_spellInfo->Id) // skip main spell, already handled above
2836  continue;
2837 
2838  _player->AddSpellCooldown(*i_scset, m_CastItem ? m_CastItem->GetEntry() : 0, catrecTime);
2839  }
2840  }
2841  }
2842 }
2843 
2844 void Spell::update(uint32 difftime)
2845 {
2846  // update pointers based at it's GUIDs
2847  UpdatePointers();
2848 
2850  {
2851  cancel();
2852  return;
2853  }
2854 
2855  // check if the player or unit caster has moved before the spell finished (exclude casting on vehicles)
2856  if (((m_caster->GetTypeId() == TYPEID_PLAYER || m_caster->GetTypeId() == TYPEID_UNIT) && m_timer != 0) &&
2859  {
2860  // always cancel for channeled spells
2862  cancel();
2863  // don't cancel for melee, autorepeat, triggered and instant spells
2865  cancel();
2866  }
2867 
2868  switch (m_spellState)
2869  {
2870  case SPELL_STATE_PREPARING:
2871  {
2872  if (m_timer > 0)
2873  {
2874  if (difftime >= (uint32)m_timer)
2875  m_timer = 0;
2876  else
2877  m_timer -= difftime;
2878  }
2879 
2880  if (m_timer == 0 && !IsNextMeleeSwingSpell() && !IsAutoRepeat())
2882  }
2883  break;
2884  case SPELL_STATE_CASTING:
2885  {
2886  if (m_timer)
2887  {
2889  {
2890  // check if player has jumped before the channeling finished
2892  cancel();
2893 
2894  // check for incapacitating player states
2896  cancel();
2897  }
2898 
2899  // check if there are alive targets left
2901  {
2902  SendChannelUpdate(0);
2903  finish();
2904  }
2905 
2906  if (m_timer > 0)
2907  {
2908  if (difftime >= (uint32)m_timer)
2909  m_timer = 0;
2910  else
2911  m_timer -= difftime;
2912  }
2913  }
2914 
2915  if (m_timer == 0)
2916  {
2917  SendChannelUpdate(0);
2918 
2919  // channeled spell processed independently for quest targeting
2920  // cast at creature (or GO) quest objectives update at successful cast channel finished
2921  // ignore autorepeat/melee casts for speed (not exist quest for spells (hm...)
2923  {
2924  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
2925  {
2926  if (ihit->deleted)
2927  continue;
2928 
2929  TargetInfo* target = &*ihit;
2930 
2931  if (!IS_CREATURE_GUID(target->targetGUID))
2932  continue;
2933 
2934  Unit* unit = m_caster->GetGUID() == target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target->targetGUID);
2935  if (unit == NULL)
2936  continue;
2937 
2939  }
2940 
2941  for (std::list<GOTargetInfo>::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
2942  {
2943  if (ihit->deleted)
2944  continue;
2945 
2946  GOTargetInfo* target = &*ihit;
2947 
2948  GameObject* go = m_caster->GetMap()->GetGameObject(target->targetGUID);
2949  if (!go)
2950  continue;
2951 
2953  }
2954  }
2955 
2956  finish();
2957  }
2958  }
2959  break;
2960  default:
2961  {
2962  } break;
2963  }
2964 }
2965 
2966 void Spell::finish(bool ok)
2967 {
2968  if (!m_caster)
2969  return;
2970 
2972  return;
2974 
2977 
2978  if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCast(false, false, true))
2980 
2981  if (!ok)
2982  {
2983  //restore spell mods
2984  if (m_caster->GetTypeId() == TYPEID_PLAYER)
2986 
2987  // Spell has failed so the combat is no longer being initiated
2988  // Do this only if the unit is initiating combat
2990  m_caster->setInitiatingCombat(false);
2991 
2992  return;
2993  }
2994  // other code related only to successfully finished spells
2995 
2996  //remove spell mods
2997  if (Player* modOwner = m_caster->GetSpellModOwner())
2998  {
2999  // Take mods after trigger spell
3000  // mods are taken only on succesfull cast and independantly from targets of the spell
3001  modOwner->RemoveSpellMods(this);
3002  }
3003 
3004  // Okay to remove extra attacks
3006  m_caster->m_extraAttacks = 0;
3007 
3008  // Heal caster for all health leech from all targets
3009  if (m_healthLeech)
3010  {
3013  }
3014 
3015  if (IsAutoActionResetSpell())
3016  {
3018  {
3021  if (m_caster->haveOffhandWeapon())
3023  }
3024  }
3025 
3026  // call triggered spell only at successful cast (after clear combo points -> for add some if need)
3027  // I assume what he means is that some triggered spells may add combo points
3028  if (!m_TriggerSpells.empty())
3029  TriggerSpell();
3030 
3031  // Stop Attack for some spells
3033  m_caster->AttackStop();
3034 }
3035 
3037 {
3038  if (m_caster->GetTypeId() != TYPEID_PLAYER)
3039  return;
3040 
3041  if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time
3042  return;
3043 
3044  if (result != SPELL_CAST_OK)
3045  {
3046  WorldPacket data(SMSG_CAST_FAILED, (4 + 1 + 1));
3047  data << uint32(m_spellInfo->Id);
3048  data << uint8(!IsPassiveSpell(m_spellInfo) ? result : SPELL_FAILED_DONT_REPORT); // do not report failed passive spells
3049  data << uint8(m_cast_count); // single cast or multi 2.3 (0/1)
3050  switch (result)
3051  {
3054  break;
3056  // hardcode areas limitation case
3057  switch (m_spellInfo->Id)
3058  {
3059  case 41617: // Cenarion Mana Salve
3060  case 41619: // Cenarion Healing Salve
3061  data << uint32(3905);
3062  break;
3063  case 41618: // Bottled Nethergon Energy
3064  case 41620: // Bottled Nethergon Vapor
3065  data << uint32(3842);
3066  break;
3067  case 45373: // Bloodberry Elixir
3068  data << uint32(4075);
3069  break;
3070  case 32307: // Warmaul Ogre Banner
3071  data << uint32(3637);
3072  break;
3073  default: // default case
3074  data << uint32(m_spellInfo->AreaId);
3075  break;
3076  }
3077  break;
3078  case SPELL_FAILED_TOTEMS:
3079  if (m_spellInfo->Totem[0])
3080  data << uint32(m_spellInfo->Totem[0]);
3081  if (m_spellInfo->Totem[1])
3082  data << uint32(m_spellInfo->Totem[1]);
3083  break;
3085  if (m_spellInfo->TotemCategory[0])
3086  data << uint32(m_spellInfo->TotemCategory[0]);
3087  if (m_spellInfo->TotemCategory[1])
3088  data << uint32(m_spellInfo->TotemCategory[1]);
3089  break;
3096  break;
3097  default:
3098  break;
3099  }
3100  m_caster->ToPlayer()->GetSession()->SendPacket(&data);
3101  }
3102  else
3103  {
3104  WorldPacket data(SMSG_CLEAR_EXTRA_AURA_INFO, (8 + 4));
3105  data << m_caster->GetPackGUID();
3106  data << uint32(m_spellInfo->Id);
3107  m_caster->ToPlayer()->GetSession()->SendPacket(&data);
3108  }
3109 }
3110 
3112 {
3113  if (!m_isNeedSendToClient)
3114  return;
3115 
3116  DEBUG_LOG("Sending SMSG_SPELL_START id=%u", m_spellInfo->Id);
3117 
3118  uint32 castFlags = CAST_FLAG_UNKNOWN1;
3119  if (IsRangedSpell())
3120  castFlags |= CAST_FLAG_AMMO;
3121 
3122  //Unit* target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster;
3123 
3124  WorldPacket data(SMSG_SPELL_START, (8 + 8 + 4 + 4 + 2));
3125  if (m_CastItem)
3126  data << m_CastItem->GetPackGUID();
3127  else
3128  data << m_caster->GetPackGUID();
3129 
3130  data << m_caster->GetPackGUID();
3131  data << uint32(m_spellInfo->Id);; // spellId
3132  data << uint8(m_cast_count); // pending spell cast?
3133  data << uint16(castFlags); // cast flags
3134  data << int32(m_timer); // delay?
3135  data << m_targets;
3136 
3137  if (castFlags & CAST_FLAG_AMMO)
3138  WriteAmmoToPacket(&data);
3139 
3140  m_caster->SendMessageToSet(&data, true);
3141 }
3142 
3144 {
3145  // not send invisible spell casting
3146  if (!m_isNeedSendToClient)
3147  return;
3148 
3149  DEBUG_LOG("Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
3150 
3151  //Unit* target = m_targets.getUnitTarget() ? m_targets.getUnitTarget() : m_caster;
3152 
3153  uint32 castFlags = CAST_FLAG_UNKNOWN3;
3154 
3155  // triggered spells with spell visual != 0 and not auto shot
3157  castFlags |= CAST_FLAG_PENDING;
3158 
3159  if (IsRangedSpell())
3160  castFlags |= CAST_FLAG_AMMO; // arrows/bullets visual
3161 
3162  WorldPacket data(SMSG_SPELL_GO, 50); // guess size
3163 
3164  if (m_CastItem)
3165  data << m_CastItem->GetPackGUID();
3166  else
3167  data << m_caster->GetPackGUID();
3168 
3169  data << m_caster->GetPackGUID();
3170  data << uint32(m_spellInfo->Id); // spellId
3171  data << uint16(castFlags); // cast flags
3172  data << uint32(getMSTime()); // timestamp
3173 
3174  WriteSpellGoTargets(&data);
3175 
3176  data << m_targets;
3177 
3178  if (castFlags & CAST_FLAG_AMMO)
3179  WriteAmmoToPacket(&data);
3180 
3181  m_caster->SendMessageToSet(&data, true);
3182 }
3183 
3185 {
3186  uint32 ammoInventoryType = 0;
3187  uint32 ammoDisplayID = 0;
3188 
3189  if (m_caster->GetTypeId() == TYPEID_PLAYER)
3190  {
3192  if (pItem)
3193  {
3194  ammoInventoryType = pItem->GetProto()->InventoryType;
3195  if (ammoInventoryType == INVTYPE_THROWN)
3196  ammoDisplayID = pItem->GetProto()->DisplayInfoID;
3197  else
3198  {
3200  if (ammoID)
3201  {
3202  ItemTemplate const* pProto = sObjectMgr.GetItemTemplate(ammoID);
3203  if (pProto)
3204  {
3205  ammoDisplayID = pProto->DisplayInfoID;
3206  ammoInventoryType = pProto->InventoryType;
3207  }
3208  }
3209  else if (m_caster->HasAura(46699)) // Requires No Ammo
3210  {
3211  ammoDisplayID = 5996; // normal arrow
3212  ammoInventoryType = INVTYPE_AMMO;
3213  }
3214  }
3215  }
3216  }
3217  else
3218  {
3219  for (uint8 i = 0; i < 3; ++i)
3220  {
3222  {
3223  if (ItemTemplate const* pProto = sObjectMgr.GetItemTemplate(item_id))
3224  {
3225  if (pProto->Class == ITEM_CLASS_WEAPON)
3226  {
3227  switch (pProto->SubClass)
3228  {
3230  ammoDisplayID = pProto->DisplayInfoID;
3231  ammoInventoryType = pProto->InventoryType;
3232  break;
3235  ammoDisplayID = 5996; // is this need fixing?
3236  ammoInventoryType = INVTYPE_AMMO;
3237  break;
3239  ammoDisplayID = 5998; // is this need fixing?
3240  ammoInventoryType = INVTYPE_AMMO;
3241  break;
3242  }
3243 
3244  if (ammoDisplayID)
3245  break;
3246  }
3247  }
3248  }
3249  }
3250  }
3251 
3252  *data << uint32(ammoDisplayID);
3253  *data << uint32(ammoInventoryType);
3254 }
3255 
3257 {
3258  *data << (uint8)m_countOfHit;
3259  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
3260  {
3261  if (ihit->deleted)
3262  continue;
3263 
3264  if ((*ihit).missCondition == SPELL_MISS_NONE) // Add only hits
3265  *data << uint64(ihit->targetGUID);
3266  }
3267 
3268  for (std::list<GOTargetInfo>::iterator ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit)
3269  {
3270  if (ighit->deleted)
3271  continue;
3272 
3273  *data << uint64(ighit->targetGUID); // Always hits
3274  }
3275 
3276  *data << (uint8)m_countOfMiss;
3277  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
3278  {
3279  if (ihit->deleted)
3280  continue;
3281 
3282  if (ihit->missCondition != SPELL_MISS_NONE) // Add only miss
3283  {
3284  *data << uint64(ihit->targetGUID);
3285  *data << uint8(ihit->missCondition);
3286  if (ihit->missCondition == SPELL_MISS_REFLECT)
3287  *data << uint8(ihit->reflectResult);
3288  }
3289  }
3290 }
3291 
3293 {
3295 
3296  WorldPacket data(SMSG_SPELLLOGEXECUTE, (8 + 4 + 4 + 4 + 4 + 8));
3297 
3298  if (m_caster->GetTypeId() == TYPEID_PLAYER)
3299  data << m_caster->GetPackGUID();
3300  else
3301  data << target->GetPackGUID();
3302 
3303  data << uint32(m_spellInfo->Id);
3304  uint32 count1 = 1;
3305  data << uint32(count1); // count1 (effect count?)
3306  for (uint32 i = 0; i < count1; ++i)
3307  {
3308  data << uint32(m_spellInfo->Effect[0]); // spell effect
3309  uint32 count2 = 1;
3310  data << uint32(count2); // count2 (target count?)
3311  for (uint32 j = 0; j < count2; ++j)
3312  {
3313  switch (m_spellInfo->Effect[0])
3314  {
3316  if (Unit* unit = m_targets.getUnitTarget())
3317  data << unit->GetPackGUID();
3318  else
3319  data << uint8(0);
3320  data << uint32(0);
3321  data << uint32(0);
3322  data << float(0);
3323  break;
3325  if (Unit* unit = m_targets.getUnitTarget())
3326  data << unit->GetPackGUID();
3327  else
3328  data << uint8(0);
3329  data << uint32(m_caster->m_extraAttacks);
3330  break;
3332  if (Unit* unit = m_targets.getUnitTarget())
3333  data << unit->GetPackGUID();
3334  else
3335  data << uint8(0);
3336  data << uint32(0); // spellid
3337  break;
3339  if (Unit* unit = m_targets.getUnitTarget())
3340  data << unit->GetPackGUID();
3341  else
3342  data << uint8(0);
3343  data << uint32(0);
3344  data << uint32(0);
3345  break;
3348  if (Item* item = m_targets.getItemTarget())
3349  data << item->GetPackGUID();
3350  else
3351  data << uint8(0);
3352  break;
3354  data << uint32(m_spellInfo->EffectItemType[0]);
3355  break;
3356  case SPELL_EFFECT_SUMMON:
3361  case SPELL_EFFECT_DUEL:
3366  if (Unit* unit = m_targets.getUnitTarget())
3367  data << unit->GetPackGUID();
3368  else if (m_targets.getItemTargetGUID())
3370  else if (GameObject* go = m_targets.getGOTarget())
3371  data << go->GetPackGUID();
3372  else
3373  data << uint8(0); // guid
3374  break;
3375  case SPELL_EFFECT_FEED_PET:
3376  data << uint32(m_targets.getItemTargetEntry());
3377  break;
3379  if (Unit* unit = m_targets.getUnitTarget())
3380  data << unit->GetPackGUID();
3381  else
3382  data << uint8(0);
3383  break;
3384  default:
3385  return;
3386  }
3387  }
3388  }
3389 
3390  m_caster->SendMessageToSet(&data, true);
3391 }
3392 
3394 {
3395  WorldPacket data(SMSG_SPELL_FAILURE, (8 + 4 + 1));
3396  data << m_caster->GetObjectGUID();
3397  data << m_spellInfo->Id;
3398  data << result;
3399  m_caster->SendMessageToSet(&data, true);
3400 
3401  data.Initialize(SMSG_SPELL_FAILED_OTHER, (8 + 4));
3402  data << m_caster->GetObjectGUID();
3403  data << m_spellInfo->Id;
3404  m_caster->SendMessageToSet(&data, true);
3405 }
3406 
3408 {
3409  if (time == 0)
3410  {
3413  }
3414 
3415  if (!m_isNeedSendToClient)
3416  return;
3417 
3418  WorldPacket data(MSG_CHANNEL_UPDATE, 8 + 4);
3419  data << m_caster->GetPackGUID();
3420  data << uint32(time);
3421 
3422  m_caster->SendMessageToSet(&data, true);
3423 }
3424 
3426 {
3427  uint64 channelTarget = 0;
3429  channelTarget = m_targets.getUnitTargetGUID();
3430  else if (m_targets.getGOTargetGUID())
3431  channelTarget = m_targets.getGOTargetGUID();
3432  else if (m_targets.getCorpseTargetGUID())
3433  channelTarget = m_targets.getCorpseTargetGUID();
3434 
3435 
3436  m_timer = duration;
3437  if (channelTarget)
3439 
3441 
3442  if (!m_isNeedSendToClient)
3443  return;
3444 
3445  WorldPacket data(MSG_CHANNEL_START, (8 + 4 + 4));
3446  data << m_caster->GetPackGUID();
3447  data << uint32(m_spellInfo->Id);
3448  data << uint32(duration);
3449  m_caster->SendMessageToSet(&data, true);
3450 }
3451 
3453 {
3454  WorldPacket data(SMSG_RESURRECT_REQUEST, (8 + 4 + 2 + 4));
3455  data << m_caster->GetGUID();
3456  data << uint32(1) << uint16(0) << uint32(1);
3457 
3458  target->GetSession()->SendPacket(&data);
3459 }
3460 
3462 {
3463  if (m_caster->GetTypeId() != TYPEID_PLAYER)
3464  return;
3465 
3467  data << uint64(m_caster->GetGUID());
3468  data << uint32(SpellID); // spell visual id?
3469  m_caster->ToPlayer()->GetSession()->SendPacket(&data);
3470 }
3471 
3473 {
3475  return;
3476 
3477  // not remove cast item at triggered spell (equipping, weapon damage, etc)
3478  if (m_IsTriggeredSpell)
3479  return;
3480 
3481  ItemTemplate const* proto = m_CastItem->GetProto();
3482 
3483  if (!proto)
3484  {
3485  // This code is to avoid a crash
3486  // I'm not sure, if this is really an error, but I guess every item needs a prototype
3487  sLog.outError("Cast item has no item prototype highId=%d, lowId=%d", m_CastItem->GetGUIDHigh(), m_CastItem->GetGUIDLow());
3488  return;
3489  }
3490 
3491  bool expendable = false;
3492  bool withoutCharges = false;
3493 
3494  for (int i = 0; i < 5; i++)
3495  {
3496  if (proto->Spells[i].SpellId)
3497  {
3498  // item has limited charges
3499  if (proto->Spells[i].SpellCharges)
3500  {
3501  if (proto->Spells[i].SpellCharges < 0)
3502  expendable = true;
3503 
3504  int32 charges = m_CastItem->GetSpellCharges(i);
3505 
3506  // item has charges left
3507  if (charges)
3508  {
3509  (charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use
3510  if (proto->Stackable < 2)
3511  m_CastItem->SetSpellCharges(i, charges);
3513  }
3514 
3515  // all charges used
3516  withoutCharges = (charges == 0);
3517  }
3518  }
3519  }
3520 
3521  if (expendable && withoutCharges)
3522  {
3523  uint32 count = 1;
3524  m_caster->ToPlayer()->DestroyItemCount(m_CastItem, count, true);
3525 
3526  // prevent crash at access to deleted m_targets.getItemTarget
3528  m_targets.setItemTarget(NULL);
3529 
3530  m_CastItem = NULL;
3531  }
3532 }
3533 
3535 {
3537  return;
3538 
3539  //Don't take power if the spell is cast while .cheat power is enabled.
3540  if (m_caster->GetTypeId() == TYPEID_PLAYER)
3541  {
3543  return;
3544  }
3545 
3546  bool hit = true;
3547  if (m_caster->GetTypeId() == TYPEID_PLAYER)
3548  {
3550  if (uint64 targetGUID = m_targets.getUnitTargetGUID())
3551  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
3552  {
3553  if (ihit->deleted)
3554  continue;
3555 
3556  if (ihit->targetGUID == targetGUID)
3557  {
3558  if (ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS/* && ihit->targetGUID != m_caster->GetGUID()*/)
3559  hit = false;
3560  break;
3561  }
3562  }
3563  }
3564 
3565  if (!m_powerCost)
3566  return;
3567 
3568  // health as power used
3570  {
3572  return;
3573  }
3574 
3576  {
3577  sLog.outError("Spell::TakePower: Unknown power type '%d'", m_spellInfo->powerType);
3578  return;
3579  }
3580 
3581  Powers powerType = Powers(m_spellInfo->powerType);
3582 
3583  if (hit)
3584  m_caster->ModifyPower(powerType, -m_powerCost);
3585  else
3586  m_caster->ModifyPower(powerType, -irand(0, m_powerCost / 4));
3587 
3588  // Set the five second timer
3589  if (powerType == POWER_MANA && m_powerCost > 0)
3591 }
3592 
3594 {
3595  if (m_IsTriggeredSpell) // reagents used in triggered spell removed by original spell or don't must be removed.
3596  return;
3597 
3598  if (m_caster->GetTypeId() != TYPEID_PLAYER)
3599  return;
3600 
3601  ItemTemplate const* castItemTemplate = m_CastItem ? m_CastItem->GetProto() : NULL;
3602 
3603  // do not take reagents for these item casts
3604  if (castItemTemplate && castItemTemplate->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST)
3605  return;
3606 
3607  Player* p_caster = m_caster->ToPlayer();
3608  if (p_caster->CanCastNoReagents(m_spellInfo))
3609  return;
3610 
3611  for (uint32 x = 0; x < 8; x++)
3612  {
3613  if (m_spellInfo->Reagent[x] <= 0)
3614  continue;
3615 
3616  uint32 itemid = m_spellInfo->Reagent[x];
3617  uint32 itemcount = m_spellInfo->ReagentCount[x];
3618 
3619  // if CastItem is also spell reagent
3620  if (m_CastItem)
3621  {
3622  ItemTemplate const* proto = m_CastItem->GetProto();
3623  if (proto && proto->ItemId == itemid)
3624  {
3625  for (int s = 0; s < 5; s++)
3626  {
3627  // CastItem will be used up and does not count as reagent
3628  int32 charges = m_CastItem->GetSpellCharges(s);
3629  if (proto->Spells[s].SpellCharges < 0 && abs(charges) < 2)
3630  {
3631  ++itemcount;
3632  break;
3633  }
3634  }
3635 
3636  m_CastItem = NULL;
3637  }
3638  }
3639 
3640  // if getItemTarget is also spell reagent
3641  if (m_targets.getItemTargetEntry() == itemid)
3642  m_targets.setItemTarget(NULL);
3643 
3644  p_caster->DestroyItemCount(itemid, itemcount, true);
3645  }
3646 }
3647 
3649 {
3650  if (m_UniqueTargetInfo.empty())
3651  return;
3652 
3655  return;
3656 
3657  float threat = 0.0f;
3658  if (SpellThreatEntry const* threatEntry = sSpellMgr.GetSpellThreatEntry(m_spellInfo->Id))
3659  {
3660  if (threatEntry->apPctMod != 0.0f)
3661  threat += threatEntry->apPctMod * m_caster->GetTotalAttackPowerValue(BASE_ATTACK);
3662 
3663  threat += threatEntry->flatMod;
3664  }
3665  else
3666  threat += m_spellInfo->spellLevel;
3667 
3668  if (threat == 0.0f)
3669  return;
3670 
3671  // since 2.0.1 threat from positive effects also is distributed among all targets, so the overall caused threat is at most the defined bonus
3672  threat /= m_UniqueTargetInfo.size();
3673 
3674  for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
3675  {
3676  float threatToAdd = threat;
3677  if (ihit->missCondition != SPELL_MISS_NONE)
3678  threatToAdd = 0.0f;
3679 
3680  Unit* target = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
3681  if (!target)
3682  continue;
3683 
3684  // positive spells distribute threat among all units that are in combat with target, like healing
3686  target->AddAssistThreat(m_caster, threatToAdd, m_spellInfo);
3687  // for negative spells threat gets distributed among affected targets
3688  else
3689  if (!target->IsFriendlyTo(m_caster))
3690  target->AddThreat(m_caster, threatToAdd, GetSpellSchoolMask(m_spellInfo), m_spellInfo);
3691  }
3692 
3693  sLog.outDebug("Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, IsPositiveSpell(m_spellInfo->Id) ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));
3694 }
3695 
3696 void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, float /*DamageMultiplier*/)
3697 {
3698  unitTarget = pUnitTarget;
3699  itemTarget = pItemTarget;
3700  gameObjTarget = pGOTarget;
3701 
3702  uint8 eff = m_spellInfo->Effect[i];
3703 
3704  DEBUG_LOG("Spell: Effect : %u", eff);
3705 
3706  //we do not need DamageMultiplier here.
3707  damage = CalculateDamage(i, NULL);
3708 
3709  if (eff < TOTAL_SPELL_EFFECTS)
3710  {
3711  //sLog.outDebug("WORLD: Spell FX %d < TOTAL_SPELL_EFFECTS ", eff);
3712  (*this.*SpellEffects[eff])((SpellEffIndex)i);
3713  }
3714  /*
3715  else
3716  {
3717  sLog.outDebug("WORLD: Spell FX %d > TOTAL_SPELL_EFFECTS ", eff);
3718  if (m_CastItem)
3719  EffectEnchantItemTmp(i);
3720  else
3721  {
3722  sLog.outError("SPELL: unknown effect %u spell id %u\n",
3723  eff, m_spellInfo->Id);
3724  }
3725  }
3726  */
3727 }
3728 
3730 {
3731  for (TriggerSpells::iterator si = m_TriggerSpells.begin(); si != m_TriggerSpells.end(); ++si)
3732  {
3733  Spell* spell = new Spell(m_caster, (*si), true, m_originalCasterGUID, m_selfContainer, true);
3734  spell->prepare(&m_targets); // use original spell original targets
3735  }
3736 }
3737 
3739 {
3740  // check death state
3742  return SPELL_FAILED_CASTER_DEAD;
3743 
3744  // check cooldowns to prevent cheating
3745  if (!m_IsTriggeredSpell)
3746  if (Player* plr = m_caster->ToPlayer())
3747  if (plr->HasSpellCooldown(m_spellInfo->Id) || (strict && plr->HasGlobalCooldown(m_spellInfo)))
3748  return SPELL_FAILED_NOT_READY;
3749 
3750  // only triggered spells can be processed an ended battleground
3753  if (bg->GetStatus() == STATUS_WAIT_LEAVE)
3754  return SPELL_FAILED_DONT_REPORT;
3755 
3757  {
3761 
3765  }
3766 
3767  // only check at first call, Stealth auras are already removed at second call
3768  // for now, ignore triggered spells
3769  if (strict && !m_IsTriggeredSpell)
3770  {
3771  // Cannot be used in this stance/form
3773  if (shapeError != SPELL_CAST_OK)
3774  return shapeError;
3775 
3778  }
3779 
3780  // caster state requirements
3785 
3786  // cancel autorepeat spells if cast start when moving
3787  // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code)
3789  {
3790  // skip stuck spell to allow use it in falling case and apply spell limitations at movement
3793  return SPELL_FAILED_MOVING;
3794  }
3795 
3796  // check spell cast conditions from database
3797  {
3799  condInfo.mConditionTargets[1] = m_targets.getUnitTarget();
3800  ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id);
3801  if (!conditions.empty() && !sConditionMgr.IsObjectMeetToConditions(condInfo, conditions))
3802  {
3803  // mLastFailedCondition can be NULL if there was an error processing the condition in Condition::Meets (i.e. wrong data for ConditionTarget or others)
3804  if (condInfo.mLastFailedCondition && condInfo.mLastFailedCondition->ErrorType)
3806 
3807  if (!condInfo.mLastFailedCondition || !condInfo.mLastFailedCondition->ConditionTarget)
3809 
3810  return SPELL_FAILED_BAD_TARGETS;
3811  }
3812  }
3813 
3816 
3817  Unit* target = m_targets.getUnitTarget();
3818 
3819  if (target)
3820  {
3821  // target state requirements (not allowed state), apply to self also
3824 
3827 
3828  // @todo Find a way to check for form instead of checking byte flag, probably no problem either way
3829  // Not allow casting on Spirit of Redemption form, includes the priest IN redemption form, except for triggered spells
3831  return SPELL_FAILED_BAD_TARGETS;
3832 
3833  if (target != m_caster)
3834  {
3835  // target state requirements (apply to non-self only), to allow cast affects to self like Dirty Deeds
3838 
3839  // Not allow casting on flying player
3840  if (target->isInFlight())
3841  return SPELL_FAILED_BAD_TARGETS;
3842 
3843  // Must be behind the target.
3844  if (m_spellInfo->AttributesEx2 == 0x100000 && (m_spellInfo->AttributesEx & 0x200) == 0x200 && target->HasInArc(static_cast<float>(M_PI), m_caster)
3845  && (m_spellInfo->SpellFamilyName != SPELLFAMILY_DRUID || m_spellInfo->SpellFamilyFlags != 0x0000000000020000LL))
3846  return SPELL_FAILED_NOT_BEHIND;
3847 
3848  // Target must be facing you.
3849  if ((m_spellInfo->Attributes == 0x150010) && !target->HasInArc(static_cast<float>(M_PI), m_caster))
3850  return SPELL_FAILED_NOT_INFRONT;
3851 
3852  // Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
3854  if (Creature const* targetCreature = target->ToCreature())
3855  if (targetCreature->hasLootRecipient() && !targetCreature->isTappedBy(m_caster->ToPlayer()))
3857 
3859  return SPELL_FAILED_BAD_TARGETS;
3860 
3861  bool isTrigger = (target->ToCreature() && target->ToCreature()->isTrigger());
3862  if (!isTrigger)
3863  {
3864  WorldObject* losTarget = target;
3867  losTarget = dynObj;
3868 
3871  }
3872 
3873  // auto selection spell rank implemented in WorldSession::HandleCastSpellOpcode
3874  // this case can be triggered if rank not found (too low-level target for first rank)
3876  {
3877  for (int i = 0; i < 3; i++)
3878  {
3880  if (target->getLevel() + 10 < m_spellInfo->spellLevel)
3881  return SPELL_FAILED_LOWLEVEL;
3882  }
3883  }
3884  }
3885 
3886  // check pet presence
3887  for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
3888  {
3890  {
3891  target = m_caster->GetGuardianPet();
3892  if (!target)
3893  {
3894  if (m_triggeredByAuraSpell) // not report pet not existence for triggered spells
3895  return SPELL_FAILED_DONT_REPORT;
3896  else
3897  return SPELL_FAILED_NO_PET;
3898  }
3899  else if (!target->IsAlive())
3901  break;
3902  }
3903  }
3904 
3905  //check creature type
3906  //ignore self casts (including area casts when caster selected as target)
3907  if (target != m_caster)
3908  {
3909  if (!CheckTargetCreatureType(target))
3910  {
3911  if (target->GetTypeId() == TYPEID_PLAYER)
3913  else
3914  return SPELL_FAILED_BAD_TARGETS;
3915  }
3916  }
3917 
3918  // @todo this check can be applied and for player to prevent cheating when IsPositiveSpell will return always correct result.
3919  // check target for pet/charmed casts (not self targeted), self targeted cast used for area effects and etc
3921  {
3922  // check correctness positive/negative cast target (pet cast real check and cheating check)
3924  {
3925  //dispel positivity is dependant on target, don't check it
3926  if (m_caster->IsHostileTo(target) && !IsDispel(m_spellInfo))
3927  return SPELL_FAILED_BAD_TARGETS;
3928  }
3929  else
3930  {
3931  if (m_caster->IsFriendlyTo(target))
3932  return SPELL_FAILED_BAD_TARGETS;
3933  }
3934  }
3935 
3936  // spells cannot be cast if player is in fake combat also
3939  }
3940 
3941  // Spell casted only in battleground
3943  if (!m_caster->ToPlayer()->InBattleground())
3945 
3946  // do not allow spells to be cast in arenas
3947  // - with greater than 15 min CD without SPELL_ATTR4_USABLE_IN_ARENA flag
3948  // - with SPELL_ATTR4_NOT_USABLE_IN_ARENA flag
3951  if (MapEntry const* mapEntry = sMapStore.LookupEntry(m_caster->GetMapId()))
3952  if (mapEntry->IsBattleArena())
3954 
3955  // zone check, can only be case in specific zones
3958 
3959  // not let players cast spells at mount (and let do it to creatures)
3962  {
3963  if (m_caster->isInFlight())
3964  return SPELL_FAILED_NOT_FLYING;
3965  else
3966  return SPELL_FAILED_NOT_MOUNTED;
3967  }
3968 
3971 
3972  SpellCastResult castResult = SPELL_CAST_OK;
3973 
3974  // always (except passive spells) check items (focus object can be required for any type casts)
3975  if (!IsPassiveSpell(m_spellInfo->Id))
3976  {
3977  castResult = CheckItems();
3978  if (castResult != SPELL_CAST_OK)
3979  return castResult;
3980  }
3981 
3982  if (!m_IsTriggeredSpell)
3983  {
3985  {
3986  castResult = CheckRange(strict);
3987  if (castResult != SPELL_CAST_OK)
3988  return castResult;
3989  }
3990  }
3991 
3992  // ImpliciteTargetA-B = 38, If fact there is 0 Spell with ImpliciteTargetB=38
3993  if (m_UniqueTargetInfo.empty()) // skip second canCast apply (for delayed spells for example)
3994  {
3995  for (uint8 j = 0; j < MAX_SPELL_EFFECTS; j++)
3996  {
4001  {
4002  ConditionList conditions = sConditionMgr.GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL_SCRIPT_TARGET, m_spellInfo->Id);
4003  if (conditions.empty())
4004  sLog.outErrorDb("Spell (ID: %u) has effect EffectImplicitTargetA/EffectImplicitTargetB = TARGET_UNIT_NEARBY_ENTRY or TARGET_DST_NEARBY_ENTRY, but does not have record in conditions.", m_spellInfo->Id);
4005 
4006  SpellRangeEntry const* srange = sSpellRangeStore.LookupEntry(m_spellInfo->rangeIndex);
4007  float range = GetSpellMaxRange(srange);
4008 
4009  Creature* creatureScriptTarget = NULL;
4010  GameObject* goScriptTarget = NULL;
4011 
4012  for (ConditionList::const_iterator i_spellST = conditions.begin(); i_spellST != conditions.end(); ++i_spellST)
4013  {
4014  if ((*i_spellST)->Type != CONDITION_SPELL_SCRIPT_TARGET)
4015  continue;
4016  switch((*i_spellST)->ConditionValue1)
4017  {
4019  {
4020  GameObject* p_GameObject = NULL;
4021 
4022  if ((*i_spellST)->ConditionValue2)
4023  {
4025  Cell cell(p);
4026 
4027  Oregon::NearestGameObjectEntryInObjectRangeCheck go_check(*m_caster, (*i_spellST)->ConditionValue2, range);
4029 
4031  cell.Visit(p, object_checker, *m_caster->GetMap(), *m_caster, range);
4032 
4033  if (p_GameObject)
4034  {
4035  // remember found target and range, next attempt will find more near target with another entry
4036  creatureScriptTarget = NULL;
4037  goScriptTarget = p_GameObject;
4038  range = go_check.GetLastRange();
4039  }
4040  }
4041  else if (focusObject) //Focus Object
4042  {
4043  float frange = m_caster->GetDistance(focusObject);
4044  if (range >= frange)
4045  {
4046  creatureScriptTarget = NULL;
4047  goScriptTarget = focusObject;
4048  range = frange;
4049  }
4050  }
4051  break;
4052  }
4055  default:
4056  {
4057  Creature* p_Creature = NULL;
4058 
4060  Cell cell(p);
4061  cell.SetNoCreate(); // Really don't know what is that???
4062 
4063  Oregon::NearestCreatureEntryWithLiveStateInObjectRangeCheck u_check(*m_caster, (*i_spellST)->ConditionValue2, (*i_spellST)->ConditionValue1 != SPELL_TARGET_TYPE_DEAD, range);
4065 
4067 
4068  cell.Visit(p, grid_creature_searcher, *m_caster->GetMap(), *m_caster, range);
4069 
4070  if (p_Creature)
4071  {
4072  creatureScriptTarget = p_Creature;
4073  goScriptTarget = NULL;
4074  range = u_check.GetLastRange();
4075  }
4076  break;
4077  }
4078  }
4079  }
4080 
4081  if (creatureScriptTarget)
4082  {
4083  // store coordinates for TARGET_DST_NEARBY_ENTRY
4086  {
4087  m_targets.setDst(creatureScriptTarget->GetPositionX(), creatureScriptTarget->GetPositionY(), creatureScriptTarget->GetPositionZ(), creatureScriptTarget->GetOrientation());
4088 
4090  AddUnitTarget(creatureScriptTarget, j);
4091  }
4092  // store explicit target for TARGET_UNIT_NEARBY_ENTRY
4093  else
4094  AddUnitTarget(creatureScriptTarget, j);
4095  }
4096  else if (goScriptTarget)
4097  {
4098  // store coordinates for TARGET_DST_NEARBY_ENTRY
4101  {
4102  m_targets.setDst(goScriptTarget->GetPositionX(), goScriptTarget->GetPositionY(), goScriptTarget->GetPositionZ(), goScriptTarget->GetOrientation());
4103 
4105  AddGOTarget(goScriptTarget, j);
4106  }
4107  // store explicit target for TARGET_UNIT_NEARBY_ENTRY
4108  else
4109  AddGOTarget(goScriptTarget, j);
4110  }
4111  //Missing DB Entry or targets for this spellEffect.
4112  else
4113  {
4114  // not report target not existence for triggered spells
4116  return SPELL_FAILED_DONT_REPORT;
4117  else
4118  return SPELL_FAILED_BAD_TARGETS;
4119  }
4120  }
4121  }
4122  }
4123 
4124  if (!m_IsTriggeredSpell)
4125  {
4126  SpellCastResult castResult;
4127 
4128  castResult = CheckRange(strict);
4129  if (castResult != SPELL_CAST_OK)
4130  return castResult;
4131 
4132  castResult = CheckPower();
4133  if (castResult != SPELL_CAST_OK)
4134  return castResult;
4135 
4136  castResult = CheckCasterAuras();
4137  if (castResult != SPELL_CAST_OK)
4138  return castResult;
4139  }
4140 
4141  // check for effect-specific restrictions
4142  for (uint32 i = 0; i < MAX_SPELL_EFFECTS; i++)
4143  {
4144  // for effects of spells that have only one target
4145  switch (m_spellInfo->Effect[i])
4146  {
4147  case SPELL_EFFECT_DUMMY:
4148  {
4149  if (SpellCastResult result = CheckDummyCast(i))
4150  if (result != SPELL_CAST_OK)
4151  return result;
4152  break;
4153  }
4155  {
4156  // Hammer of Wrath
4157  if (m_spellInfo->SpellVisual == 7250)
4158  {
4159  if (!m_targets.getUnitTarget())
4161 
4163  return SPELL_FAILED_BAD_TARGETS;
4164  }
4165  break;
4166  }
4168  {
4169  // report single-target "buff degrading" (dont report for triggered spells)
4170  // also works only for positive spells and the buffed is always able to degrade
4171  // his own buffs
4172  if (strict && target != m_caster && target)
4175  if (sSpellMgr.IsNoStackSpellDueToSpell(m_spellInfo->Id, m_spellInfo->Id, false))
4176  if (target->HasHigherRankOfAura(m_spellInfo->Id, i))
4178 
4179  switch(m_spellInfo->EffectApplyAuraName[i])
4180  {
4181  case SPELL_AURA_BIND_SIGHT:
4182  {
4183  // Cannot bind sight across instances/continents.
4184  // Does not affect the same instance/continent, no matter the range.
4185  if(target == m_caster)
4186  return SPELL_FAILED_BAD_TARGETS;
4187  break;
4188  }
4189  }
4190  break;
4191  }
4193  {
4194  if (m_caster->GetTypeId() != TYPEID_PLAYER)
4195  return SPELL_FAILED_BAD_TARGETS;
4196 
4198  break;
4199 
4200  Pet* pet = m_caster->ToPlayer()->GetPet();
4201 
4202  if (!pet)
4203  return SPELL_FAILED_NO_PET;
4204 
4205  SpellEntry const* learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4206 
4207  if (!learn_spellproto)
4208  return SPELL_FAILED_NOT_KNOWN;
4209 
4210  if (!pet->CanTakeMoreActiveSpells(learn_spellproto->Id))
4212 
4213  if (m_spellInfo->spellLevel > pet->getLevel())
4214  return SPELL_FAILED_LOWLEVEL;
4215 
4216  if (!pet->HasTPForSpell(learn_spellproto->Id))
4218 
4219  break;
4220  }
4221  case SPELL_EFFECT_TRIGGER_SPELL_2: // Only Ritual of Summoning
4222  {
4225  break;
4226  }
4228  {
4229  if (m_caster->GetTypeId() != TYPEID_PLAYER)
4230  return SPELL_FAILED_BAD_TARGETS;
4231 
4232  Pet* pet = m_caster->ToPlayer()->GetPet();
4233  if (!pet)
4234  return SPELL_FAILED_NO_PET;
4235 
4236  SpellEntry const* learn_spellproto = sSpellStore.LookupEntry(m_spellInfo->EffectTriggerSpell[i]);
4237 
4238  if (!learn_spellproto)
4239  return SPELL_FAILED_NOT_KNOWN;
4240 
4241  if (!pet->CanTakeMoreActiveSpells(learn_spellproto->Id))
4243 
4244  if (m_spellInfo->spellLevel > pet->getLevel())
4245  return SPELL_FAILED_LOWLEVEL;
4246 
4247  if (!pet->HasTPForSpell(learn_spellproto->Id))
4249 
4250  break;
4251  }
4252  case SPELL_EFFECT_FEED_PET:
4253  {
4255  return SPELL_FAILED_BAD_TARGETS;
4256 
4257  Pet* pet = m_caster->ToPlayer()->GetPet();
4258 
4259  if (!pet)
4260  return SPELL_FAILED_NO_PET;
4261 
4262  if (!pet->HaveInDiet(m_targets.getItemTarget()->GetProto()))
4264 
4267 
4268  if (m_caster->IsInCombat() || pet->IsInCombat())
4270 
4271  break;
4272  }
4275  {
4276  // Can be area effect, Check only for players and not check if target - caster (spell can have multiply drain/burn effects)
4277  if (m_caster->GetTypeId() == TYPEID_PLAYER)
4278  if (Unit* target = m_targets.getUnitTarget())
4279  if (target != m_caster && target->getPowerType() != uint32(m_spellInfo->EffectMiscValue[i]))
4280  if (!(target->ToCreature() && target->ToCreature()->ToPet() && m_spellInfo->EffectMiscValue[i] == POWER_HAPPINESS))
4281  return SPELL_FAILED_BAD_TARGETS;
4282  break;
4283  }
4284  case SPELL_EFFECT_CHARGE:
4285  {
4287  return SPELL_FAILED_ROOTED;
4288 
4289  break;
4290  }
4291  case SPELL_EFFECT_SKINNING:
4292  {
4294  return SPELL_FAILED_BAD_TARGETS;
4295 
4298 
4299  Creature* creature = m_targets.getUnitTarget()->ToCreature();
4300  if (!creature->IsCritter() && !creature->loot.isLooted())
4302 
4303  uint32 skill = creature->GetCreatureTemplate()->GetRequiredLootSkill();
4304 
4305  int32 skillValue = m_caster->ToPlayer()->GetSkillValue(skill);
4306  int32 TargetLevel = m_targets.getUnitTarget()->getLevel();
4307  int32 ReqValue = (skillValue < 100 ? (TargetLevel - 10) * 10 : TargetLevel * 5);
4308  if (ReqValue > skillValue)
4310 
4311  // chance for fail at orange skinning attempt
4312  if ((m_selfContainer && (*m_selfContainer) == this) &&
4313  skillValue < sWorld.GetConfigMaxSkillValue() &&
4314  (ReqValue < 0 ? 0 : ReqValue) > irand(skillValue - 25, skillValue + 37))
4315  return SPELL_FAILED_TRY_AGAIN;
4316 
4317  break;
4318  }
4321  {
4324  break;
4325 
4326  // we need a go target in case of TARGET_GAMEOBJECT
4328  return SPELL_FAILED_BAD_TARGETS;
4329 
4330  // get the lock entry
4331  uint32 lockId = 0;
4332  if (GameObject* go = m_targets.getGOTarget())
4333  {
4334  // In Battleground players can use only flags and banners
4335  if (Player* player = m_caster->ToPlayer())
4336  if (player->InBattleground() && !player->CanUseBattlegroundObject(m_targets.getGOTarget()))
4337  return SPELL_FAILED_TRY_AGAIN;
4338 
4339  lockId = go->GetGOInfo()->GetLockId();
4340 
4341  if (!lockId)
4343  }
4344  else if (Item* itm = m_targets.getItemTarget())
4345  lockId = itm->GetProto()->LockID;
4346  else
4347  return SPELL_FAILED_BAD_TARGETS;
4348 
4349  LockEntry const* lockInfo = sLockStore.LookupEntry(lockId);
4350 
4351  // check lock compatibility
4352  if (lockInfo)
4353  {
4354  // check for lock - key pair (checked by client also, just prevent cheating
4355  bool ok_key = false;
4356  for (int it = 0; it < 5; ++it)
4357  {
4358  switch (lockInfo->keytype[it])
4359  {
4360  case LOCK_KEY_ITEM:
4361  {
4362  if (lockInfo->key[it])
4363  if (m_CastItem && m_CastItem->GetEntry() == lockInfo->key[it])
4364  ok_key = true;
4365  break;
4366  }
4367  case LOCK_KEY_SKILL:
4368  {
4369  // wrong locktype, skip
4370  if (uint32(m_spellInfo->EffectMiscValue[i]) != lockInfo->key[it])
4371  break;
4372 
4373  switch (lockInfo->key[it])
4374  {
4375  case LOCKTYPE_HERBALISM:
4377  ok_key = true;
4378  break;
4379  case LOCKTYPE_MINING:
4381  ok_key = true;
4382  break;
4383  default:
4384  ok_key = true;
4385  break;
4386  }
4387  }
4388  }
4389 
4390  if (ok_key)
4391  break;
4392  }
4393 
4394  if (!ok_key)
4395  return SPELL_FAILED_BAD_TARGETS;
4396  }
4397 
4398  // chance for fail at orange mining/herb/LockPicking gathering attempt
4399  if (!m_selfContainer || ((*m_selfContainer) != this))
4400  break;
4401 
4402  // get the skill value of the player
4403  int32 SkillValue = 0;
4404  bool canFailAtMax = true;
4406  {
4407  SkillValue = m_caster->ToPlayer()->GetSkillValue(SKILL_HERBALISM);
4408  canFailAtMax = false;
4409  }
4411  {
4412  SkillValue = m_caster->ToPlayer()->GetSkillValue(SKILL_MINING);
4413  canFailAtMax = false;
4414  }
4417 
4418  // castitem check: rogue using skeleton keys. the skill values should not be added in this case.
4419  if (m_CastItem)
4420  SkillValue = 0;
4421 
4422  // add the damage modifier from the spell casted (cheat lock / skeleton key etc.) (use m_currentBasePoints, CalculateDamage returns wrong value)
4423  // @todo is this a hack?
4424  SkillValue += m_currentBasePoints[i] + m_spellInfo->EffectBaseDice[i];
4425 
4426  // get the required lock value
4427  int32 ReqValue = 0;
4428  if (lockInfo)
4429  {
4431  ReqValue = lockInfo->requiredlockskill;
4432  else
4433  ReqValue = lockInfo->requiredminingskill;
4434  }
4435 
4436  // skill doesn't meet the required value
4437  if (ReqValue > SkillValue)
4439 
4440  // chance for failure in orange gather / lockpick (gathering skill can't fail at maxskill)
4441  if (canFailAtMax || SkillValue < sWorld.GetConfigMaxSkillValue())
4442  if (ReqValue > irand(SkillValue - 25, SkillValue + 37))
4443  return SPELL_FAILED_TRY_AGAIN;
4444 
4445  break;
4446  }
4447  // Bring the pet back to the land of the living
4449  {
4450  Creature* pet = m_caster->GetGuardianPet();
4451  if (pet && pet->IsAlive())
4453 
4454  // Do not revive dismissed pets, they are not dead
4457 
4458  // Attempting to revive a non existing pet?
4459  if (m_caster->isPlayer() && !m_caster->ToPlayer()->doesOwnPet())
4460  return SPELL_FAILED_NO_PET;
4461 
4462  break;
4463  }
4464  // Called when we start channeling 'Dismiss pet' spell
4466  {
4467  // Don't start dismissing the pet if it's dead!
4468  Pet* pet = m_caster->ToPlayer()->GetPet();
4469  if (!pet || !pet->IsAlive())
4471 
4472  break;
4473  }
4474  // This is generic summon effect
4475  case SPELL_EFFECT_SUMMON:
4476  {
4477  SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(m_spellInfo->EffectMiscValueB[i]);
4478  if (!SummonProperties)
4479  break;
4480  switch (SummonProperties->Category)
4481  {
4482  case SUMMON_CATEGORY_PET:
4485  // intentional missing break, check both GetPetGUID() and GetCharmGUID for SUMMON_CATEGORY_PET
4487  if (m_caster->GetCharmGUID())
4489  break;
4490  }
4491  break;
4492  }
4494  {
4495  // Check these things only for player hunters
4496  if (