Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
Spell.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#include "Battlefield.h"
7#include "BattlefieldMgr.h"
8#include "Battleground.h"
9#include "CellImpl.h"
10#include "Common.h"
11#include "ConditionMgr.h"
12#include "DatabaseEnv.h"
13#include "DB2Stores.h"
14#include "DisableMgr.h"
15#include "DynamicObject.h"
16#include "GridNotifiers.h"
17#include "GridNotifiersImpl.h"
18#include "Group.h"
19#include "Guild.h"
20#include "InstanceScript.h"
21#include "Log.h"
22#include "LootMgr.h"
23#include "MapManager.h"
24#include "ObjectAccessor.h"
25#include "ObjectMgr.h"
26#include "Opcodes.h"
27#include "Pet.h"
28#include "Player.h"
29#include "RuntimeMetrics.h"
30#include "ScriptMgr.h"
31#include "SharedDefines.h"
32#include "Spell.h"
33#include "SpellAuraEffects.h"
34#include "SpellCalculations.h"
35#include "SpellInfo.h"
36#include "SpellMgr.h"
37#include "SpellScript.h"
38#include "SpellValidation.h"
39#include "TemporarySummon.h"
40#include "Totem.h"
41#include "Unit.h"
42#include "UpdateData.h"
43#include "UpdateMask.h"
44#include "Util.h"
45#include "Vehicle.h"
46#include "VMapFactory.h"
47#include "World.h"
48#include "WorldPacket.h"
49#include "WorldSession.h"
50
52
54{
55 _position.Relocate(0, 0, 0, 0);
57 _transportOffset.Relocate(0, 0, 0, 0);
58}
59
60SpellDestination::SpellDestination(float x, float y, float z, float orientation, uint32 mapId)
61{
62 _position.Relocate(x, y, z, orientation);
64 _position.m_mapId = mapId;
65}
66
68{
69 _position.Relocate(pos);
71}
72
74{
77 _position.Relocate(wObj);
78 _position.SetOrientation(wObj.GetOrientation());
79}
80
92
93SpellCastTargets::SpellCastTargets(Unit* caster, uint32 targetMask, uint64 targetGuid, uint64 itemTargetGuid, uint64 srcTransportGuid, uint64 destTransportGuid, Position srcPos, Position destPos, float elevation, float missileSpeed, std::string targetString) :
94 m_targetMask(targetMask), m_objectTargetGUID(targetGuid), m_itemTargetGUID(itemTargetGuid), m_elevation(elevation), m_speed(missileSpeed), m_strTarget(targetString)
95{
96 m_objectTarget = NULL;
97 m_itemTarget = NULL;
99
100 m_src._transportGUID = srcTransportGuid;
101 if (m_src._transportGUID)
102 m_src._transportOffset.Relocate(srcPos);
103 else
104 m_src._position.Relocate(srcPos);
105
106 m_dst._transportGUID = destTransportGuid;
107 if (m_dst._transportGUID)
108 m_dst._transportOffset.Relocate(destPos);
109 else
110 m_dst._position.Relocate(destPos);
111
112 Update(caster);
113}
114
116
118{
119 data >> m_targetMask;
120
122 return;
123
126
129
131 {
132 data.readPackGUID(m_src._transportGUID);
133 if (m_src._transportGUID)
134 data >> m_src._transportOffset.PositionXYZStream();
135 else
136 data >> m_src._position.PositionXYZStream();
137 }
138 else
139 {
140 m_src._transportGUID = caster->GetTransGUID();
141 if (m_src._transportGUID)
142 m_src._transportOffset.Relocate(caster->GetTransOffsetX(), caster->GetTransOffsetY(), caster->GetTransOffsetZ(), caster->GetTransOffsetO());
143 else
144 m_src._position.Relocate(caster);
145 }
146
148 {
149 data.readPackGUID(m_dst._transportGUID);
150 if (m_dst._transportGUID)
151 data >> m_dst._transportOffset.PositionXYZStream();
152 else
153 data >> m_dst._position.PositionXYZStream();
154 }
155 else
156 {
157 m_dst._transportGUID = caster->GetTransGUID();
158 if (m_dst._transportGUID)
159 m_dst._transportOffset.Relocate(caster->GetTransOffsetX(), caster->GetTransOffsetY(), caster->GetTransOffsetZ(), caster->GetTransOffsetO());
160 else
161 m_dst._position.Relocate(caster);
162 }
163
165 data >> m_strTarget;
166
167 Update(caster);
168}
169
171{
172 data << uint32(m_targetMask);
173
176
178 {
179 if (m_itemTarget)
180 data.append(m_itemTarget->GetPackGUID());
181 else
182 data << uint8(0);
183 }
184
186 {
187 data.appendPackGUID(m_src._transportGUID); // relative position guid here - transport for example
188 if (m_src._transportGUID)
189 data << m_src._transportOffset.PositionXYZStream();
190 else
191 data << m_src._position.PositionXYZStream();
192 }
193
195 {
196 data.appendPackGUID(m_dst._transportGUID); // relative position guid here - transport for example
197 if (m_dst._transportGUID)
198 data << m_dst._transportOffset.PositionXYZStream();
199 else
200 data << m_dst._position.PositionXYZStream();
201 }
202
204 data << m_strTarget;
205}
206
208{
210 {
211 case HIGHGUID_PLAYER:
212 case HIGHGUID_VEHICLE:
213 case HIGHGUID_UNIT:
214 case HIGHGUID_PET:
215 return m_objectTargetGUID;
216 default:
217 return 0LL;
218 }
219}
220
222{
223 if (m_objectTarget)
224 return m_objectTarget->ToUnit();
225 return NULL;
226}
227
229{
230 if (!target)
231 return;
232
233 m_objectTarget = target;
234 m_objectTargetGUID = target->GetGUID();
236}
237
239{
241 {
245 return m_objectTargetGUID;
246 default:
247 return 0LL;
248 }
249}
250
252{
253 if (m_objectTarget)
254 return m_objectTarget->ToGameObject();
255 return NULL;
256}
257
259{
260 if (!target)
261 return;
262
263 m_objectTarget = target;
264 m_objectTargetGUID = target->GetGUID();
266}
267
269{
271 {
272 case HIGHGUID_CORPSE:
273 return m_objectTargetGUID;
274 default:
275 return 0LL;
276 }
277}
278
280{
281 if (m_objectTarget)
282 return m_objectTarget->ToCorpse();
283 return NULL;
284}
285
290
295
302
304{
305 if (!item)
306 return;
307
308 m_itemTarget = item;
309 m_itemTargetGUID = item->GetGUID();
310 m_itemTargetEntry = item->GetEntry();
312}
313
322
331
333{
334 return &m_src;
335}
336
338{
339 return &m_src._position;
340}
341
342void SpellCastTargets::SetSrc(float x, float y, float z)
343{
344 m_src = SpellDestination(x, y, z);
346}
347
353
359
361{
363
364 if (m_src._transportGUID)
365 {
366 Position offset;
367 m_src._position.GetPositionOffsetTo(pos, offset);
368 m_src._transportOffset.RelocateOffset(offset);
369 }
370 m_src._position.Relocate(pos);
371}
372
377
379{
380 return &m_dst;
381}
382
384{
385 return &m_dst._position;
386}
387
388void SpellCastTargets::SetDst(float x, float y, float z, float orientation, uint32 mapId)
389{
390 m_dst = SpellDestination(x, y, z, orientation, mapId);
392}
393
399
405
407{
408 m_dst = spellTargets.m_dst;
410}
411
413{
415
416 if (m_dst._transportGUID)
417 {
418 Position offset;
419 m_dst._position.GetPositionOffsetTo(pos, offset);
420 m_dst._transportOffset.RelocateOffset(offset);
421 }
422 m_dst._position.Relocate(pos);
423}
424
429
431{
433
434 m_itemTarget = NULL;
435 if (caster->GetTypeId() == TypeID::TYPEID_PLAYER)
436 {
437 Player* player = caster->ToPlayer();
441 if (m_itemTargetGUID == TRADE_SLOT_NONTRADED) // here it is not guid but slot. Also prevents hacking slots
442 if (TradeData* pTrade = player->GetTradeData())
443 m_itemTarget = pTrade->GetTraderData()->GetItem(TRADE_SLOT_NONTRADED);
444
445 if (m_itemTarget)
446 m_itemTargetEntry = m_itemTarget->GetEntry();
447 }
448
449 // update positions by transport move
450 if (HasSrc() && m_src._transportGUID)
451 {
452 if (WorldObject* transport = ObjectAccessor::GetWorldObject(*caster, m_src._transportGUID))
453 {
454 m_src._position.Relocate(transport);
455 m_src._position.RelocateOffset(m_src._transportOffset);
456 }
457 }
458
459 if (HasDst() && m_dst._transportGUID)
460 {
461 if (WorldObject* transport = ObjectAccessor::GetWorldObject(*caster, m_dst._transportGUID))
462 {
463 m_dst._position.Relocate(transport);
464 m_dst._position.RelocateOffset(m_dst._transportOffset);
465 }
466 }
467}
468
470{
471 if (!m_targetMask)
472 SF_LOG_INFO("spells", "No targets");
473
474 SF_LOG_INFO("spells", "target mask: %u", m_targetMask);
476 SF_LOG_INFO("spells", "Object target: " UI64FMTD, m_objectTargetGUID);
478 SF_LOG_INFO("spells", "Item target: " UI64FMTD, m_itemTargetGUID);
480 SF_LOG_INFO("spells", "Trade item target: " UI64FMTD, m_itemTargetGUID);
482 SF_LOG_INFO("spells", "Source location: transport guid:" UI64FMTD " trans offset: %s position: %s", m_src._transportGUID, m_src._transportOffset.ToString().c_str(), m_src._position.ToString().c_str());
484 SF_LOG_INFO("spells", "Destination location: transport guid:" UI64FMTD " trans offset: %s position: %s", m_dst._transportGUID, m_dst._transportOffset.ToString().c_str(), m_dst._position.ToString().c_str());
486 SF_LOG_INFO("spells", "String: %s", m_strTarget.c_str());
487 SF_LOG_INFO("spells", "speed: %f", m_speed);
488 SF_LOG_INFO("spells", "elevation: %f", m_elevation);
489}
490
492{
493 for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
494 EffectBasePoints[i] = proto->Effects[i].BasePoints;
496 RadiusMod = 1.0f;
497 AuraStackAmount = 1;
498}
499
500Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, uint64 originalCasterGUID, bool skipCheck) :
501 m_spellInfo(sSpellMgr->GetSpellForDifficultyFromSpell(info, caster)),
502 m_caster((info->AttributesEx6& SPELL_ATTR6_CAST_BY_CHARMER&& caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster),
504{
506 m_skipCheck = skipCheck;
507 m_selfContainer = NULL;
509 m_executedCurrently = false;
510 m_needComboPoints = m_spellInfo->NeedsComboPoints();
512 m_delayStart = 0;
514
516 m_auraScaleMask = 0;
517
518 // Get data for type of attack
519 switch (m_spellInfo->DmgClass)
520 {
521 case SPELL_DAMAGE_CLASS_MELEE:
522 if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND)
523 m_attackType = WeaponAttackType::OFF_ATTACK;
524 else
525 m_attackType = WeaponAttackType::BASE_ATTACK;
526 break;
527 case SPELL_DAMAGE_CLASS_RANGED:
528 m_attackType = m_spellInfo->IsRangedWeaponSpell() ? WeaponAttackType::RANGED_ATTACK : WeaponAttackType::BASE_ATTACK;
529 break;
530 default:
531 // Wands
532 if (m_spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG)
533 m_attackType = WeaponAttackType::RANGED_ATTACK;
534 else
535 m_attackType = WeaponAttackType::BASE_ATTACK;
536 break;
537 }
538
539 m_spellSchoolMask = info->GetSchoolMask(); // Can be override for some spell (wand shoot for example)
540
542 // wand case
543 if ((m_caster->getClassMask() & CLASSMASK_WAND_USERS) != 0 && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
544 if (Item* pItem = m_caster->ToPlayer()->GetWeaponForAttack(WeaponAttackType::RANGED_ATTACK))
545 m_spellSchoolMask = SpellSchoolMask(1 << pItem->GetTemplate()->DamageType);
546
547 if (originalCasterGUID)
548 m_originalCasterGUID = originalCasterGUID;
549 else
550 m_originalCasterGUID = m_caster->GetGUID();
551
552 if (m_originalCasterGUID == m_caster->GetGUID())
554 else
555 {
556 m_originalCaster = ObjectAccessor::GetUnit(*m_caster, m_originalCasterGUID);
557 if (m_originalCaster && !m_originalCaster->IsInWorld())
558 m_originalCaster = NULL;
559 }
560
562 _triggeredCastFlags = triggerFlags;
565
566 m_CastItem = NULL;
567 m_castItemGUID = 0;
568
569 unitTarget = NULL;
570 itemTarget = NULL;
571 gameObjTarget = NULL;
572 focusObject = NULL;
573 m_cast_count = 0;
574 m_glyphIndex = 0;
575 m_researchData = NULL;
577 m_spellAura = NULL;
578
579 //Auto Shot & Shoot (wand)
580 m_autoRepeat = m_spellInfo->IsAutoRepeatRangedSpell();
581
582 m_runesState = 0;
583 m_powerType = 0;
586 m_powerCost = 0; // setup to correct value in Spell::prepare, must not be used before.
587 m_casttime = 0; // setup to correct value in Spell::prepare, must not be used before.
588 m_timer = 0; // will set to castime in prepare
589
591
592 // Determine if spell can be reflected back to the caster
593 // Patch 1.2 notes: Spell Reflection no longer reflects abilities
596 && !m_spellInfo->IsPassive() && !m_spellInfo->IsPositive();
597
599
600 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
602}
603
605{
606 // unload scripts
607 while (!m_loadedScripts.empty())
608 {
609 std::list<SpellScript*>::iterator itr = m_loadedScripts.begin();
610 (*itr)->_Unload();
611 delete (*itr);
612 m_loadedScripts.erase(itr);
613 }
614
616 {
617 // Clean the reference to avoid later crash.
618 // If this error is repeating, we may have to add an ASSERT to better track down how we get into this case.
619 SF_LOG_ERROR("spells", "SPELL: deleting spell for spell ID %u. However, spell still referenced.", m_spellInfo->Id);
620 *m_selfContainer = NULL;
621 }
622
623 if (m_caster && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
624 ASSERT(m_caster->ToPlayer()->m_spellModTakingSpell != this);
625
626 delete m_spellValue;
627 delete m_researchData;
628
630}
631
633{
634 m_targets = targets;
635 // this function tries to correct spell explicit targets for spell
636 // client doesn't send explicit targets correctly sometimes - we need to fix such spells serverside
637 // this also makes sure that we correctly send explicit targets to client (removes redundant data)
638 uint32 neededTargets = m_spellInfo->GetExplicitTargetMask();
639
640 if (WorldObject* target = m_targets.GetObjectTarget())
641 {
642 // check if object target is valid with needed target flags
643 // for unit case allow corpse target mask because player with not released corpse is a unit target
644 if ((target->ToUnit() && !(neededTargets & (TARGET_FLAG_UNIT_MASK | TARGET_FLAG_CORPSE_MASK)))
645 || (target->ToGameObject() && !(neededTargets & TARGET_FLAG_GAMEOBJECT_MASK))
646 || (target->ToCorpse() && !(neededTargets & TARGET_FLAG_CORPSE_MASK)))
647 m_targets.RemoveObjectTarget();
648 }
649 else
650 {
651 // try to select correct unit target if not provided by client or by serverside cast
652 if (neededTargets & (TARGET_FLAG_UNIT_MASK))
653 {
654 Unit* unit = NULL;
655 // try to use player selection as a target
656 if (Player* playerCaster = m_caster->ToPlayer())
657 {
658 // selection has to be found and to be valid target for the spell
659 if (Unit* selectedUnit = ObjectAccessor::GetUnit(*m_caster, playerCaster->GetTarget()))
660 if (m_spellInfo->CheckExplicitTarget(m_caster, selectedUnit) == SpellCastResult::SPELL_CAST_OK)
661 unit = selectedUnit;
662 }
663 // try to use attacked unit as a target
664 else if ((m_caster->GetTypeId() == TypeID::TYPEID_UNIT) && neededTargets & (TARGET_FLAG_UNIT_ENEMY | TARGET_FLAG_UNIT))
665 unit = m_caster->GetVictim();
666
667 // didn't find anything - let's use self as target
668 if (!unit && neededTargets & (TARGET_FLAG_UNIT_RAID | TARGET_FLAG_UNIT_PARTY | TARGET_FLAG_UNIT_ALLY))
669 unit = m_caster;
670
671 m_targets.SetUnitTarget(unit);
672 }
673 }
674
675 // check if spell needs dst target
676 if (neededTargets & TARGET_FLAG_DEST_LOCATION)
677 {
678 // and target isn't set
679 if (!m_targets.HasDst())
680 {
681 // try to use unit target if provided
682 if (WorldObject* target = targets.GetObjectTarget())
683 m_targets.SetDst(*target);
684 // or use self if not available
685 else
686 m_targets.SetDst(*m_caster);
687 }
688 }
689 else
690 m_targets.RemoveDst();
691
692 if (neededTargets & TARGET_FLAG_SOURCE_LOCATION)
693 {
694 if (!targets.HasSrc())
695 m_targets.SetSrc(*m_caster);
696 }
697 else
698 m_targets.RemoveSrc();
699}
700
702{
703 // here go all explicit target changes made to explicit targets after spell prepare phase is finished
704 if (Unit* target = m_targets.GetUnitTarget())
705 {
706 // check for explicit target redirection, for Grounding Totem for example
707 if (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT_ENEMY
708 || (m_spellInfo->GetExplicitTargetMask() & TARGET_FLAG_UNIT && !m_spellInfo->IsPositive()))
709 {
710 Unit* redirect;
711 switch (m_spellInfo->DmgClass)
712 {
714 redirect = m_caster->GetMagicHitRedirectTarget(target, m_spellInfo);
715 break;
718 redirect = m_caster->GetMeleeHitRedirectTarget(target, m_spellInfo);
719 break;
720 default:
721 redirect = NULL;
722 break;
723 }
724 if (redirect && (redirect != target))
725 m_targets.SetUnitTarget(redirect);
726 }
727 }
728}
729
731{
732 // select targets for cast phase
734
735 uint32 processedAreaEffectsMask = 0;
736 for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
737 {
738 // not call for empty effect.
739 // Also some spells use not used effect targets for store targets for dummy effect in triggered spells
740 if (!m_spellInfo->Effects[i].IsEffect())
741 continue;
742
743 // set expected type of implicit targets to be sent to client
744 uint32 implicitTargetMask = GetTargetFlagMask(m_spellInfo->Effects[i].TargetA.GetObjectType()) | GetTargetFlagMask(m_spellInfo->Effects[i].TargetB.GetObjectType());
745 if (implicitTargetMask & TARGET_FLAG_UNIT)
746 m_targets.SetTargetFlag(TARGET_FLAG_UNIT);
747 if (implicitTargetMask & (TARGET_FLAG_GAMEOBJECT | TARGET_FLAG_GAMEOBJECT_ITEM))
748 m_targets.SetTargetFlag(TARGET_FLAG_GAMEOBJECT);
749
750 SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetA, processedAreaEffectsMask);
751 SelectEffectImplicitTargets(SpellEffIndex(i), m_spellInfo->Effects[i].TargetB, processedAreaEffectsMask);
752
753 // Select targets of effect based on effect type
754 // those are used when no valid target could be added for spell effect based on spell target type
755 // some spell effects use explicit target as a default target added to target map (like SPELL_EFFECT_LEARN_SPELL)
756 // some spell effects add target to target map only when target type specified (like SPELL_EFFECT_WEAPON)
757 // some spell effects don't add anything to target map (confirmed with sniffs) (like SPELL_EFFECT_DESTROY_ALL_TOTEMS)
759
760 if (m_targets.HasDst())
761 AddDestTarget(*m_targets.GetDst(), i);
762
763 if (m_spellInfo->IsChanneled())
764 {
765 uint8 mask = (1 << i);
766 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
767 {
768 if (ihit->effectMask & mask)
769 {
771 break;
772 }
773 }
774 }
775 else if (m_auraScaleMask)
776 {
777 bool checkLvl = !m_UniqueTargetInfo.empty();
778 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();)
779 {
780 // remove targets which did not pass min level check
781 if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask)
782 {
783 // Do not check for selfcast
784 if (!ihit->scaleAura && ihit->targetGUID != m_caster->GetGUID())
785 {
786 m_UniqueTargetInfo.erase(ihit++);
787 continue;
788 }
789 }
790 ++ihit;
791 }
792 if (checkLvl && m_UniqueTargetInfo.empty())
793 {
795 finish(false);
796 }
797 }
798 }
799
800 if (m_targets.HasDst())
801 {
802 if (m_targets.HasTraj())
803 {
804 float speed = m_targets.GetSpeedXY();
805 if (speed > 0.0f)
806 m_delayMoment = (uint64)floor(m_targets.GetDist2d() / speed * 1000.0f);
807 }
808 else if (m_spellInfo->Speed > 0.0f)
809 {
810 float dist = m_caster->GetDistance(*m_targets.GetDstPos());
812 m_delayMoment = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
813 else
814 m_delayMoment = uint64(m_spellInfo->Speed * 1000.0f);
815 }
816 }
817}
818
819void Spell::SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const& targetType, uint32& processedEffectMask)
820{
821 if (!targetType.GetTarget())
822 return;
823
824 uint32 effectMask = 1 << effIndex;
825 // set the same target list for all effects
826 // some spells appear to need this, however this requires more research
827 switch (targetType.GetSelectionCategory())
828 {
832 // targets for effect already selected
833 if (effectMask & processedEffectMask)
834 return;
835 // choose which targets we can select at once
836 for (uint32 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j)
837 {
838 SpellEffectInfo const* effects = GetSpellInfo()->Effects;
839 if (effects[j].IsEffect() &&
840 effects[effIndex].TargetA.GetTarget() == effects[j].TargetA.GetTarget() &&
841 effects[effIndex].TargetB.GetTarget() == effects[j].TargetB.GetTarget() &&
842 effects[effIndex].ImplicitTargetConditions == effects[j].ImplicitTargetConditions &&
843 effects[effIndex].CalcRadius(m_caster) == effects[j].CalcRadius(m_caster) &&
845 {
846 effectMask |= 1 << j;
847 }
848 }
849 processedEffectMask |= effectMask;
850 break;
851 default:
852 break;
853 }
854
855 switch (targetType.GetSelectionCategory())
856 {
858 SelectImplicitChannelTargets(effIndex, targetType);
859 break;
861 SelectImplicitNearbyTargets(effIndex, targetType, effectMask);
862 break;
864 SelectImplicitConeTargets(effIndex, targetType, effectMask);
865 break;
867 SelectImplicitAreaTargets(effIndex, targetType, effectMask);
868 break;
870 switch (targetType.GetObjectType())
871 {
873 switch (targetType.GetReferenceType())
874 {
876 m_targets.SetSrc(*m_caster);
877 break;
878 default:
879 ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_SRC");
880 break;
881 }
882 break;
884 switch (targetType.GetReferenceType())
885 {
887 SelectImplicitCasterDestTargets(effIndex, targetType);
888 break;
890 SelectImplicitTargetDestTargets(effIndex, targetType);
891 break;
893 SelectImplicitDestDestTargets(effIndex, targetType);
894 break;
895 default:
896 ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT_DEST");
897 break;
898 }
899 break;
900 default:
901 switch (targetType.GetReferenceType())
902 {
904 SelectImplicitCasterObjectTargets(effIndex, targetType);
905 break;
907 SelectImplicitTargetObjectTargets(effIndex, targetType);
908 break;
909 default:
910 ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target reference type for TARGET_TYPE_OBJECT");
911 break;
912 }
913 break;
914 }
915 break;
917 SF_LOG_DEBUG("spells", "SPELL: target type %u, found in spellID %u, effect %u is not implemented yet!", m_spellInfo->Id, effIndex, targetType.GetTarget());
918 break;
919 default:
920 ASSERT(false && "Spell::SelectEffectImplicitTargets: received not implemented select target category");
921 break;
922 }
923}
924
926{
928 {
929 ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target reference type");
930 return;
931 }
932
933 Spell* channeledSpell = m_originalCaster->GetCurrentSpell(CURRENT_CHANNELED_SPELL);
934 if (!channeledSpell)
935 {
936 SF_LOG_DEBUG("spells", "Spell::SelectImplicitChannelTargets: cannot find channel spell for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
937 return;
938 }
939 switch (targetType.GetTarget())
940 {
942 {
944 CallScriptObjectTargetSelectHandlers(target, effIndex);
945 // unit target may be no longer avalible - teleported out of map for example
946 if (target && target->ToUnit())
947 AddUnitTarget(target->ToUnit(), 1 << effIndex);
948 else
949 SF_LOG_DEBUG("spells", "SPELL: cannot find channel spell target for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
950 break;
951 }
953 if (channeledSpell->m_targets.HasDst())
954 m_targets.SetDst(channeledSpell->m_targets);
956 {
957 CallScriptObjectTargetSelectHandlers(target, effIndex);
958 if (target)
959 m_targets.SetDst(*target);
960 }
961 else
962 SF_LOG_DEBUG("spells", "SPELL: cannot find channel spell destination for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
963 break;
965 m_targets.SetDst(*channeledSpell->GetCaster());
966 break;
967 default:
968 ASSERT(false && "Spell::SelectImplicitChannelTargets: received not implemented target type");
969 break;
970 }
971}
972
974{
976 {
977 ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target reference type");
978 return;
979 }
980
981 float range = 0.0f;
982 switch (targetType.GetCheckType())
983 {
985 range = m_spellInfo->GetMaxRange(false, m_caster, this);
986 break;
991 range = m_spellInfo->GetMaxRange(true, m_caster, this);
992 break;
995 range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive(), m_caster, this);
996 break;
997 default:
998 ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented selection check type");
999 break;
1000 }
1001
1002 ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
1003
1004 // handle emergency case - try to use other provided targets if no conditions provided
1005 if (targetType.GetCheckType() == TARGET_CHECK_ENTRY && (!condList || condList->empty()))
1006 {
1007 SF_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: no conditions entry for target with TARGET_CHECK_ENTRY of spell ID %u, effect %u - selecting default targets", m_spellInfo->Id, effIndex);
1008 switch (targetType.GetObjectType())
1009 {
1011 if (m_spellInfo->RequiresSpellFocus)
1012 {
1013 if (focusObject)
1014 AddGOTarget(focusObject, effMask);
1015 return;
1016 }
1017 break;
1019 if (m_spellInfo->RequiresSpellFocus)
1020 {
1021 if (focusObject)
1022 m_targets.SetDst(*focusObject);
1023 return;
1024 }
1025 break;
1026 default:
1027 break;
1028 }
1029 }
1030
1031 WorldObject* target = SearchNearbyTarget(range, targetType.GetObjectType(), targetType.GetCheckType(), condList);
1032 if (!target)
1033 {
1034 SF_LOG_DEBUG("spells", "Spell::SelectImplicitNearbyTargets: cannot find nearby target for spell ID %u, effect %u", m_spellInfo->Id, effIndex);
1035 return;
1036 }
1037
1038 CallScriptObjectTargetSelectHandlers(target, effIndex);
1039
1040 switch (targetType.GetObjectType())
1041 {
1043 if (Unit* unitTarget = target->ToUnit())
1044 AddUnitTarget(unitTarget, effMask, true, false);
1045 break;
1047 if (GameObject* gobjTarget = target->ToGameObject())
1048 AddGOTarget(gobjTarget, effMask);
1049 break;
1051 m_targets.SetDst(*target);
1052 break;
1053 default:
1054 ASSERT(false && "Spell::SelectImplicitNearbyTargets: received not implemented target object type");
1055 break;
1056 }
1057
1058 SelectImplicitChainTargets(effIndex, targetType, target, effMask);
1059}
1060
1062{
1064 {
1065 ASSERT(false && "Spell::SelectImplicitConeTargets: received not implemented target reference type");
1066 return;
1067 }
1068 std::list<WorldObject*> targets;
1069 SpellTargetObjectTypes objectType = targetType.GetObjectType();
1070 SpellTargetCheckTypes selectionType = targetType.GetCheckType();
1071 ConditionList* condList = m_spellInfo->Effects[effIndex].ImplicitTargetConditions;
1072 float coneAngle = M_PI / 2;
1073 float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
1074
1075 if (uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList))
1076 {
1077 Skyfire::WorldObjectSpellConeTargetCheck check(coneAngle, radius, m_caster, m_spellInfo, selectionType, condList);
1080
1082
1083 if (!targets.empty())
1084 {
1085 // Other special target selection goes here
1086 if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
1087 Skyfire::Containers::RandomResizeList(targets, maxTargets);
1088
1089 // for compability with older code - add only unit and go targets
1091 std::list<Unit*> unitTargets;
1092 std::list<GameObject*> gObjTargets;
1093
1094 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
1095 {
1096 if (Unit* unitTarget = (*itr)->ToUnit())
1097 unitTargets.push_back(unitTarget);
1098 else if (GameObject* gObjTarget = (*itr)->ToGameObject())
1099 gObjTargets.push_back(gObjTarget);
1100 }
1101
1102 for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
1103 AddUnitTarget(*itr, effMask, false);
1104
1105 for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr)
1106 AddGOTarget(*itr, effMask);
1107 }
1108 }
1109}
1110
1112{
1113 Unit* referer = NULL;
1114 switch (targetType.GetReferenceType())
1115 {
1119 referer = m_caster;
1120 break;
1122 referer = m_targets.GetUnitTarget();
1123 break;
1125 {
1126 // find last added target for this effect
1127 for (std::list<TargetInfo>::reverse_iterator ihit = m_UniqueTargetInfo.rbegin(); ihit != m_UniqueTargetInfo.rend(); ++ihit)
1128 {
1129 if (ihit->effectMask & (1 << effIndex))
1130 {
1131 referer = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
1132 break;
1133 }
1134 }
1135 break;
1136 }
1137 default:
1138 ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
1139 return;
1140 }
1141 if (!referer)
1142 return;
1143
1144 Position const* center = NULL;
1145 switch (targetType.GetReferenceType())
1146 {
1148 center = m_targets.GetSrcPos();
1149 break;
1151 center = m_targets.GetDstPos();
1152 break;
1156 center = referer;
1157 break;
1158 default:
1159 ASSERT(false && "Spell::SelectImplicitAreaTargets: received not implemented target reference type");
1160 return;
1161 }
1162 std::list<WorldObject*> targets;
1163 float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
1164 SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
1165
1166 // Custom entries
1168 switch (m_spellInfo->Id)
1169 {
1170 case 46584: // Raise Dead
1171 {
1172 if (Player* playerCaster = m_caster->ToPlayer())
1173 {
1174 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
1175 {
1176 switch ((*itr)->GetTypeId())
1177 {
1180 {
1181 Unit* unitTarget = (*itr)->ToUnit();
1182 if (unitTarget->IsAlive() || !playerCaster->isHonorOrXPTarget(unitTarget)
1183 || ((unitTarget->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID - 1))) == 0)
1184 || (unitTarget->GetDisplayId() != unitTarget->GetNativeDisplayId()))
1185 break;
1186 AddUnitTarget(unitTarget, effMask, false);
1187 // no break;
1188 }
1189 case TypeID::TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet
1190 m_targets.SetDst(*(*itr));
1191 return; // nothing more to do here
1192 default:
1193 break;
1194 }
1195 }
1196 }
1197 return; // don't add targets to target map
1198 }
1199 // Corpse Explosion
1200 case 49158:
1201 case 51325:
1202 case 51326:
1203 case 51327:
1204 case 51328:
1205 // check if our target is not valid (spell can target ghoul or dead unit)
1206 if (!(m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId() &&
1207 ((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID())
1208 || m_targets.GetUnitTarget()->isDead())))
1209 {
1210 // remove existing targets
1212
1213 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
1214 {
1215 switch ((*itr)->GetTypeId())
1216 {
1219 if (!(*itr)->ToUnit()->isDead())
1220 break;
1221 AddUnitTarget((*itr)->ToUnit(), 1 << effIndex, false);
1222 return;
1223 default:
1224 break;
1225 }
1226 }
1227 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
1228 m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
1230 finish(false);
1231 }
1232 return;
1233 default:
1234 break;
1235 }
1236
1238
1239 std::list<Unit*> unitTargets;
1240 std::list<GameObject*> gObjTargets;
1241 // for compability with older code - add only unit and go targets
1243 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
1244 {
1245 if (Unit* unitTarget = (*itr)->ToUnit())
1246 unitTargets.push_back(unitTarget);
1247 else if (GameObject* gObjTarget = (*itr)->ToGameObject())
1248 gObjTargets.push_back(gObjTarget);
1249 }
1250
1251 if (!unitTargets.empty())
1252 {
1253 // Special target selection for smart heals and energizes
1254 uint32 maxSize = 0;
1255 int32 power = -1;
1256 switch (m_spellInfo->SpellFamilyName)
1257 {
1259 switch (m_spellInfo->Id)
1260 {
1261 case 52759: // Ancestral Awakening
1262 case 71610: // Echoes of Light (Althor's Abacus normal version)
1263 case 71641: // Echoes of Light (Althor's Abacus heroic version)
1264 maxSize = 1;
1265 power = POWER_HEALTH;
1266 break;
1267 case 54968: // Glyph of Holy Light
1268 maxSize = m_spellInfo->MaxAffectedTargets;
1269 power = POWER_HEALTH;
1270 break;
1271 case 57669: // Replenishment
1272 // In arenas Replenishment may only affect the caster
1273 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && m_caster->ToPlayer()->InArena())
1274 {
1275 unitTargets.clear();
1276 unitTargets.push_back(m_caster);
1277 break;
1278 }
1279 maxSize = 10;
1280 power = POWER_MANA;
1281 break;
1282 default:
1283 break;
1284 }
1285 break;
1286 case SPELLFAMILY_PRIEST:
1287 if (m_spellInfo->SpellFamilyFlags[0] == 0x10000000) // Circle of Healing
1288 {
1289 maxSize = m_caster->HasAura(55675) ? 6 : 5; // Glyph of Circle of Healing
1290 power = POWER_HEALTH;
1291 }
1292 else if (m_spellInfo->Id == 64844) // Divine Hymn
1293 {
1294 maxSize = 3;
1295 power = POWER_HEALTH;
1296 }
1297 else if (m_spellInfo->Id == 64904) // Hymn of Hope
1298 {
1299 maxSize = 3;
1300 power = POWER_MANA;
1301 }
1302 else
1303 break;
1304
1305 // Remove targets outside caster's raid
1306 for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end();)
1307 {
1308 if (!(*itr)->IsInRaidWith(m_caster))
1309 itr = unitTargets.erase(itr);
1310 else
1311 ++itr;
1312 }
1313 break;
1314 case SPELLFAMILY_DRUID:
1315 if (m_spellInfo->SpellFamilyFlags[1] == 0x04000000) // Wild Growth
1316 {
1317 maxSize = m_caster->HasAura(62970) ? 6 : 5; // Glyph of Wild Growth
1318 power = POWER_HEALTH;
1319 }
1320 else
1321 break;
1322
1323 // Remove targets outside caster's raid
1324 for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end();)
1325 if (!(*itr)->IsInRaidWith(m_caster))
1326 itr = unitTargets.erase(itr);
1327 else
1328 ++itr;
1329 break;
1330 default:
1331 break;
1332 }
1333
1334 if (maxSize && power != -1)
1335 {
1336 if (Powers(power) == POWER_HEALTH)
1337 {
1338 if (unitTargets.size() > maxSize)
1339 {
1340 unitTargets.sort(Skyfire::HealthPctOrderPred());
1341 unitTargets.resize(maxSize);
1342 }
1343 }
1344 else
1345 {
1346 for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end();)
1347 if ((*itr)->getPowerType() != (Powers)power)
1348 itr = unitTargets.erase(itr);
1349 else
1350 ++itr;
1351
1352 if (unitTargets.size() > maxSize)
1353 {
1354 unitTargets.sort(Skyfire::PowerPctOrderPred((Powers)power));
1355 unitTargets.resize(maxSize);
1356 }
1357 }
1358 }
1359
1360 // Other special target selection goes here
1361 if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
1362 Skyfire::Containers::RandomResizeList(unitTargets, maxTargets);
1363
1364 for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
1365 AddUnitTarget(*itr, effMask, false);
1366 }
1367
1368 if (!gObjTargets.empty())
1369 {
1370 if (uint32 maxTargets = m_spellValue->MaxAffectedTargets)
1371 Skyfire::Containers::RandomResizeList(gObjTargets, maxTargets);
1372
1373 for (std::list<GameObject*>::iterator itr = gObjTargets.begin(); itr != gObjTargets.end(); ++itr)
1374 AddGOTarget(*itr, effMask);
1375 }
1376}
1377
1379{
1380 switch (targetType.GetTarget())
1381 {
1382 case TARGET_DEST_CASTER:
1383 m_targets.SetDst(*m_caster);
1384 return;
1385 case TARGET_DEST_HOME:
1386 if (Player* playerCaster = m_caster->ToPlayer())
1387 m_targets.SetDst(playerCaster->m_homebindX, playerCaster->m_homebindY, playerCaster->m_homebindZ, playerCaster->GetOrientation(), playerCaster->m_homebindMapId);
1388 return;
1389 case TARGET_DEST_DB:
1390 if (SpellTargetPosition const* st = sSpellMgr->GetSpellTargetPosition(m_spellInfo->Id, effIndex))
1391 {
1394 m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation, (int32)st->target_mapId);
1395 else if (st->target_mapId == m_caster->GetMapId())
1396 m_targets.SetDst(st->target_X, st->target_Y, st->target_Z, st->target_Orientation);
1397 }
1398 else
1399 {
1400 SF_LOG_DEBUG("spells", "SPELL: unknown target coordinates for spell ID %u", m_spellInfo->Id);
1401 WorldObject* target = m_targets.GetObjectTarget();
1402 m_targets.SetDst(target ? *target : *m_caster);
1403 }
1404 return;
1406 {
1407 float min_dis = m_spellInfo->GetMinRange(true);
1408 float max_dis = m_spellInfo->GetMaxRange(true);
1409 float dis = (float)rand_norm() * (max_dis - min_dis) + min_dis;
1410 float x, y, z, angle;
1411 angle = (float)rand_norm() * static_cast<float>(M_PI * 35.0f / 180.0f) - static_cast<float>(M_PI * 17.5f / 180.0f);
1412 m_caster->GetClosePoint(x, y, z, DEFAULT_WORLD_OBJECT_SIZE, dis, angle);
1413
1414 float ground = z;
1415 float liquidLevel = m_caster->GetMap()->GetWaterOrGroundLevel(x, y, z, &ground);
1416 if (liquidLevel <= ground) // When there is no liquid Map::GetWaterOrGroundLevel returns ground level
1417 {
1420 finish(false);
1421 return;
1422 }
1423
1424 if (ground + 0.75 > liquidLevel)
1425 {
1428 finish(false);
1429 return;
1430 }
1431
1432 m_targets.SetDst(x, y, liquidLevel, m_caster->GetOrientation());
1433 return;
1434 }
1435 default:
1436 break;
1437 }
1438
1439 float dist;
1440 float angle = targetType.CalcDirectionAngle();
1441 float objSize = m_caster->GetObjectSize();
1442 if (targetType.GetTarget() == TARGET_DEST_CASTER_SUMMON)
1443 dist = PET_FOLLOW_DIST;
1444 else
1445 dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
1446
1447 if (dist < objSize)
1448 dist = objSize;
1449 else if (targetType.GetTarget() == TARGET_DEST_CASTER_RANDOM)
1450 dist = objSize + (dist - objSize) * (float)rand_norm();
1451
1452 Position pos;
1453 if (targetType.GetTarget() == TARGET_DEST_CASTER_FRONT_LEAP)
1454 m_caster->GetFirstCollisionPosition(pos, dist, angle);
1455 else
1456 m_caster->GetNearPosition(pos, dist, angle);
1457 m_targets.SetDst(*m_caster);
1458 m_targets.ModDst(pos);
1459}
1460
1462{
1463 WorldObject* target = m_targets.GetObjectTarget();
1464 switch (targetType.GetTarget())
1465 {
1468 m_targets.SetDst(*target);
1469 return;
1470 default:
1471 break;
1472 }
1473
1474 float angle = targetType.CalcDirectionAngle();
1475 float objSize = target->GetObjectSize();
1476 float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
1477 if (dist < objSize)
1478 dist = objSize;
1479 else if (targetType.GetTarget() == TARGET_DEST_TARGET_RANDOM)
1480 dist = objSize + (dist - objSize) * (float)rand_norm();
1481
1482 Position pos;
1483 target->GetNearPosition(pos, dist, angle);
1484 m_targets.SetDst(*target);
1485 m_targets.ModDst(pos);
1486}
1487
1489{
1490 // set destination to caster if no dest provided
1491 // can only happen if previous destination target could not be set for some reason
1492 // (not found nearby target, or channel target for example
1493 // maybe we should abort the spell in such case?
1494 if (!m_targets.HasDst())
1495 m_targets.SetDst(*m_caster);
1496
1497 switch (targetType.GetTarget())
1498 {
1502 case TARGET_DEST_DEST:
1503 return;
1504 case TARGET_DEST_TRAJ:
1506 return;
1507 default:
1508 break;
1509 }
1510
1511 float angle = targetType.CalcDirectionAngle();
1512 float dist = m_spellInfo->Effects[effIndex].CalcRadius(m_caster);
1513 if (targetType.GetTarget() == TARGET_DEST_DEST_RANDOM)
1514 dist *= (float)rand_norm();
1515
1516 Position pos = *m_targets.GetDstPos();
1517 m_caster->MovePosition(pos, dist, angle);
1518 m_targets.ModDst(pos);
1519}
1520
1522{
1523 WorldObject* target = NULL;
1524 bool checkIfValid = true;
1525
1526 switch (targetType.GetTarget())
1527 {
1528 case TARGET_UNIT_CASTER:
1529 target = m_caster;
1530 checkIfValid = false;
1531 break;
1532 case TARGET_UNIT_MASTER:
1533 target = m_caster->GetCharmerOrOwner();
1534 break;
1535 case TARGET_UNIT_PET:
1536 target = m_caster->GetGuardianPet();
1537 break;
1539 if (m_caster->IsSummon())
1540 target = m_caster->ToTempSummon()->GetSummoner();
1541 break;
1543 target = m_caster->GetVehicleBase();
1544 break;
1553 if (m_caster->GetTypeId() == TypeID::TYPEID_UNIT && m_caster->ToCreature()->IsVehicle())
1554 target = m_caster->GetVehicleKit()->GetPassenger(targetType.GetTarget() - TARGET_UNIT_PASSENGER_0);
1555 break;
1556 default:
1557 break;
1558 }
1559
1560 CallScriptObjectTargetSelectHandlers(target, effIndex);
1561
1562 if (target && target->ToUnit())
1563 AddUnitTarget(target->ToUnit(), 1 << effIndex, checkIfValid);
1564}
1565
1567{
1568 ASSERT((m_targets.GetObjectTarget() || m_targets.GetItemTarget()) && "Spell::SelectImplicitTargetObjectTargets - no explicit object or item target available!");
1569
1570 WorldObject* target = m_targets.GetObjectTarget();
1571
1572 CallScriptObjectTargetSelectHandlers(target, effIndex);
1573
1574 if (target)
1575 {
1576 if (Unit* unit = target->ToUnit())
1577 AddUnitTarget(unit, 1 << effIndex, true, false);
1578 else if (GameObject* gobj = target->ToGameObject())
1579 AddGOTarget(gobj, 1 << effIndex);
1580
1581 SelectImplicitChainTargets(effIndex, targetType, target, 1 << effIndex);
1582 }
1583 // Script hook can remove object target and we would wrongly land here
1584 else if (Item* item = m_targets.GetItemTarget())
1585 AddItemTarget(item, 1 << effIndex);
1586}
1587
1589{
1590 uint32 maxTargets = m_spellInfo->Effects[effIndex].ChainTarget;
1591 if (Player* modOwner = m_caster->GetSpellModOwner())
1592 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this);
1593
1594 if (maxTargets > 1)
1595 {
1596 // mark damage multipliers as used
1597 for (uint32 k = effIndex; k < MAX_SPELL_EFFECTS; ++k)
1598 if (effMask & (1 << k))
1599 m_damageMultipliers[k] = 1.0f;
1600 m_applyMultiplierMask |= effMask;
1601
1602 std::list<WorldObject*> targets;
1603 SearchChainTargets(targets, maxTargets - 1, target, targetType.GetObjectType(), targetType.GetCheckType(),
1604 m_spellInfo->Effects[effIndex].ImplicitTargetConditions, targetType.GetTarget() == TARGET_UNIT_TARGET_CHAINHEAL_ALLY);
1605
1606 // Chain primary target is added earlier
1608
1609 // for backward compability
1610 std::list<Unit*> unitTargets;
1611 for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
1612 if (Unit* unitTarget = (*itr)->ToUnit())
1613 unitTargets.push_back(unitTarget);
1614
1615 for (std::list<Unit*>::iterator itr = unitTargets.begin(); itr != unitTargets.end(); ++itr)
1616 AddUnitTarget(*itr, effMask, false);
1617 }
1618}
1619
1620static float tangent(float x)
1621{
1622 x = tan(x);
1623 //if (x < std::numeric_limits<float>::max() && x > -std::numeric_limits<float>::max()) return x;
1624 //if (x >= std::numeric_limits<float>::max()) return std::numeric_limits<float>::max();
1625 //if (x <= -std::numeric_limits<float>::max()) return -std::numeric_limits<float>::max();
1626 if (x < 100000.0f && x > -100000.0f) return x;
1627 if (x >= 100000.0f) return 100000.0f;
1628 if (x <= 100000.0f) return -100000.0f;
1629 return 0.0f;
1630}
1631
1632#define DEBUG_TRAJ(a) //a
1633
1635{
1636 if (!m_targets.HasTraj())
1637 return;
1638
1639 float dist2d = m_targets.GetDist2d();
1640 if (!dist2d)
1641 return;
1642
1643 float srcToDestDelta = m_targets.GetDstPos()->m_positionZ - m_targets.GetSrcPos()->m_positionZ;
1644
1645 std::list<WorldObject*> targets;
1649 if (targets.empty())
1650 return;
1651
1653
1654 float b = tangent(m_targets.GetElevation());
1655 float a = (srcToDestDelta - dist2d * b) / (dist2d * dist2d);
1656 if (a > -0.0001f)
1657 a = 0;
1658 DEBUG_TRAJ(SF_LOG_ERROR("spells", "Spell::SelectTrajTargets: a %f b %f", a, b);)
1659
1660 float bestDist = m_spellInfo->GetMaxRange(false);
1661
1662 std::list<WorldObject*>::const_iterator itr = targets.begin();
1663 for (; itr != targets.end(); ++itr)
1664 {
1665 if (Unit* unitTarget = (*itr)->ToUnit())
1666 if (m_caster == *itr || m_caster->IsOnVehicle(unitTarget) || (unitTarget)->GetVehicle())//(*itr)->IsOnVehicle(m_caster))
1667 continue;
1668
1669 const float size = std::max((*itr)->GetObjectSize() * 0.7f, 1.0f); // 1/sqrt(3)
1671 const float objDist2d = m_targets.GetSrcPos()->GetExactDist2d(*itr) * std::cos(m_targets.GetSrcPos()->GetRelativeAngle(*itr));
1672 const float dz = (*itr)->GetPositionZ() - m_targets.GetSrcPos()->m_positionZ;
1673
1674 DEBUG_TRAJ(SF_LOG_ERROR("spells", "Spell::SelectTrajTargets: check %u, dist between %f %f, height between %f %f.", (*itr)->GetEntry(), objDist2d - size, objDist2d + size, dz - size, dz + size);)
1675
1676 float dist = objDist2d - size;
1677 float height = dist * (a * dist + b);
1678 DEBUG_TRAJ(SF_LOG_ERROR("spells", "Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)
1679 if (dist < bestDist&& height < dz + size && height > dz - size)
1680 {
1681 bestDist = dist > 0 ? dist : 0;
1682 break;
1683 }
1684
1685#define CHECK_DIST {\
1686 DEBUG_TRAJ(SF_LOG_ERROR("spells", "Spell::SelectTrajTargets: dist %f, height %f.", dist, height);)\
1687 if (dist > bestDist)\
1688 continue;\
1689 if (dist < objDist2d + size && dist > objDist2d - size)\
1690 {\
1691 bestDist = dist;\
1692 break;\
1693 }\
1694 }
1695
1696 if (!a)
1697 {
1698 height = dz - size;
1699 dist = height / b;
1700 CHECK_DIST;
1701
1702 height = dz + size;
1703 dist = height / b;
1704 CHECK_DIST;
1705
1706 continue;
1707 }
1708
1709 height = dz - size;
1710 float sqrt1 = b * b + 4 * a * height;
1711 if (sqrt1 > 0)
1712 {
1713 sqrt1 = sqrt(sqrt1);
1714 dist = (sqrt1 - b) / (2 * a);
1715 CHECK_DIST;
1716 }
1717
1718 height = dz + size;
1719 float sqrt2 = b * b + 4 * a * height;
1720 if (sqrt2 > 0)
1721 {
1722 sqrt2 = sqrt(sqrt2);
1723 dist = (sqrt2 - b) / (2 * a);
1724 CHECK_DIST;
1725
1726 dist = (-sqrt2 - b) / (2 * a);
1727 CHECK_DIST;
1728 }
1729
1730 if (sqrt1 > 0)
1731 {
1732 dist = (-sqrt1 - b) / (2 * a);
1733 CHECK_DIST;
1734 }
1735 }
1736
1737 if (m_targets.GetSrcPos()->GetExactDist2d(m_targets.GetDstPos()) > bestDist)
1738 {
1739 float x = m_targets.GetSrcPos()->m_positionX + std::cos(m_caster->GetOrientation()) * bestDist;
1740 float y = m_targets.GetSrcPos()->m_positionY + std::sin(m_caster->GetOrientation()) * bestDist;
1741 float z = m_targets.GetSrcPos()->m_positionZ + bestDist * (a * bestDist + b);
1742
1743 if (itr != targets.end())
1744 {
1745 float distSq = (*itr)->GetExactDistSq(x, y, z);
1746 float sizeSq = (*itr)->GetObjectSize();
1747 sizeSq *= sizeSq;
1748 DEBUG_TRAJ(SF_LOG_ERROR("spells", "Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
1749 if (distSq > sizeSq)
1750 {
1751 float factor = 1 - sqrt(sizeSq / distSq);
1752 x += factor * ((*itr)->GetPositionX() - x);
1753 y += factor * ((*itr)->GetPositionY() - y);
1754 z += factor * ((*itr)->GetPositionZ() - z);
1755
1756 distSq = (*itr)->GetExactDistSq(x, y, z);
1757 DEBUG_TRAJ(SF_LOG_ERROR("spells", "Initial %f %f %f %f %f", x, y, z, distSq, sizeSq);)
1758 }
1759 }
1760
1761 Position trajDst;
1762 trajDst.Relocate(x, y, z, m_caster->GetOrientation());
1763 m_targets.ModDst(trajDst);
1764 }
1765
1766 if (Vehicle* veh = m_caster->GetVehicleKit())
1767 veh->SetLastShootPos(*m_targets.GetDstPos());
1768}
1769
1771{
1772 // special case for SPELL_EFFECT_SUMMON_RAF_FRIEND and SPELL_EFFECT_SUMMON_PLAYER
1774 switch (m_spellInfo->Effects[effIndex].Effect)
1775 {
1778 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && m_caster->GetTarget())
1779 {
1780 WorldObject* target = ObjectAccessor::FindPlayer(m_caster->GetTarget());
1781
1783
1784 if (target && target->ToPlayer())
1785 AddUnitTarget(target->ToUnit(), 1 << effIndex, false);
1786 }
1787 return;
1788 default:
1789 break;
1790 }
1791
1792 // select spell implicit targets based on effect type
1793 if (!m_spellInfo->Effects[effIndex].GetImplicitTargetType())
1794 return;
1795
1796 uint32 targetMask = m_spellInfo->Effects[effIndex].GetMissingTargetMask();
1797
1798 if (!targetMask)
1799 return;
1800
1801 WorldObject* target = NULL;
1802
1803 switch (m_spellInfo->Effects[effIndex].GetImplicitTargetType())
1804 {
1805 // add explicit object target or self to the target map
1807 // player which not released his spirit is Unit, but target flag for it is TARGET_FLAG_CORPSE_MASK
1809 {
1810 if (Unit* unitTarget = m_targets.GetUnitTarget())
1811 target = unitTarget;
1812 else if (targetMask & TARGET_FLAG_CORPSE_MASK)
1813 {
1814 if (Corpse* corpseTarget = m_targets.GetCorpseTarget())
1815 {
1817 if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
1818 target = owner;
1819 }
1820 }
1821 else //if (targetMask & TARGET_FLAG_UNIT_MASK)
1822 target = m_caster;
1823 }
1824 if (targetMask & TARGET_FLAG_ITEM_MASK)
1825 {
1826 if (Item* itemTarget = m_targets.GetItemTarget())
1827 AddItemTarget(itemTarget, 1 << effIndex);
1828 return;
1829 }
1830 if (targetMask & TARGET_FLAG_GAMEOBJECT_MASK)
1831 target = m_targets.GetGOTarget();
1832 break;
1833 // add self to the target map
1835 if (targetMask & TARGET_FLAG_UNIT_MASK)
1836 target = m_caster;
1837 break;
1838 default:
1839 break;
1840 }
1841
1843
1844 if (target)
1845 {
1846 if (target->ToUnit())
1847 AddUnitTarget(target->ToUnit(), 1 << effIndex, false);
1848 else if (target->ToGameObject())
1849 AddGOTarget(target->ToGameObject(), 1 << effIndex);
1850 }
1851}
1852
1854{
1855 // this function selects which containers need to be searched for spell target
1857
1858 // filter searchers based on searched object type
1859 switch (objType)
1860 {
1867 break;
1871 break;
1872 default:
1873 break;
1874 }
1875 if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_DEAD))
1876 retMask &= ~GRID_MAP_TYPE_MASK_CORPSE;
1877 if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_PLAYERS)
1879 if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_ONLY_TARGET_GHOSTS)
1880 retMask &= GRID_MAP_TYPE_MASK_PLAYER;
1881
1882 if (condList)
1883 retMask &= sConditionMgr->GetSearcherTypeMaskForConditionList(*condList);
1884 return retMask;
1885}
1886
1887template<class SEARCHER>
1888void Spell::SearchTargets(SEARCHER& searcher, uint32 containerMask, Unit* referer, Position const* pos, float radius)
1889{
1890 if (!containerMask)
1891 return;
1892
1893 // search world and grid for possible targets
1894 bool searchInGrid = containerMask & (GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_GAMEOBJECT);
1895 bool searchInWorld = containerMask & (GRID_MAP_TYPE_MASK_CREATURE | GRID_MAP_TYPE_MASK_PLAYER | GRID_MAP_TYPE_MASK_CORPSE);
1896 if (searchInGrid || searchInWorld)
1897 {
1898 float x, y;
1899 x = pos->GetPositionX();
1900 y = pos->GetPositionY();
1901
1903 Cell cell(p);
1904 cell.SetNoCreate();
1905
1906 Map& map = *(referer->GetMap());
1907
1908 if (searchInWorld)
1909 {
1910 TypeContainerVisitor<SEARCHER, WorldTypeMapContainer> world_object_notifier(searcher);
1911 cell.Visit(p, world_object_notifier, map, radius, x, y);
1912 }
1913 if (searchInGrid)
1914 {
1915 TypeContainerVisitor<SEARCHER, GridTypeMapContainer > grid_object_notifier(searcher);
1916 cell.Visit(p, grid_object_notifier, map, radius, x, y);
1917 }
1918 }
1919}
1920
1922{
1923 WorldObject* target = NULL;
1924 uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList);
1925 if (!containerTypeMask)
1926 return NULL;
1927 Skyfire::WorldObjectSpellNearbyTargetCheck check(range, m_caster, m_spellInfo, selectionType, condList);
1930 return target;
1931}
1932
1933void Spell::SearchAreaTargets(std::list<WorldObject*>& targets, float range, Position const* position, Unit* referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList* condList)
1934{
1935 uint32 containerTypeMask = GetSearcherTypeMask(objectType, condList);
1936 if (!containerTypeMask)
1937 return;
1938 Skyfire::WorldObjectSpellAreaTargetCheck check(range, position, m_caster, referer, m_spellInfo, selectionType, condList);
1941}
1942
1943void Spell::SearchChainTargets(std::list<WorldObject*>& targets, uint32 chainTargets, WorldObject* target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList* condList, bool isChainHeal)
1944{
1945 // max dist for jump target selection
1946 float jumpRadius = 0.0f;
1947 switch (m_spellInfo->DmgClass)
1948 {
1950 // 7.5y for multi shot
1951 jumpRadius = 7.5f;
1952 break;
1954 // 5y for swipe, cleave and similar
1955 jumpRadius = 5.0f;
1956 break;
1959 // 12.5y for chain heal spell since 3.2 patch
1960 if (isChainHeal)
1961 jumpRadius = 12.5f;
1962 // 10y as default for magic chain spells
1963 else
1964 jumpRadius = 10.0f;
1965 break;
1966 }
1967
1968 // chain lightning/heal spells and similar - allow to jump at larger distance and go out of los
1969 bool isBouncingFar = (m_spellInfo->AttributesEx4 & SPELL_ATTR4_AREA_TARGET_CHAIN
1970 || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_NONE
1971 || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC);
1972
1973 // max dist which spell can reach
1974 float searchRadius = jumpRadius;
1975 if (isBouncingFar)
1976 searchRadius *= chainTargets;
1977
1978 std::list<WorldObject*> tempTargets;
1979 SearchAreaTargets(tempTargets, searchRadius, target, m_caster, objectType, selectType, condList);
1980 tempTargets.remove(target);
1981
1982 // remove targets which are always invalid for chain spells
1983 // for some spells allow only chain targets in front of caster (swipe for example)
1984 if (!isBouncingFar)
1985 {
1986 for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end();)
1987 {
1988 std::list<WorldObject*>::iterator checkItr = itr++;
1989 if (!m_caster->HasInArc(static_cast<float>(M_PI), *checkItr))
1990 tempTargets.erase(checkItr);
1991 }
1992 }
1993
1994 while (chainTargets)
1995 {
1996 // try to get unit for next chain jump
1997 std::list<WorldObject*>::iterator foundItr = tempTargets.end();
1998 // get unit with highest hp deficit in dist
1999 if (isChainHeal)
2000 {
2001 uint32 maxHPDeficit = 0;
2002 for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
2003 {
2004 if (Unit* unitTarget = (*itr)->ToUnit())
2005 {
2006 uint32 deficit = unitTarget->GetMaxHealth() - unitTarget->GetHealth();
2007 if ((deficit > maxHPDeficit || foundItr == tempTargets.end()) && target->IsWithinDist(unitTarget, jumpRadius) && target->IsWithinLOSInMap(unitTarget))
2008 {
2009 foundItr = itr;
2010 maxHPDeficit = deficit;
2011 }
2012 }
2013 }
2014 }
2015 // get closest object
2016 else
2017 {
2018 for (std::list<WorldObject*>::iterator itr = tempTargets.begin(); itr != tempTargets.end(); ++itr)
2019 {
2020 if (foundItr == tempTargets.end())
2021 {
2022 if ((!isBouncingFar || target->IsWithinDist(*itr, jumpRadius)) && target->IsWithinLOSInMap(*itr))
2023 foundItr = itr;
2024 }
2025 else if (target->GetDistanceOrder(*itr, *foundItr) && target->IsWithinLOSInMap(*itr))
2026 foundItr = itr;
2027 }
2028 }
2029 // not found any valid target - chain ends
2030 if (foundItr == tempTargets.end())
2031 break;
2032 target = *foundItr;
2033 tempTargets.erase(foundItr);
2034 targets.push_back(target);
2035 --chainTargets;
2036 }
2037}
2038
2047
2048void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
2049{
2050 //==========================================================================================
2051 // Now fill data for trigger system, need know:
2052 // can spell trigger another or not (m_canTrigger)
2053 // Create base triggers flags for Attacker and Victim (m_procAttacker, m_procVictim and m_procEx)
2054 //==========================================================================================
2055
2057 // Get data for type of attack and fill base info for trigger
2058 switch (m_spellInfo->DmgClass)
2059 {
2064 else
2067 break;
2069 // Auto attack
2070 if (m_spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG)
2071 {
2074 }
2075 else // Ranged spell attack
2076 {
2079 }
2080 break;
2081 default:
2082 if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON &&
2083 m_spellInfo->EquippedItemSubClassMask & (1 << ITEM_SUBCLASS_WEAPON_WAND)
2084 && m_spellInfo->AttributesEx2 & SPELL_ATTR2_AUTOREPEAT_FLAG) // Wands auto attack
2085 {
2088 }
2089 // For other spells trigger procflags are set in Spell::DoAllEffectOnTarget
2090 // Because spell positivity is dependant on target
2091 }
2093
2094 // Hunter trap spells - activation proc for Lock and Load, Entrapment and Misdirection
2095 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER &&
2096 (m_spellInfo->SpellFamilyFlags[0] & 0x18 || // Freezing and Frost Trap, Freezing Arrow
2097 m_spellInfo->Id == 57879 || // Snake Trap - done this way to avoid double proc
2098 m_spellInfo->SpellFamilyFlags[2] & 0x00024000)) // Explosive and Immolation Trap
2099 {
2101 }
2102
2103 /* Effects which are result of aura proc from triggered spell cannot proc
2104 to prevent chain proc of these spells */
2105
2106 // Hellfire Effect - trigger as DOT
2107 if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags[0] & 0x00000040)
2108 {
2111 }
2112
2113 // Ranged autorepeat attack is set as triggered spell - ignore it
2115 {
2122 }
2123 // Totem casts require spellfamilymask defined in spell_proc_event to proc
2124 if (m_originalCaster && m_caster != m_originalCaster && m_caster->GetTypeId() == TypeID::TYPEID_UNIT && m_caster->ToCreature()->IsTotem() && m_caster->IsControlledByPlayer())
2126}
2127
2129{
2130 m_UniqueTargetInfo.clear();
2131 m_UniqueGOTargetInfo.clear();
2132 m_UniqueItemInfo.clear();
2133 m_delayMoment = 0;
2134}
2135
2136void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/, bool implicit /*= true*/)
2137{
2138 for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
2139 if (!m_spellInfo->Effects[effIndex].IsEffect() || !CheckEffectTarget(target, effIndex))
2140 effectMask &= ~(1 << effIndex);
2141
2142 // no effects left
2143 if (!effectMask)
2144 return;
2145
2146 if (checkIfValid)
2147 if (m_spellInfo->CheckTarget(m_caster, target, implicit) != SpellCastResult::SPELL_CAST_OK)
2148 return;
2149
2150 // Check for effect immune skip if immuned
2151 for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
2152 if (target->IsImmunedToSpellEffect(m_spellInfo, effIndex))
2153 effectMask &= ~(1 << effIndex);
2154
2155 uint64 targetGUID = target->GetGUID();
2156
2157 // Lookup target in already in list
2158 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
2159 {
2160 if (targetGUID == ihit->targetGUID) // Found in list
2161 {
2162 ihit->effectMask |= effectMask; // Immune effects removed from mask
2163 ihit->scaleAura = false;
2164 if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask && m_caster != target)
2165 {
2166 SpellInfo const* auraSpell = m_spellInfo->GetFirstRankSpell();
2167 if (uint32(target->getLevel() + 10) >= auraSpell->SpellLevel)
2168 ihit->scaleAura = true;
2169 }
2170 return;
2171 }
2172 }
2173
2174 // This is new target calculate data for him
2175
2176 // Get spell hit result on target
2177 TargetInfo targetInfo;
2178 targetInfo.targetGUID = targetGUID; // Store target GUID
2179 targetInfo.effectMask = effectMask; // Store all effects not immune
2180 targetInfo.processed = false; // Effects not apply on target
2181 targetInfo.alive = target->IsAlive();
2182 targetInfo.damage = 0;
2183 targetInfo.crit = false;
2184 targetInfo.scaleAura = false;
2185 if (m_auraScaleMask && targetInfo.effectMask == m_auraScaleMask && m_caster != target)
2186 {
2187 SpellInfo const* auraSpell = m_spellInfo->GetFirstRankSpell();
2188 if (uint32(target->getLevel() + 10) >= auraSpell->SpellLevel)
2189 targetInfo.scaleAura = true;
2190 }
2191
2192 // Calculate hit result
2193 if (m_originalCaster)
2194 {
2195 targetInfo.missCondition = m_originalCaster->SpellHitResult(target, m_spellInfo, m_canReflect);
2196 if (m_skipCheck && targetInfo.missCondition != SPELL_MISS_IMMUNE)
2197 targetInfo.missCondition = SPELL_MISS_NONE;
2198 }
2199 else
2200 targetInfo.missCondition = SPELL_MISS_EVADE; //SPELL_MISS_NONE;
2201
2202 // Spell have speed - need calculate incoming time
2203 // Incoming time is zero for self casts. At least I think so.
2204 if (m_spellInfo->Speed > 0.0f && m_caster != target)
2205 {
2206 // calculate spell incoming interval
2208 float dist = m_caster->GetDistance(target->GetPositionX(), target->GetPositionY(), target->GetPositionZ());
2209
2210 if (dist < 5.0f)
2211 dist = 5.0f;
2212
2213 if (!(m_spellInfo->AttributesEx9 & SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
2214 targetInfo.timeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
2215 else
2216 targetInfo.timeDelay = uint64(m_spellInfo->Speed * 1000.0f);
2217
2218 // Calculate minimum incoming time
2219 if (m_delayMoment == 0 || m_delayMoment > targetInfo.timeDelay)
2220 m_delayMoment = targetInfo.timeDelay;
2221 }
2222 else
2223 targetInfo.timeDelay = 0LL;
2224
2225 // If target reflect spell back to caster
2226 if (targetInfo.missCondition == SPELL_MISS_REFLECT)
2227 {
2228 // Calculate reflected spell result on caster
2229 targetInfo.reflectResult = m_caster->SpellHitResult(m_caster, m_spellInfo, m_canReflect);
2230
2231 if (targetInfo.reflectResult == SPELL_MISS_REFLECT) // Impossible reflect again, so simply deflect spell
2232 targetInfo.reflectResult = SPELL_MISS_PARRY;
2233
2234 // Increase time interval for reflected spells by 1.5
2235 targetInfo.timeDelay += targetInfo.timeDelay >> 1;
2236 }
2237 else
2238 targetInfo.reflectResult = SPELL_MISS_NONE;
2239
2240 // Add target to list
2241 m_UniqueTargetInfo.push_back(targetInfo);
2242}
2243
2245{
2246 for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
2247 {
2248 if (!m_spellInfo->Effects[effIndex].IsEffect())
2249 effectMask &= ~(1 << effIndex);
2250 else
2251 {
2252 switch (m_spellInfo->Effects[effIndex].Effect)
2253 {
2258 effectMask &= ~(1 << effIndex);
2259 break;
2260 default:
2261 break;
2262 }
2263 }
2264 }
2265
2266 if (!effectMask)
2267 return;
2268
2269 uint64 targetGUID = go->GetGUID();
2270
2271 // Lookup target in already in list
2272 for (std::list<GOTargetInfo>::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
2273 {
2274 if (targetGUID == ihit->targetGUID) // Found in list
2275 {
2276 ihit->effectMask |= effectMask; // Add only effect mask
2277 return;
2278 }
2279 }
2280
2281 // This is new target calculate data for him
2282
2283 GOTargetInfo target;
2284 target.targetGUID = targetGUID;
2285 target.effectMask = effectMask;
2286 target.processed = false; // Effects not apply on target
2287
2288 // Spell have speed - need calculate incoming time
2289 if (m_spellInfo->Speed > 0.0f)
2290 {
2291 // calculate spell incoming interval
2292 float dist = m_caster->GetDistance(go->GetPositionX(), go->GetPositionY(), go->GetPositionZ());
2293 if (dist < 5.0f)
2294 dist = 5.0f;
2295
2296 if (!(m_spellInfo->AttributesEx9 & SPELL_ATTR9_SPECIAL_DELAY_CALCULATION))
2297 target.timeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f));
2298 else
2299 target.timeDelay = uint64(m_spellInfo->Speed * 1000.0f);
2300
2301 if (m_delayMoment == 0 || m_delayMoment > target.timeDelay)
2302 m_delayMoment = target.timeDelay;
2303 }
2304 else
2305 target.timeDelay = 0LL;
2306
2307 // Add target to list
2308 m_UniqueGOTargetInfo.push_back(target);
2309}
2310
2311void Spell::AddItemTarget(Item* item, uint32 effectMask)
2312{
2313 for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
2314 if (!m_spellInfo->Effects[effIndex].IsEffect())
2315 effectMask &= ~(1 << effIndex);
2316
2317 // no effects left
2318 if (!effectMask)
2319 return;
2320
2321 // Lookup target in already in list
2322 for (std::list<ItemTargetInfo>::iterator ihit = m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
2323 {
2324 if (item == ihit->item) // Found in list
2325 {
2326 ihit->effectMask |= effectMask; // Add only effect mask
2327 return;
2328 }
2329 }
2330
2331 // This is new target add data
2332
2333 ItemTargetInfo target;
2334 target.item = item;
2335 target.effectMask = effectMask;
2336
2337 m_UniqueItemInfo.push_back(target);
2338}
2339
2341{
2342 m_destTargets[effIndex] = dest;
2343}
2344
2346{
2347 if (!target || target->processed)
2348 return;
2349
2350 target->processed = true; // Target checked in apply effects procedure
2351
2352 // Get mask of effects for target
2353 uint8 mask = target->effectMask;
2354
2355 Unit* unit = m_caster->GetGUID() == target->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, target->targetGUID);
2356 if (!unit)
2357 {
2358 uint8 farMask = 0;
2359 // create far target mask
2360 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2361 if (m_spellInfo->Effects[i].IsFarUnitTargetEffect())
2362 if ((1 << i) & mask)
2363 farMask |= (1 << i);
2364
2365 if (!farMask)
2366 return;
2367 // find unit in world
2368 unit = ObjectAccessor::FindUnit(target->targetGUID);
2369 if (!unit)
2370 return;
2371
2372 // do far effects on the unit
2373 // can't use default call because of threading, do stuff as fast as possible
2374 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2375 if (farMask & (1 << i))
2376 HandleEffects(unit, NULL, NULL, i, SPELL_EFFECT_HANDLE_HIT_TARGET);
2377 return;
2378 }
2379
2380 if (unit->IsAlive() != target->alive)
2381 return;
2382
2383 if (getState() == SPELL_STATE_DELAYED && !m_spellInfo->IsPositive() && (getMSTime() - target->timeDelay) <= unit->m_lastSanctuaryTime)
2384 return; // No missinfo in that case
2385
2386 // Get original caster (if exist) and calculate damage/healing from him data
2388
2389 // Skip if m_originalCaster not avaiable
2390 if (!caster)
2391 return;
2392
2393 SpellMissInfo missInfo = target->missCondition;
2394
2395 // Need init unitTarget by default unit (can changed in code on reflect)
2396 // Or on missInfo != SPELL_MISS_NONE unitTarget undefined (but need in trigger subsystem)
2397 unitTarget = unit;
2398
2399 // Reset damage/healing counter
2400 m_damage = target->damage;
2401 m_healing = -target->damage;
2402
2403 // Fill base trigger info
2404 uint32 procAttacker = m_procAttacker;
2405 uint32 procVictim = m_procVictim;
2406 uint32 procEx = m_procEx;
2407
2408 m_spellAura = NULL; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied
2409
2410 //Spells with this flag cannot trigger if effect is casted on self
2411 bool canEffectTrigger = !(m_spellInfo->AttributesEx3 & SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && CanExecuteTriggersOnHit(mask);
2412 Unit* spellHitTarget = NULL;
2413
2414 if (missInfo == SPELL_MISS_NONE) // In case spell hit target, do all effect on that target
2415 spellHitTarget = unit;
2416 else if (missInfo == SPELL_MISS_REFLECT) // In case spell reflect from target, do all effect on caster (if hit)
2417 {
2418 if (target->reflectResult == SPELL_MISS_NONE) // If reflected spell hit caster -> do all effect on him
2419 {
2420 spellHitTarget = m_caster;
2421 if (m_caster->GetTypeId() == TypeID::TYPEID_UNIT)
2422 m_caster->ToCreature()->LowerPlayerDamageReq(target->damage);
2423 }
2424 }
2425
2426 if (spellHitTarget)
2427 {
2428 SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura);
2429 if (missInfo2 != SPELL_MISS_NONE)
2430 {
2431 if (missInfo2 != SPELL_MISS_MISS)
2432 m_caster->SendSpellMiss(unit, m_spellInfo->Id, missInfo2);
2433 m_damage = 0;
2434 spellHitTarget = NULL;
2435 }
2436 }
2437
2438 // Do not take combo points on dodge and miss
2439 if (missInfo != SPELL_MISS_NONE && m_needComboPoints &&
2440 m_targets.GetUnitTargetGUID() == target->targetGUID)
2441 {
2442 m_needComboPoints = false;
2443 // Restore spell mods for a miss/dodge/parry Cold Blood
2445 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && (missInfo == SPELL_MISS_MISS ||
2446 missInfo == SPELL_MISS_DODGE || missInfo == SPELL_MISS_PARRY))
2447 m_caster->ToPlayer()->RestoreSpellMods(this, 14177);
2448 }
2449
2450 // Trigger info was not filled in spell::preparedatafortriggersystem - we do it now
2451 if (canEffectTrigger && !procAttacker && !procVictim)
2452 {
2453 bool positive = true;
2454 if (m_damage > 0)
2455 positive = false;
2456 else if (!m_healing)
2457 {
2458 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2459 // If at least one effect negative spell is negative hit
2460 if (mask & (1 << i) && !m_spellInfo->IsPositiveEffect(i))
2461 {
2462 positive = false;
2463 break;
2464 }
2465 }
2466 switch (m_spellInfo->DmgClass)
2467 {
2469 if (positive)
2470 {
2473 }
2474 else
2475 {
2478 }
2479 break;
2481 if (positive)
2482 {
2485 }
2486 else
2487 {
2490 }
2491 break;
2492 }
2493 }
2495
2496 // All calculated do it!
2497 // Do healing and triggers
2498 if (m_healing > 0)
2499 {
2500 bool crit = caster->isSpellCrit(unitTarget, m_spellInfo, m_spellSchoolMask);
2501 uint32 addhealth = m_healing;
2502 if (crit)
2503 {
2504 procEx |= PROC_EX_CRITICAL_HIT;
2505 addhealth = caster->SpellCriticalHealingBonus(m_spellInfo, addhealth, NULL);
2506 }
2507 else
2508 procEx |= PROC_EX_NORMAL_HIT;
2509
2510 int32 gain = caster->HealBySpell(unitTarget, m_spellInfo, addhealth, crit);
2511 unitTarget->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, m_spellInfo);
2512 m_healing = gain;
2513
2514 // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
2515 if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT)
2516 caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell);
2517 }
2518 // Do damage and triggers
2519 else if (m_damage > 0)
2520 {
2521 // Fill base damage struct (unitTarget - is real spell target)
2523
2524 // Add bonuses and fill damageInfo struct
2525 caster->CalculateSpellDamageTaken(&damageInfo, m_damage, m_spellInfo, m_attackType, target->crit);
2526 caster->DealDamageMods(damageInfo.target, damageInfo.damage, &damageInfo.absorb);
2527
2528 // Send log damage message to client
2529 caster->SendSpellNonMeleeDamageLog(&damageInfo);
2530
2531 procEx |= createProcExtendMask(&damageInfo, missInfo);
2532 procVictim |= PROC_FLAG_TAKEN_DAMAGE;
2533
2534 // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
2535 if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT)
2536 {
2537 caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo, m_triggeredByAuraSpell);
2538 if (caster->GetTypeId() == TypeID::TYPEID_PLAYER && (m_spellInfo->Attributes & SPELL_ATTR0_STOP_ATTACK_TARGET) == 0 &&
2540 caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx);
2541 }
2542
2543 m_damage = damageInfo.damage;
2544
2545 caster->DealSpellDamage(&damageInfo, true);
2546 }
2547 // Passive spell hits/misses or active spells only misses (only triggers)
2548 else
2549 {
2550 // Fill base damage struct (unitTarget - is real spell target)
2552 procEx |= createProcExtendMask(&damageInfo, missInfo);
2553 // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge)
2554 if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT)
2555 caster->ProcDamageAndSpell(unit, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell);
2556
2557 // Failed Pickpocket, reveal rogue
2558 if (missInfo == SPELL_MISS_RESIST && m_spellInfo->AttributesCu & SPELL_ATTR0_CU_PICKPOCKET && unitTarget->GetTypeId() == TypeID::TYPEID_UNIT)
2559 {
2560 m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_TALK);
2561 if (unitTarget->ToCreature()->IsAIEnabled)
2562 unitTarget->ToCreature()->AI()->AttackStart(m_caster);
2563 }
2564 }
2565
2566 if (missInfo != SPELL_MISS_EVADE && !m_caster->IsFriendlyTo(unit) && (!m_spellInfo->IsPositive() || m_spellInfo->HasEffect(SPELL_EFFECT_DISPEL)))
2567 {
2568 m_caster->CombatStart(unit, !(m_spellInfo->AttributesEx & SPELL_ATTR1_NO_THREAT || m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO));
2569
2570 if (m_spellInfo->AttributesCu & SPELL_ATTR0_CU_AURA_CC)
2571 if (!unit->IsStandState())
2573 }
2574
2575 if (spellHitTarget)
2576 {
2577 //AI functions
2578 if (spellHitTarget->GetTypeId() == TypeID::TYPEID_UNIT)
2579 if (spellHitTarget->ToCreature()->IsAIEnabled)
2580 spellHitTarget->ToCreature()->AI()->SpellHit(m_caster, m_spellInfo);
2581
2582 if (m_caster->GetTypeId() == TypeID::TYPEID_UNIT && m_caster->ToCreature()->IsAIEnabled)
2583 m_caster->ToCreature()->AI()->SpellHitTarget(spellHitTarget, m_spellInfo);
2584
2585 // Needs to be called after dealing damage/healing to not remove breaking on damage auras
2586 DoTriggersOnSpellHit(spellHitTarget, mask);
2587
2588 // if target is fallged for pvp also flag caster if a player
2589 if (unit->IsPvP() && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
2590 m_caster->ToPlayer()->UpdatePvP(true);
2591
2593 }
2594}
2595
2596SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura)
2597{
2598 if (!unit || !effectMask)
2599 return SPELL_MISS_EVADE;
2600
2601 // For delayed spells immunity may be applied between missile launch and hit - check immunity for that case
2602 if (m_spellInfo->Speed && (unit->IsImmunedToDamage(m_spellInfo) || unit->IsImmunedToSpell(m_spellInfo)))
2603 return SPELL_MISS_IMMUNE;
2604
2605 // disable effects to which unit is immune
2606 SpellMissInfo returnVal = SPELL_MISS_IMMUNE;
2607 for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber)
2608 if (effectMask & (1 << effectNumber))
2609 if (unit->IsImmunedToSpellEffect(m_spellInfo, effectNumber))
2610 effectMask &= ~(1 << effectNumber);
2611
2612 if (!effectMask)
2613 return returnVal;
2614
2617
2618 if (Player* player = unit->ToPlayer())
2619 {
2620 player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET, m_spellInfo->Id);
2621 player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET, m_spellInfo->Id, 0, 0, m_caster);
2622 player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2, m_spellInfo->Id);
2623 }
2624
2625 if (Player* player = m_caster->ToPlayer())
2626 {
2627 player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER, m_spellInfo->Id);
2628 player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2, m_spellInfo->Id, 0, 0, unit);
2629 }
2630
2631 if (m_caster != unit)
2632 {
2633 // Recheck UNIT_FLAG_NON_ATTACKABLE for delayed spells
2634 if (m_spellInfo->Speed > 0.0f && unit->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) && unit->GetCharmerOrOwnerGUID() != m_caster->GetGUID())
2635 return SPELL_MISS_EVADE;
2636
2637 if (m_caster->_IsValidAttackTarget(unit, m_spellInfo))
2638 {
2641 if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_AURA_CC) && unit->IsControlledByPlayer())
2643 }
2644 else if (m_caster->IsFriendlyTo(unit))
2645 {
2646 // for delayed spells ignore negative spells (after duel end) for friendly targets
2648 // 63881 - Malady of the Mind jump spell (Yogg-Saron)
2649 if (m_spellInfo->Speed > 0.0f && unit->GetTypeId() == TypeID::TYPEID_PLAYER && !m_spellInfo->IsPositive() && m_spellInfo->Id != 63881)
2650 return SPELL_MISS_EVADE;
2651
2652 // assisting case, healing and resurrection
2654 {
2655 m_caster->SetContestedPvP();
2656 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
2657 m_caster->ToPlayer()->UpdatePvP(true);
2658 }
2659 if (unit->IsInCombat() && !(m_spellInfo->AttributesEx & SPELL_ATTR1_NO_THREAT || m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO))
2660 {
2661 m_caster->SetInCombatState(unit->GetCombatTimer() > 0, unit);
2663 }
2664 }
2665 }
2666
2667 // Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add
2670 {
2673 // Increase Diminishing on unit, current informations for actually casts will use values above
2674 if ((type == DRTYPE_PLAYER &&
2676 type == DRTYPE_ALL)
2678 }
2679
2680 uint8 aura_effmask = 0;
2681 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2682 if (effectMask & (1 << i) && m_spellInfo->Effects[i].IsUnitOwnedAuraEffect())
2683 aura_effmask |= 1 << i;
2684
2685 if (aura_effmask)
2686 {
2687 // Select rank for aura with level requirements only in specific cases
2688 // Unit has to be target only of aura effect, both caster and target have to be players, target has to be other than unit target
2689 SpellInfo const* aurSpellInfo = m_spellInfo;
2690 int32 basePoints[MAX_SPELL_EFFECTS];
2691
2692 if (scaleAura)
2693 {
2694 aurSpellInfo = m_spellInfo->GetAuraRankForLevel(unitTarget->getLevel());
2695 ASSERT(aurSpellInfo);
2696 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2697 {
2698 basePoints[i] = aurSpellInfo->Effects[i].BasePoints;
2699 if (m_spellInfo->Effects[i].Effect != aurSpellInfo->Effects[i].Effect)
2700 {
2701 aurSpellInfo = m_spellInfo;
2702 break;
2703 }
2704 }
2705 }
2706
2707 if (m_originalCaster)
2708 {
2709 bool refresh = false;
2710 m_spellAura = Aura::TryRefreshStackOrCreate(aurSpellInfo, effectMask, unit,
2711 m_originalCaster, (aurSpellInfo == m_spellInfo) ? &m_spellValue->EffectBasePoints[0] : &basePoints[0], m_CastItem, 0, &refresh);
2712 if (m_spellAura)
2713 {
2714 // Set aura stack amount to desired value
2715 if (m_spellValue->AuraStackAmount > 1)
2716 {
2717 if (!refresh)
2718 m_spellAura->SetStackAmount(m_spellValue->AuraStackAmount);
2719 else
2720 m_spellAura->ModStackAmount(m_spellValue->AuraStackAmount);
2721 }
2722
2723 // Now Reduce spell duration using data received at spell hit
2724 int32 duration = m_spellAura->GetMaxDuration();
2725 int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup, aurSpellInfo);
2726 float diminishMod = unit->ApplyDiminishingToDuration(m_diminishGroup, duration, m_originalCaster, m_diminishLevel, limitduration);
2727
2728 // unit is immune to aura if it was diminished to 0 duration
2729 if (diminishMod == 0.0f)
2730 {
2731 m_spellAura->Remove();
2732 bool found = false;
2733 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2734 if (effectMask & (1 << i) && m_spellInfo->Effects[i].Effect != SPELL_EFFECT_APPLY_AURA)
2735 found = true;
2736 if (!found)
2737 return SPELL_MISS_IMMUNE;
2738 }
2739 else
2740 {
2741 ((UnitAura*)m_spellAura)->SetDiminishGroup(m_diminishGroup);
2742
2743 bool positive = m_spellAura->GetSpellInfo()->IsPositive();
2744 if (AuraApplication* aurApp = m_spellAura->GetApplicationOfTarget(m_originalCaster->GetGUID()))
2745 positive = aurApp->IsPositive();
2746
2747 duration = m_originalCaster->ModSpellDuration(aurSpellInfo, unit, duration, positive, effectMask);
2748
2749 if (duration > 0)
2750 {
2751 // Haste modifies duration of channeled spells
2752 if (m_spellInfo->IsChanneled())
2753 {
2755 m_originalCaster->ModSpellCastTime(aurSpellInfo, duration, this);
2756 }
2757 else if (m_spellInfo->AttributesEx5 & SPELL_ATTR5_HASTE_AFFECT_DURATION)
2758 {
2759 int32 origDuration = duration;
2760 duration = 0;
2761 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2762 if (AuraEffect const* eff = m_spellAura->GetEffect(i))
2763 if (int32 amplitude = eff->GetAmplitude()) // amplitude is hastened by UNIT_FIELD_MOD_CASTING_SPEED
2764 duration = std::max(std::max(origDuration / amplitude, 1) * amplitude, duration);
2765
2766 // if there is no periodic effect
2767 if (!duration)
2768 duration = int32(origDuration * m_originalCaster->GetFloatValue(UNIT_FIELD_MOD_CASTING_SPEED));
2769 }
2770 }
2771
2772 if (duration != m_spellAura->GetMaxDuration())
2773 {
2774 m_spellAura->SetMaxDuration(duration);
2775 m_spellAura->SetDuration(duration);
2776 }
2777 m_spellAura->_RegisterForTargets();
2778 }
2779 }
2780 }
2781 }
2782
2783 for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber)
2784 if (effectMask & (1 << effectNumber))
2785 HandleEffects(unit, NULL, NULL, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET);
2786
2787 return SPELL_MISS_NONE;
2788}
2789
2791{
2792 // handle SPELL_AURA_ADD_TARGET_TRIGGER auras
2793 // this is executed after spell proc spells on target hit
2794 // spells are triggered for each hit spell target
2795 // info confirmed with retail sniffs of permafrost and shadow weaving
2796 if (!m_hitTriggerSpells.empty())
2797 {
2798 int _duration = 0;
2799 for (HitTriggerSpellList::const_iterator i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i)
2800 {
2801 if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance))
2802 {
2803 m_caster->CastSpell(unit, i->triggeredSpell, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_TARGET_CHECK));
2804 SF_LOG_DEBUG("spells", "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->triggeredSpell->Id);
2805
2806 // SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration
2807 // set duration of current aura to the triggered spell
2808 if (i->triggeredSpell->GetDuration() == -1)
2809 {
2810 if (Aura* triggeredAur = unit->GetAura(i->triggeredSpell->Id, m_caster->GetGUID()))
2811 {
2812 // get duration from aura-only once
2813 if (!_duration)
2814 {
2815 Aura* aur = unit->GetAura(m_spellInfo->Id, m_caster->GetGUID());
2816 _duration = aur ? aur->GetDuration() : -1;
2817 }
2818 triggeredAur->SetDuration(_duration);
2819 }
2820 }
2821 }
2822 }
2823 }
2824
2825 // trigger linked auras remove/apply
2827 if (std::vector<int32> const* spellTriggered = sSpellMgr->GetSpellLinked(m_spellInfo->Id + SPELL_LINK_HIT))
2828 {
2829 for (std::vector<int32>::const_iterator i = spellTriggered->begin(); i != spellTriggered->end(); ++i)
2830 {
2831 if (*i < 0)
2832 unit->RemoveAurasDueToSpell(-(*i));
2833 else
2834 unit->CastSpell(unit, *i, true, 0, 0, m_caster->GetGUID());
2835 }
2836 }
2837}
2838
2840{
2841 if (target->processed) // Check target
2842 return;
2843 target->processed = true; // Target checked in apply effects procedure
2844
2845 uint32 effectMask = target->effectMask;
2846 if (!effectMask)
2847 return;
2848
2849 GameObject* go = m_caster->GetMap()->GetGameObject(target->targetGUID);
2850 if (!go)
2851 return;
2852
2855
2856 for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber)
2857 if (effectMask & (1 << effectNumber))
2858 HandleEffects(NULL, NULL, go, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET);
2859
2862}
2863
2865{
2866 uint32 effectMask = target->effectMask;
2867 if (!target->item || !effectMask)
2868 return;
2869
2872
2873 for (uint32 effectNumber = 0; effectNumber < MAX_SPELL_EFFECTS; ++effectNumber)
2874 if (effectMask & (1 << effectNumber))
2875 HandleEffects(NULL, target->item, NULL, effectNumber, SPELL_EFFECT_HANDLE_HIT_TARGET);
2876
2878
2880}
2881
2883{
2884 // Not need check return true
2886 return true;
2887
2888 uint8 channelTargetEffectMask = m_channelTargetEffectMask;
2889 uint8 channelAuraMask = 0;
2890 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2891 if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA)
2892 channelAuraMask |= 1 << i;
2893
2894 channelAuraMask &= channelTargetEffectMask;
2895
2896 float range = 0;
2897 if (channelAuraMask)
2898 {
2899 range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive());
2900 if (Player* modOwner = m_caster->GetSpellModOwner())
2901 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this);
2902 }
2903
2904 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
2905 {
2906 if (ihit->missCondition == SPELL_MISS_NONE && (channelTargetEffectMask & ihit->effectMask))
2907 {
2908 Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
2909
2910 if (!unit)
2911 continue;
2912
2913 if (IsValidDeadOrAliveTarget(unit))
2914 {
2915 if (channelAuraMask & ihit->effectMask)
2916 {
2918 {
2919 if (m_caster != unit && !m_caster->IsWithinDistInMap(unit, range))
2920 {
2921 ihit->effectMask &= ~aurApp->GetEffectMask();
2922 unit->RemoveAura(aurApp);
2923 continue;
2924 }
2925 }
2926 else // aura is dispelled
2927 continue;
2928 }
2929
2930 channelTargetEffectMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target
2931 }
2932 }
2933 }
2934
2935 // is all effects from m_needAliveTargetMask have alive targets
2936 return channelTargetEffectMask == 0;
2937}
2938
2939void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggeredByAura)
2940{
2941 if (m_CastItem)
2942 m_castItemGUID = m_CastItem->GetGUID();
2943 else
2944 m_castItemGUID = 0;
2945
2946 InitExplicitTargets(*targets);
2947
2948 // Fill aura scaling information
2949 if (m_caster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING))
2950 {
2951 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
2952 {
2953 if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_APPLY_AURA)
2954 {
2955 // Change aura with ranks only if basepoints are taken from spellInfo and aura is positive
2956 if (m_spellInfo->IsPositiveEffect(i))
2957 {
2958 m_auraScaleMask |= (1 << i);
2959 if (m_spellValue->EffectBasePoints[i] != m_spellInfo->Effects[i].BasePoints)
2960 {
2961 m_auraScaleMask = 0;
2962 break;
2963 }
2964 }
2965 }
2966 }
2967 }
2968
2970
2971 if (triggeredByAura)
2972 m_triggeredByAuraSpell = triggeredByAura->GetSpellInfo();
2973
2974 // create and add update event for this spell
2975 SpellEvent* Event = new SpellEvent(this);
2976 m_caster->m_Events.AddEvent(Event, m_caster->m_Events.CalculateTime(1));
2977
2978 //Prevent casting at cast another spell (ServerSide check)
2979 if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS) && m_caster->IsNonMeleeSpellCasted(false, true, true) && m_cast_count)
2980 {
2982 finish(false);
2983 return;
2984 }
2985
2987 {
2989 finish(false);
2990 return;
2991 }
2992 LoadScripts();
2993
2994 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
2995 m_caster->ToPlayer()->SetSpellModTakingSpell(this, true);
2996
2997 uint32 tmpPowerCost = 0;
2998 uint32 tmpPeriodicPowerCost = 0;
2999 for (uint32 i = 0; i < sSpellPowerStore.GetNumRows(); ++i)
3000 {
3001 const SpellPowerEntry* spellPower = sSpellPowerStore.LookupEntry(i);
3002 if (!spellPower)
3003 continue;
3004
3005 if (spellPower->spellId != m_spellInfo->Id)
3006 continue;
3007
3008 if (spellPower->ShapeShiftSpellID && !m_caster->ToPlayer()->HasAura(spellPower->ShapeShiftSpellID))
3009 continue;
3010
3011 m_powerType = spellPower->powerType;
3012 uint32 maxPowerForCost = 0;
3013 if (spellPower->ChannelCostPercentageFloat ||
3015 maxPowerForCost = m_caster->GetMaxPower(Powers(m_powerType));
3016
3018 {
3019 spellPower->manaCost,
3020 spellPower->manaPerSecond,
3021 spellPower->ManaCostPercentageFloat,
3022 spellPower->ChannelCostPercentageFloat,
3024 m_caster->GetCreateHealth(),
3025 maxPowerForCost
3026 };
3028 tmpPowerCost = costResult.PowerCost;
3029 tmpPeriodicPowerCost = costResult.PeriodicPowerCost;
3030
3031 switch (costResult.Status)
3032 {
3034 SF_LOG_DEBUG("spells", "CalculateManaCost: Not implemented yet!");
3035 break;
3037 SF_LOG_ERROR("spells", "CalculateManaCost: Unknown power type '%d' in spell %d", m_powerType, m_spellInfo->Id);
3038 break;
3039 default:
3040 break;
3041 }
3042
3043 // Apply cost mod by spell
3044 if (Player* modOwner = m_caster->GetSpellModOwner())
3045 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, tmpPowerCost);
3046
3047
3048 if (!m_caster->IsControlledByPlayer())
3049 {
3051 {
3052 GtNPCManaCostScalerEntry const* spellScaler = sGtNPCManaCostScalerStore.LookupEntry(m_spellInfo->SpellLevel - 1);
3053 GtNPCManaCostScalerEntry const* casterScaler = sGtNPCManaCostScalerStore.LookupEntry(m_caster->getLevel() - 1);
3054 if (spellScaler && casterScaler)
3055 tmpPowerCost *= casterScaler->ratio / spellScaler->ratio;
3056 }
3057 }
3058
3059 // Flat mod from caster auras by spell school and power type
3060 Unit::AuraEffectList const& auras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL);
3061 for (Unit::AuraEffectList::const_iterator i = auras.begin(); i != auras.end(); ++i)
3062 {
3063 if (!((*i)->GetMiscValue() & m_spellInfo->SchoolMask))
3064 continue;
3065
3066 if (!((*i)->GetMiscValueB() & (1 << m_powerType)))
3067 continue;
3068
3069 tmpPowerCost += (*i)->GetAmount();
3070 }
3071
3072 // PCT mod from user auras by spell school and power type
3073 Unit::AuraEffectList const& aurasPct = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT);
3074 for (Unit::AuraEffectList::const_iterator i = aurasPct.begin(); i != aurasPct.end(); ++i)
3075 {
3076 if (!((*i)->GetMiscValue() & m_spellInfo->SchoolMask))
3077 continue;
3078
3079 if (!((*i)->GetMiscValueB() & (1 << m_powerType)))
3080 continue;
3081
3082 tmpPowerCost += CalculatePct(tmpPowerCost, (*i)->GetAmount());
3083 }
3084
3085 // Spell drain all exist power on cast (Bunyanize)
3086 if (m_spellInfo->AttributesEx & SPELL_ATTR1_DRAIN_ALL_POWER)
3087 {
3088 // If power type - health drain all
3090 tmpPowerCost = m_caster->GetHealth();
3091 // Else drain all power
3092 if (spellPower->powerType < MAX_POWERS)
3093 {
3094 tmpPowerCost = m_caster->GetPower(Powers(m_powerType));
3095 }
3096 else
3097 {
3098 SF_LOG_ERROR("spells", "Spell::prepare: Unknown power type '%d' in spell %d", m_powerType, m_spellInfo->Id);
3099 tmpPowerCost = 0;
3100 }
3101 }
3102 }
3103
3104 // Fill cost data (not use power for item casts)
3105 m_powerCost = m_CastItem ? 0 : tmpPowerCost;
3106 m_periodicPowerCost = tmpPeriodicPowerCost;
3107
3108
3109 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3110 m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
3111
3112 // Set combo point requirement
3114 m_needComboPoints = false;
3115
3116 SpellCastResult result = CheckCast(true);
3117 // target is checked in too many locations and with different results to handle each of them
3118 // handle just the general SPELL_FAILED_BAD_TARGETS result which is the default result for most DBC target checks
3121 if (result != SpellCastResult::SPELL_CAST_OK && !IsAutoRepeat()) //always cast autorepeat dummy for triggering
3122 {
3123 // Periodic auras should be interrupted when aura triggers a spell which can't be cast
3124 // for example bladestorm aura should be removed on disarm as of patch 3.3.5
3125 // channeled periodic spells should be affected by this (arcane missiles, penance, etc)
3126 // a possible alternative sollution for those would be validating aura target on unit state change
3127 if (triggeredByAura && triggeredByAura->IsPeriodic() && !triggeredByAura->GetBase()->IsPassive())
3128 {
3130 triggeredByAura->GetBase()->SetDuration(0);
3131 }
3132
3133 SendCastResult(result);
3134
3135 finish(false);
3136 return;
3137 }
3138
3139 // Prepare data for triggers
3140 prepareDataForTriggerSystem(triggeredByAura);
3141
3142 if (Player* player = m_caster->ToPlayer())
3143 {
3144 if (!player->GetCommandStatus(CHEAT_CASTTIME))
3145 {
3146 player->SetSpellModTakingSpell(this, true);
3147 // calculate cast time (calculated after first CheckCast check to prevent charge counting for first CheckCast fail)
3148 m_casttime = m_spellInfo->CalcCastTime(player->getLevel(), this);
3149 player->SetSpellModTakingSpell(this, false);
3150 }
3151 else
3152 m_casttime = 0; // Set cast time to 0 if .cheat casttime is enabled.
3153 }
3154 else
3155 m_casttime = m_spellInfo->CalcCastTime(m_caster->getLevel(), this);
3156
3157 // don't allow channeled spells / spells with cast time to be casted while moving
3158 // (even if they are interrupted on moving, spells with almost immediate effect get to have their effect processed before movement interrupter kicks in)
3159 // don't cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect
3160 if (((m_spellInfo->IsChanneled() || m_casttime) && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && m_caster->isMoving() &&
3161 m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) && !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
3162 {
3164 finish(false);
3165 return;
3166 }
3167
3168 // set timer base at cast time
3169 ReSetTimer();
3170
3171 SF_LOG_DEBUG("spells", "Spell::prepare: spell id %u source %u caster %d customCastFlags %u mask %u", m_spellInfo->Id, m_caster->GetEntry(), m_originalCaster ? m_originalCaster->GetEntry() : -1, _triggeredCastFlags, m_targets.GetTargetMask());
3172
3173 //Containers for channeled spells have to be set
3175 // Why check duration? 29350: channelled triggers channelled
3176 if ((_triggeredCastFlags & TRIGGERED_CAST_DIRECTLY) && (!m_spellInfo->IsChanneled() || !m_spellInfo->GetMaxDuration()))
3177 cast(true);
3178 else
3179 {
3180 // stealth must be removed at cast starting (at show channel bar)
3181 // skip triggered spell (item equip spell casting and other not explicit character casts/item uses)
3183 {
3184 m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_CAST);
3185 for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
3186 if (m_spellInfo->Effects[i].GetUsedTargetObjectType() == TARGET_OBJECT_TYPE_UNIT)
3187 {
3188 m_caster->RemoveAurasWithInterruptFlags(AURA_INTERRUPT_FLAG_SPELL_ATTACK);
3189 break;
3190 }
3191 }
3192
3193 m_caster->SetCurrentCastedSpell(this);
3195
3196 // set target for proper facing
3198 if (m_caster->GetTypeId() == TypeID::TYPEID_UNIT && m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget())
3199 m_caster->ToCreature()->FocusTarget(this, m_targets.GetObjectTarget());
3200
3203
3204 //item: first cast may destroy item and second cast causes crash
3205 if (!m_casttime && !m_spellInfo->StartRecoveryTime && !m_castItemGUID && GetCurrentContainer() == CURRENT_GENERIC_SPELL)
3206 cast(true);
3207 }
3208}
3209
3211{
3213 return;
3214
3215 uint32 oldState = m_spellState;
3217
3218 m_autoRepeat = false;
3219 switch (oldState)
3220 {
3223 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3224 m_caster->ToPlayer()->RestoreSpellMods(this);
3225 // no break
3227 SendInterrupted(0);
3229 break;
3230
3232 for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
3233 if ((*ihit).missCondition == SPELL_MISS_NONE)
3234 if (Unit* unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID))
3235 unit->RemoveOwnedAura(m_spellInfo->Id, m_originalCasterGUID, 0, AURA_REMOVE_BY_CANCEL);
3236
3238 SendInterrupted(0);
3240
3241 // spell is canceled-take mods and clear list
3242 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3243 m_caster->ToPlayer()->RemoveSpellMods(this);
3244
3245 m_appliedMods.clear();
3246 break;
3247
3248 default:
3249 break;
3250 }
3251
3253 if (m_selfContainer && *m_selfContainer == this)
3254 *m_selfContainer = NULL;
3255
3256 m_caster->RemoveDynObject(m_spellInfo->Id);
3257 if (m_spellInfo->IsChanneled()) // if not channeled then the object for the current cast wasn't summoned yet
3258 m_caster->RemoveGameObject(m_spellInfo->Id, true);
3259
3260 //set state back so finish will be processed
3261 m_spellState = oldState;
3262
3263 finish(false);
3264}
3265
3266void Spell::cast(bool skipCheck)
3267{
3268 // update pointers base at GUIDs to prevent access to non-existed already object
3270
3271 // cancel at lost explicit target during cast
3272 if (m_targets.GetObjectTargetGUID() && !m_targets.GetObjectTarget())
3273 {
3274 cancel();
3275 return;
3276 }
3277
3278 if (Player* playerCaster = m_caster->ToPlayer())
3279 {
3280 // now that we've done the basic check, now run the scripts
3281 // should be done before the spell is actually executed
3282 sScriptMgr->OnPlayerSpellCast(playerCaster, this, skipCheck);
3283
3284 // As of 3.0.2 pets begin attacking their owner's target immediately
3285 // Let any pets know we've attacked something. Check DmgClass for harmful spells only
3286 // This prevents spells such as Hunter's Mark from triggering pet attack
3287 if (this->GetSpellInfo()->DmgClass != SPELL_DAMAGE_CLASS_NONE)
3288 if (Pet* playerPet = playerCaster->GetPet())
3289 if (playerPet->IsAlive() && playerPet->isControlled() && (m_targets.GetTargetMask() & TARGET_FLAG_UNIT))
3290 playerPet->AI()->OwnerAttacked(m_targets.GetObjectTarget()->ToUnit());
3291 }
3292
3294
3296 if (m_caster->GetTypeId() == TypeID::TYPEID_UNIT && m_targets.GetObjectTarget() && m_caster != m_targets.GetObjectTarget())
3297 m_caster->SetInFront(m_targets.GetObjectTarget());
3298
3299 // Should this be done for original caster?
3300 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3301 {
3302 // Set spell which will drop charges for triggered cast spells
3303 // if not successfully casted, will be remove in finish(false)
3304 m_caster->ToPlayer()->SetSpellModTakingSpell(this, true);
3305 }
3306
3308
3309 // skip check if done already (for instant cast spells for example)
3310 if (!skipCheck)
3311 {
3312 SpellCastResult castResult = CheckCast(false);
3313 if (castResult != SpellCastResult::SPELL_CAST_OK)
3314 {
3315 SendCastResult(castResult);
3316 SendInterrupted(0);
3317 //restore spell mods
3318 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3319 {
3320 m_caster->ToPlayer()->RestoreSpellMods(this);
3321 // cleanup after mod system
3322 // triggered spell pointer can be not removed in some cases
3323 m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
3324 }
3325 finish(false);
3326 SetExecutedCurrently(false);
3327 return;
3328 }
3329
3330 // additional check after cast bar completes (must not be in CheckCast)
3331 // if trade not complete then remember it in trade data
3332 if (m_targets.GetTargetMask() & TARGET_FLAG_TRADE_ITEM)
3333 {
3334 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3335 {
3336 if (TradeData* my_trade = m_caster->ToPlayer()->GetTradeData())
3337 {
3338 if (!my_trade->IsInAcceptProcess())
3339 {
3340 // Spell will be casted at completing the trade. Silently ignore at this place
3341 my_trade->SetSpell(m_spellInfo->Id, m_CastItem);
3343 SendInterrupted(0);
3344 m_caster->ToPlayer()->RestoreSpellMods(this);
3345 // cleanup after mod system
3346 // triggered spell pointer can be not removed in some cases
3347 m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
3348 finish(false);
3349 SetExecutedCurrently(false);
3350 return;
3351 }
3352 }
3353 }
3354 }
3355 }
3356
3358
3359 // Spell may be finished after target map check
3361 {
3362 SendInterrupted(0);
3363 //restore spell mods
3364 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3365 {
3366 m_caster->ToPlayer()->RestoreSpellMods(this);
3367 // cleanup after mod system
3368 // triggered spell pointer can be not removed in some cases
3369 m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
3370 }
3371 finish(false);
3372 SetExecutedCurrently(false);
3373 return;
3374 }
3375
3377
3379
3380 // traded items have trade slot instead of guid in m_itemTargetGUID
3381 // set to real guid to be sent later to the client
3382 m_targets.UpdateTradeSlotItem();
3383
3384 if (Player* player = m_caster->ToPlayer())
3385 {
3387 {
3388 player->StartTimedAchievement(ACHIEVEMENT_TIMED_TYPE_ITEM, m_CastItem->GetEntry());
3389 player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM, m_CastItem->GetEntry());
3390 }
3391
3392 player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL, m_spellInfo->Id);
3393 }
3394
3396 {
3397 // Powers have to be taken before SendSpellGo
3398 TakePower();
3399 TakeReagents(); // we must remove reagents before HandleEffects to allow place crafted item in same slot
3400 }
3401 else if (Item* targetItem = m_targets.GetItemTarget())
3402 {
3404 if (targetItem->GetOwnerGUID() != m_caster->GetGUID())
3405 TakeReagents();
3406 }
3407
3408 // CAST SPELL
3410
3412
3414
3415 // we must send smsg_spell_go packet before m_castItem delete in TakeCastItem()...
3416 SendSpellGo();
3417
3418 // Okay, everything is prepared. Now we need to distinguish between immediate and evented delayed spells
3419 if ((m_spellInfo->Speed > 0.0f && !m_spellInfo->IsChanneled()) || m_spellInfo->AttributesEx4 & SPELL_ATTR4_UNK4)
3420 {
3421 // Remove used for cast item if need (it can be already NULL after TakeReagents call
3422 // in case delayed spell remove item at cast delay start
3423 TakeCastItem();
3424
3425 // Okay, maps created, now prepare flags
3426 m_immediateHandled = false;
3428 SetDelayStart(0);
3429
3430 if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCasted(false, false, true))
3431 m_caster->ClearUnitState(UNIT_STATE_CASTING);
3432 }
3433 else
3434 {
3435 // Immediate spell, no big deal
3437 }
3438
3440
3441 if (const std::vector<int32>* spell_triggered = sSpellMgr->GetSpellLinked(m_spellInfo->Id))
3442 {
3443 for (std::vector<int32>::const_iterator i = spell_triggered->begin(); i != spell_triggered->end(); ++i)
3444 if (*i < 0)
3445 m_caster->RemoveAurasDueToSpell(-(*i));
3446 else
3447 m_caster->CastSpell(m_targets.GetUnitTarget() ? m_targets.GetUnitTarget() : m_caster, *i, true);
3448 }
3449
3450 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3451 {
3452 m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
3453
3454 //Clear spell cooldowns after every spell is cast if .cheat cooldown is enabled.
3455 if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN))
3456 m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
3457 }
3458
3459 SetExecutedCurrently(false);
3460}
3461
3463{
3464 // start channeling if applicable
3465 if (m_spellInfo->IsChanneled())
3466 {
3467 int32 duration = m_spellInfo->GetDuration();
3468 if (duration > 0)
3469 {
3470 // First mod_duration then haste - see Missile Barrage
3471 // Apply duration mod
3472 if (Player* modOwner = m_caster->GetSpellModOwner())
3473 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration);
3474 // Apply haste mods
3476 m_caster->ModSpellCastTime(m_spellInfo, duration, this);
3477
3479 m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags);
3480 SendChannelStart(duration);
3481 }
3482 else if (duration == -1)
3483 {
3485 m_caster->AddInterruptMask(m_spellInfo->ChannelInterruptFlags);
3486 SendChannelStart(duration);
3487 }
3488 }
3489
3491
3492 // process immediate effects (items, ground, etc.) also initialize some variables
3494
3495 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
3496 DoAllEffectOnTarget(&(*ihit));
3497
3498 for (std::list<GOTargetInfo>::iterator ihit = m_UniqueGOTargetInfo.begin(); ihit != m_UniqueGOTargetInfo.end(); ++ihit)
3499 DoAllEffectOnTarget(&(*ihit));
3500
3502
3503 // spell is finished, perform some last features of the spell here
3505
3506 // Remove used for cast item if need (it can be already NULL after TakeReagents call
3507 TakeCastItem();
3508
3509 // handle ammo consumption for thrown weapons
3510 //if (m_spellInfo->IsRangedWeaponSpell() && m_spellInfo->IsChanneled())
3511 // TakeAmmo();
3512
3514 finish(true); // successfully finish spell cast (not last in case autorepeat or channel spell)
3515}
3516
3518{
3520
3521 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3522 m_caster->ToPlayer()->SetSpellModTakingSpell(this, true);
3523
3524 uint64 next_time = 0;
3525
3527
3528 if (!m_immediateHandled)
3529 {
3531 m_immediateHandled = true;
3532 }
3533
3534 bool single_missile = (m_targets.HasDst());
3535
3536 // 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)
3537 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
3538 {
3539 if (ihit->processed == false)
3540 {
3541 if (single_missile || ihit->timeDelay <= t_offset)
3542 {
3543 ihit->timeDelay = t_offset;
3544 DoAllEffectOnTarget(&(*ihit));
3545 }
3546 else if (next_time == 0 || ihit->timeDelay < next_time)
3547 next_time = ihit->timeDelay;
3548 }
3549 }
3550
3551 // now recheck gameobject targeting correctness
3552 for (std::list<GOTargetInfo>::iterator ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit)
3553 {
3554 if (ighit->processed == false)
3555 {
3556 if (single_missile || ighit->timeDelay <= t_offset)
3557 DoAllEffectOnTarget(&(*ighit));
3558 else if (next_time == 0 || ighit->timeDelay < next_time)
3559 next_time = ighit->timeDelay;
3560 }
3561 }
3562
3564
3565 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3566 m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
3567
3568 // All targets passed - need finish phase
3569 if (next_time == 0)
3570 {
3571 // spell is finished, perform some last features of the spell here
3573
3574 finish(true); // successfully finish spell cast
3575
3576 // return zero, spell is finished now
3577 return 0;
3578 }
3579 else
3580 {
3581 // spell is unfinished, return next execution time
3582 return next_time;
3583 }
3584}
3585
3587{
3588 m_spellAura = NULL;
3589 // initialize Diminishing Returns Data
3592
3593 // handle some immediate features of the spell here
3595
3597
3598 // handle effects with SPELL_EFFECT_HANDLE_HIT mode
3599 for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
3600 {
3601 // don't do anything for empty effect
3602 if (!m_spellInfo->Effects[j].IsEffect())
3603 continue;
3604
3605 // call effect handlers to handle destination hit
3606 HandleEffects(NULL, NULL, NULL, j, SPELL_EFFECT_HANDLE_HIT);
3607 }
3608
3609 // process items
3610 for (std::list<ItemTargetInfo>::iterator ihit = m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit)
3611 DoAllEffectOnTarget(&(*ihit));
3612
3613 if (!m_originalCaster)
3614 return;
3615 // Handle procs on cast
3617 if (m_UniqueTargetInfo.empty() && m_targets.HasDst())
3618 {
3619 uint32 procAttacker = m_procAttacker;
3620 if (!procAttacker)
3622
3623 // Proc the spells that have DEST target
3625 }
3626}
3627
3629{
3630 if (m_caster->m_movedPlayer)
3631 {
3632 // Take for real after all targets are processed
3634 m_caster->m_movedPlayer->ClearComboPoints();
3635
3636 // Real add combo points from effects
3637 if (m_comboPointGain)
3638 m_caster->m_movedPlayer->GainSpellComboPoints(m_comboPointGain);
3639
3640 if (m_powerType == POWER_HOLY_POWER && m_caster->m_movedPlayer->getClass() == CLASS_PALADIN)
3641 HandleHolyPower(m_caster->m_movedPlayer);
3642 }
3643
3644 if (m_caster->m_extraAttacks && GetSpellInfo()->HasEffect(SPELL_EFFECT_ADD_EXTRA_ATTACKS))
3645 m_caster->HandleProcExtraAttackFor(m_caster->GetVictim());
3646
3648}
3649
3651{
3652 Player* _player = m_caster->ToPlayer();
3653 if (!_player)
3654 return;
3655
3656 // mana/health/etc potions, disabled by client (until combat out as declarate)
3657 if (m_CastItem && (m_CastItem->IsPotion() || m_spellInfo->IsCooldownStartedOnEvent()))
3658 {
3659 // need in some way provided data for Spell::finish SendCooldownEvent
3660 _player->SetLastPotionId(m_CastItem->GetEntry());
3661 return;
3662 }
3663
3664 // have infinity cooldown but set at aura apply // do not set cooldown for triggered spells (needed by reincarnation)
3665 if (m_spellInfo->IsCooldownStartedOnEvent() || m_spellInfo->IsPassive() || (_triggeredCastFlags & TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD))
3666 return;
3667
3668 _player->AddSpellAndCategoryCooldowns(m_spellInfo, m_CastItem ? m_CastItem->GetEntry() : 0, this);
3669}
3670
3671void Spell::update(uint32 difftime)
3672{
3673 // update pointers based at it's GUIDs
3675
3676 if (m_targets.GetUnitTargetGUID() && !m_targets.GetUnitTarget())
3677 {
3678 SF_LOG_DEBUG("spells", "Spell %u is cancelled due to removal of target.", m_spellInfo->Id);
3679 cancel();
3680 return;
3681 }
3682
3683 // check if the player caster has moved before the spell finished
3684 // with the exception of spells affected with SPELL_AURA_CAST_WHILE_WALKING effect
3685 if ((m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && m_timer != 0) &&
3686 m_caster->isMoving() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_MOVEMENT) &&
3687 (m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK || !m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR)) &&
3688 !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
3689 {
3690 // don't cancel for melee, autorepeat, triggered and instant spells
3692 cancel();
3693 }
3694
3695 switch (m_spellState)
3696 {
3698 {
3699 if (m_timer > 0)
3700 {
3701 if (difftime >= (uint32)m_timer)
3702 m_timer = 0;
3703 else
3704 m_timer -= difftime;
3705 }
3706
3707 if (m_timer == 0 && !IsNextMeleeSwingSpell() && !IsAutoRepeat())
3708 // don't CheckCast for instant spells - done in spell::prepare, skip duplicate checks, needed for range checks for example
3709 cast(!m_casttime);
3710 break;
3711 }
3713 {
3714 if (m_timer)
3715 {
3716 // check if there are alive targets left
3718 {
3719 SF_LOG_DEBUG("spells", "Channeled spell %d is removed due to lack of targets", m_spellInfo->Id);
3721 finish();
3722 }
3723
3724 if (m_timer > 0)
3725 {
3726 if (difftime >= (uint32)m_timer)
3727 m_timer = 0;
3728 else
3729 {
3730 m_periodicPowerTimer += difftime;
3731 if (m_periodicPowerTimer >= 1000)
3732 {
3733 // Check power amount
3734 Powers powerType = Powers(m_powerType);
3735 if (int32(m_caster->GetPower(powerType)) < (m_periodicPowerCost))
3736 {
3737 SF_LOG_ERROR("spells", "Channeled spell %d is removed due to lack of power", m_spellInfo->Id);
3739 finish();
3740 }
3743 }
3744
3745 m_timer -= difftime;
3746 }
3747 }
3748 }
3749
3750 if (m_timer == 0)
3751 {
3753 finish();
3754 }
3755 break;
3756 }
3757 default:
3758 break;
3759 }
3760}
3761
3762void Spell::finish(bool ok)
3763{
3764 if (!m_caster)
3765 return;
3766
3768 return;
3770
3771 if (m_spellInfo->IsChanneled())
3772 m_caster->UpdateInterruptMask();
3773
3774 if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !m_caster->IsNonMeleeSpellCasted(false, false, true))
3775 m_caster->ClearUnitState(UNIT_STATE_CASTING);
3776
3777 // Unsummon summon as possessed creatures on spell cancel
3778 if (m_spellInfo->IsChanneled() && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3779 {
3780 if (Unit* charm = m_caster->GetCharm())
3781 if (charm->GetTypeId() == TypeID::TYPEID_UNIT
3782 && charm->ToCreature()->HasUnitTypeMask(UNIT_MASK_PUPPET)
3783 && charm->GetUInt32Value(UNIT_FIELD_CREATED_BY_SPELL) == m_spellInfo->Id)
3784 ((Puppet*)charm)->UnSummon();
3785 }
3786
3787 if (Creature* creatureCaster = m_caster->ToCreature())
3788 creatureCaster->ReleaseFocus(this);
3789
3790 if (!ok)
3791 return;
3792
3793 if (m_caster->GetTypeId() == TypeID::TYPEID_UNIT && m_caster->ToCreature()->IsSummon())
3794 {
3795 // Unsummon statue
3796 uint32 spell = m_caster->GetUInt32Value(UNIT_FIELD_CREATED_BY_SPELL);
3797 SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell);
3798 if (spellInfo && spellInfo->SpellIconID == 2056)
3799 {
3800 SF_LOG_DEBUG("spells", "Statue %d is unsummoned in spell %d finish", m_caster->GetGUIDLow(), m_spellInfo->Id);
3801 m_caster->setDeathState(DeathState::JUST_DIED);
3802 return;
3803 }
3804 }
3805
3807 {
3808 bool found = false;
3809 Unit::AuraEffectList const& vIgnoreReset = m_caster->GetAuraEffectsByType(SPELL_AURA_IGNORE_MELEE_RESET);
3810 for (Unit::AuraEffectList::const_iterator i = vIgnoreReset.begin(); i != vIgnoreReset.end(); ++i)
3811 {
3812 if ((*i)->IsAffectingSpell(m_spellInfo))
3813 {
3814 found = true;
3815 break;
3816 }
3817 }
3818 if (!found && !(m_spellInfo->AttributesEx2 & SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS))
3819 {
3820 m_caster->resetAttackTimer(WeaponAttackType::BASE_ATTACK);
3821 if (m_caster->haveOffhandWeapon())
3822 m_caster->resetAttackTimer(WeaponAttackType::OFF_ATTACK);
3823 m_caster->resetAttackTimer(WeaponAttackType::RANGED_ATTACK);
3824 }
3825 }
3826
3827 // potions disabled by client, send event "not in combat" if need
3828 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
3829 {
3831 m_caster->ToPlayer()->UpdatePotionCooldown(this);
3832
3833 // triggered spell pointer can be not set in some cases
3834 // this is needed for proper apply of triggered spell mods
3835 m_caster->ToPlayer()->SetSpellModTakingSpell(this, true);
3836
3837 // Take mods after trigger spell (needed for 14177 to affect 48664)
3838 // mods are taken only on succesfull cast and independantly from targets of the spell
3839 m_caster->ToPlayer()->RemoveSpellMods(this);
3840 m_caster->ToPlayer()->SetSpellModTakingSpell(this, false);
3841 }
3842
3843 // Stop Attack for some spells
3845 m_caster->AttackStop();
3846}
3847
3849{
3850 if (result == SpellCastResult::SPELL_CAST_OK)
3851 return;
3852
3853 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
3854 return;
3855
3856 if (m_caster->ToPlayer()->GetSession()->PlayerLoading()) // don't send cast results at loading time
3857 return;
3858
3860}
3861
3863{
3864 if (result == SpellCastResult::SPELL_CAST_OK)
3865 return;
3866
3867 Unit* owner = m_caster->GetCharmerOrOwner();
3868 if (!owner || owner->GetTypeId() != TypeID::TYPEID_PLAYER)
3869 return;
3870
3872}
3873
3874void Spell::SendCastResult(Player* caster, SpellInfo const* spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError /*= SPELL_CUSTOM_ERROR_NONE*/, Opcodes opcode /*= SMSG_CAST_FAILED*/)
3875{
3876 if (result == SpellCastResult::SPELL_CAST_OK)
3877 return;
3878
3880 spellInfo ? spellInfo->Id : 0,
3881 static_cast<uint32>(result),
3882 static_cast<uint32>(customError),
3883 static_cast<uint32>(opcode));
3884
3885 WorldPacket data(opcode, (4 + 1 + 1));
3886 data << uint32(spellInfo->Id);
3887 data << uint32(result); // problem
3888 data << uint8(cast_count);
3889
3890 size_t pos = data.bitwpos();
3891 data.WriteBit(1);
3892 data.WriteBit(1);
3893 data.FlushBits();
3894
3895 size_t dataPos = data.wpos();
3896 switch (result)
3897 {
3899 data << uint32(0); // unknown (value 1 update cooldowns on client flag)
3900 break;
3902 data << uint32(spellInfo->RequiresSpellFocus); // SpellFocusObject.dbc id
3903 break;
3904 case SpellCastResult::SPELL_FAILED_REQUIRES_AREA: // AreaTable.dbc id
3905 // hardcode areas limitation case
3906 switch (spellInfo->Id)
3907 {
3908 case 41617: // Cenarion Mana Salve
3909 case 41619: // Cenarion Healing Salve
3910 data << uint32(3905);
3911 break;
3912 case 41618: // Bottled Nethergon Energy
3913 case 41620: // Bottled Nethergon Vapor
3914 data << uint32(3842);
3915 break;
3916 case 45373: // Bloodberry Elixir
3917 data << uint32(4075);
3918 break;
3919 default: // default case (don't must be)
3920 data << uint32(0);
3921 break;
3922 }
3923 break;
3925 if (spellInfo->Totem[0])
3926 data << uint32(spellInfo->Totem[0]);
3927 if (spellInfo->Totem[1])
3928 data << uint32(spellInfo->Totem[1]);
3929 break;
3931 if (spellInfo->TotemCategory[0])
3932 data << uint32(spellInfo->TotemCategory[0]);
3933 if (spellInfo->TotemCategory[1])
3934 data << uint32(spellInfo->TotemCategory[1]);
3935 break;
3939 data << uint32(spellInfo->EquippedItemClass);
3940 data << uint32(spellInfo->EquippedItemSubClassMask);
3941 break;
3943 {
3944 uint32 item = 0;
3945 for (int8 eff = 0; eff < MAX_SPELL_EFFECTS; eff++)
3946 if (spellInfo->Effects[eff].ItemType)
3947 item = spellInfo->Effects[eff].ItemType;
3948 ItemTemplate const* proto = sObjectMgr->GetItemTemplate(item);
3949 if (proto && proto->ItemLimitCategory)
3950 data << uint32(proto->ItemLimitCategory);
3951 break;
3952 }
3954 data << uint32(spellInfo->GetAllEffectsMechanicMask()); // SpellMechanic.dbc id
3955 break;
3957 data << uint32(spellInfo->EquippedItemSubClassMask); // seems correct...
3958 break;
3960 data << uint32(0); // Item id
3961 data << uint32(0); // Item count?
3962 break;
3964 data << uint32(0); // SkillLine.dbc id
3965 data << uint32(0); // required skill value
3966 break;
3968 data << uint32(0); // required fishing skill
3969 break;
3971 data << uint32(customError);
3972 break;
3974 data << uint32(0); // Unknown
3975 break;
3977 {
3978 uint32 missingItem = 0;
3979 for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++)
3980 {
3981 if (spellInfo->Reagent[i] <= 0)
3982 continue;
3983
3984 uint32 itemid = spellInfo->Reagent[i];
3985 uint32 itemcount = spellInfo->ReagentCount[i];
3986
3987 if (!caster->HasItemCount(itemid, itemcount))
3988 {
3989 missingItem = itemid;
3990 break;
3991 }
3992 }
3993
3994 data << uint32(missingItem); // first missing item
3995 break;
3996 }
3997 // TODO: SPELL_FAILED_NOT_STANDING
3998 default:
3999 break;
4000 }
4001
4002 if (int32 diff = data.wpos() - dataPos)
4003 {
4004 if ((diff / 4) == 1)
4005 data.PutBits(pos, 0, 1);
4006 else
4007 data.PutBits(pos, 0, 2); // 1 and 1
4008 }
4009 caster->GetSession()->SendPacket(&data);
4010}
4011
4013{
4014 if (!IsNeedSendToClient())
4015 return;
4016
4017 uint32 castFlags = CAST_FLAG_HAS_TRAJECTORY;
4018 if (((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell) && !m_cast_count)
4019 castFlags |= CAST_FLAG_PENDING;
4020
4021 if ((m_caster->GetTypeId() == TypeID::TYPEID_PLAYER ||
4022 (m_caster->GetTypeId() == TypeID::TYPEID_UNIT && m_caster->ToCreature()->IsPet()))
4024 castFlags |= CAST_FLAG_POWER_LEFT_SELF;
4025
4026 if (m_spellInfo->RuneCostID && m_powerType == POWER_RUNES)
4027 castFlags |= CAST_FLAG_UNKNOWN_19;
4028
4029 ObjectGuid casterGuid = m_CastItem ? m_CastItem->GetGUID() : m_caster->GetGUID();
4030 ObjectGuid casterUnitGuid = m_caster->GetGUID();
4031 ObjectGuid targetGuid = m_targets.GetObjectTargetGUID();
4032 ObjectGuid itemTargetGuid = m_targets.GetItemTargetGUID();
4033 ObjectGuid unkGuid = 0;
4034 bool hasDestLocation = (m_targets.GetTargetMask() & TARGET_FLAG_DEST_LOCATION) && m_targets.GetDst();
4035 bool hasSourceLocation = (m_targets.GetTargetMask() & TARGET_FLAG_SOURCE_LOCATION) && m_targets.GetSrc();
4036 bool hasTargetString = m_targets.GetTargetMask() & TARGET_FLAG_STRING;
4037 bool hasPredictedHeal = castFlags & CAST_FLAG_HEAL_PREDICTION;
4038 bool hasPredictedType = castFlags & CAST_FLAG_HEAL_PREDICTION;
4039 bool hasTargetMask = m_targets.GetTargetMask() != 0;
4040 bool hasCastImmunities = castFlags & CAST_FLAG_IMMUNITY;
4041 bool hasCastSchoolImmunities = castFlags & CAST_FLAG_IMMUNITY;
4042 bool hasElevation = castFlags & CAST_FLAG_ADJUST_MISSILE;
4043 bool hasVisualChain = castFlags & CAST_FLAG_VISUAL_CHAIN;
4044 bool hasAmmoInventoryType = castFlags & CAST_FLAG_PROJECTILE;
4045 bool hasAmmoDisplayId = castFlags & CAST_FLAG_PROJECTILE;
4046 uint8 runeCooldownPassedCount = (castFlags & CAST_FLAG_RUNE_LIST) && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER ? MAX_RUNES : 0;
4047 uint8 predictedPowerCount = castFlags & CAST_FLAG_POWER_LEFT_SELF ? 1 : 0;
4048
4049 WorldPacket data(SMSG_SPELL_START, 25);
4050
4051 data.WriteBits(0, 24); // Miss Count (not used currently in SMSG_SPELL_START)
4052 data.WriteBit(casterGuid[5]);
4053
4054 //for (uint32 i = 0; i < missCount; ++i)
4055 //{
4056 //}
4057
4058 data.WriteBit(1); // Unk read int8
4059 data.WriteBit(0); // Fake Bit
4060 data.WriteBit(casterUnitGuid[4]);
4061 data.WriteBit(casterGuid[2]);
4062 data.WriteBits(runeCooldownPassedCount, 3); // Rune Cooldown Passed Count
4063 data.WriteBit(casterUnitGuid[2]);
4064 data.WriteBit(casterUnitGuid[6]);
4065 data.WriteBits(0, 25); // MissType Count (not used currently in SMSG_SPELL_START)
4066 data.WriteBits(0, 13); // Unknown Bits
4067 data.WriteBit(casterGuid[4]);
4068 data.WriteBits(0, 24); // Hit Count (not used currently in SMSG_SPELL_START)
4069 data.WriteBit(casterUnitGuid[7]);
4070
4071 //for (uint32 i = 0; i < hitCount; ++i)
4072 //{
4073 //}
4074
4075 data.WriteBit(hasSourceLocation);
4076 data.WriteBits(predictedPowerCount, 21);
4077
4078 data.WriteBit(itemTargetGuid[3]);
4079 data.WriteBit(itemTargetGuid[0]);
4080 data.WriteBit(itemTargetGuid[1]);
4081 data.WriteBit(itemTargetGuid[7]);
4082 data.WriteBit(itemTargetGuid[2]);
4083 data.WriteBit(itemTargetGuid[6]);
4084 data.WriteBit(itemTargetGuid[4]);
4085 data.WriteBit(itemTargetGuid[5]);
4086
4087 data.WriteBit(!hasElevation);
4088 data.WriteBit(!hasTargetString);
4089 data.WriteBit(!hasAmmoInventoryType);
4090 data.WriteBit(hasDestLocation);
4091 data.WriteBit(1); // Unk Read32
4092 data.WriteBit(casterGuid[3]);
4093
4094 if (hasDestLocation)
4095 {
4096 ObjectGuid destTransportGuid = m_targets.GetDst()->_transportGUID;
4097 data.WriteBit(destTransportGuid[1]);
4098 data.WriteBit(destTransportGuid[6]);
4099 data.WriteBit(destTransportGuid[2]);
4100 data.WriteBit(destTransportGuid[7]);
4101 data.WriteBit(destTransportGuid[0]);
4102 data.WriteBit(destTransportGuid[3]);
4103 data.WriteBit(destTransportGuid[5]);
4104 data.WriteBit(destTransportGuid[4]);
4105 }
4106
4107 data.WriteBit(!hasAmmoDisplayId);
4108
4109 if (hasSourceLocation)
4110 {
4111 ObjectGuid srcTransportGuid = m_targets.GetSrc()->_transportGUID;
4112 data.WriteBit(srcTransportGuid[4]);
4113 data.WriteBit(srcTransportGuid[3]);
4114 data.WriteBit(srcTransportGuid[5]);
4115 data.WriteBit(srcTransportGuid[1]);
4116 data.WriteBit(srcTransportGuid[7]);
4117 data.WriteBit(srcTransportGuid[0]);
4118 data.WriteBit(srcTransportGuid[6]);
4119 data.WriteBit(srcTransportGuid[2]);
4120 }
4121
4122 data.WriteBit(0); // Fake Bit
4123 data.WriteBit(casterGuid[6]);
4124
4125 data.WriteBit(unkGuid[2]);
4126 data.WriteBit(unkGuid[1]);
4127 data.WriteBit(unkGuid[7]);
4128 data.WriteBit(unkGuid[6]);
4129 data.WriteBit(unkGuid[0]);
4130 data.WriteBit(unkGuid[5]);
4131 data.WriteBit(unkGuid[3]);
4132 data.WriteBit(unkGuid[4]);
4133
4134 data.WriteBit(!hasTargetMask);
4135
4136 if (hasTargetMask)
4137 data.WriteBits(m_targets.GetTargetMask(), 20);
4138
4139 data.WriteBit(casterGuid[1]);
4140 data.WriteBit(!hasPredictedHeal);
4141 data.WriteBit(1); // Unk read int8
4142 data.WriteBit(!hasCastSchoolImmunities);
4143 data.WriteBit(casterUnitGuid[5]);
4144 data.WriteBit(0); // Fake Bit
4145 data.WriteBits(0, 20); // Extra Target Count (not used currently in SMSG_SPELL_START)
4146
4147 //for (uint32 i = 0; i < extraTargetCount; ++i)
4148 //{
4149 //}
4150
4151 data.WriteBit(targetGuid[1]);
4152 data.WriteBit(targetGuid[4]);
4153 data.WriteBit(targetGuid[6]);
4154 data.WriteBit(targetGuid[7]);
4155 data.WriteBit(targetGuid[5]);
4156 data.WriteBit(targetGuid[3]);
4157 data.WriteBit(targetGuid[0]);
4158 data.WriteBit(targetGuid[2]);
4159
4160 data.WriteBit(casterGuid[0]);
4161 data.WriteBit(casterUnitGuid[3]);
4162 data.WriteBit(1); // Unk uint8
4163
4164 if (hasTargetString)
4165 data.WriteBits(uint32(m_targets.GetTargetString().length()), 7);
4166
4167 //for (uint32 i = 0; i < missTypeCount; ++i)
4168 //{
4169 //}
4170
4171 data.WriteBit(!hasCastImmunities);
4172 data.WriteBit(casterUnitGuid[1]);
4173 data.WriteBit(hasVisualChain);
4174 data.WriteBit(casterGuid[7]);
4175 data.WriteBit(!hasPredictedType);
4176 data.WriteBit(casterUnitGuid[0]);
4177
4178 data.FlushBits();
4179
4180 data.WriteByteSeq(itemTargetGuid[1]);
4181 data.WriteByteSeq(itemTargetGuid[7]);
4182 data.WriteByteSeq(itemTargetGuid[6]);
4183 data.WriteByteSeq(itemTargetGuid[0]);
4184 data.WriteByteSeq(itemTargetGuid[4]);
4185 data.WriteByteSeq(itemTargetGuid[2]);
4186 data.WriteByteSeq(itemTargetGuid[3]);
4187 data.WriteByteSeq(itemTargetGuid[5]);
4188
4189 //for (uint32 i = 0; i < hitCount; ++i)
4190 //{
4191 //}
4192
4193 data.WriteByteSeq(targetGuid[4]);
4194 data.WriteByteSeq(targetGuid[5]);
4195 data.WriteByteSeq(targetGuid[1]);
4196 data.WriteByteSeq(targetGuid[7]);
4197 data.WriteByteSeq(targetGuid[6]);
4198 data.WriteByteSeq(targetGuid[3]);
4199 data.WriteByteSeq(targetGuid[2]);
4200 data.WriteByteSeq(targetGuid[0]);
4201
4202 data << uint32(m_casttime);
4203
4204 data.WriteByteSeq(unkGuid[4]);
4205 data.WriteByteSeq(unkGuid[5]);
4206 data.WriteByteSeq(unkGuid[3]);
4207 data.WriteByteSeq(unkGuid[2]);
4208 data.WriteByteSeq(unkGuid[1]);
4209 data.WriteByteSeq(unkGuid[6]);
4210 data.WriteByteSeq(unkGuid[7]);
4211 data.WriteByteSeq(unkGuid[0]);
4212
4213 if (hasDestLocation)
4214 {
4215 float x, y, z;
4216 ObjectGuid destTransportGuid = m_targets.GetDst()->_transportGUID;
4217 if (destTransportGuid)
4218 m_targets.GetDst()->_transportOffset.GetPosition(x, y, z);
4219 else
4220 m_targets.GetDst()->_position.GetPosition(x, y, z);
4221
4222 data.WriteByteSeq(destTransportGuid[4]);
4223 data.WriteByteSeq(destTransportGuid[0]);
4224 data.WriteByteSeq(destTransportGuid[5]);
4225 data.WriteByteSeq(destTransportGuid[7]);
4226 data.WriteByteSeq(destTransportGuid[1]);
4227 data.WriteByteSeq(destTransportGuid[2]);
4228 data.WriteByteSeq(destTransportGuid[3]);
4229 data << y;
4230 data << z;
4231 data.WriteByteSeq(destTransportGuid[6]);
4232 data << x;
4233 }
4234
4235 //for (uint32 i = 0; i < extraTargetCount; ++i)
4236 //{
4237 //}
4238
4239 if (hasSourceLocation)
4240 {
4241 float x, y, z;
4242 ObjectGuid srcTransportGuid = m_targets.GetSrc()->_transportGUID;
4243 if (srcTransportGuid)
4244 m_targets.GetSrc()->_transportOffset.GetPosition(x, y, z);
4245 else
4246 m_targets.GetSrc()->_position.GetPosition(x, y, z);
4247
4248 data.WriteByteSeq(srcTransportGuid[0]);
4249 data.WriteByteSeq(srcTransportGuid[5]);
4250 data.WriteByteSeq(srcTransportGuid[4]);
4251 data.WriteByteSeq(srcTransportGuid[7]);
4252 data.WriteByteSeq(srcTransportGuid[3]);
4253 data.WriteByteSeq(srcTransportGuid[6]);
4254 data << x;
4255 data.WriteByteSeq(srcTransportGuid[2]);
4256 data << z;
4257 data.WriteByteSeq(srcTransportGuid[1]);
4258 data << y;
4259 }
4260
4261 data.WriteByteSeq(casterGuid[4]);
4262
4263 //for (uint32 i = 0; i < missCount; ++i)
4264 //{
4265 //}
4266
4267 if (hasCastSchoolImmunities)
4268 data << uint32(0);
4269
4270 data.WriteByteSeq(casterGuid[2]);
4271
4272 if (hasCastImmunities)
4273 data << uint32(0);
4274
4275 if (hasVisualChain)
4276 {
4277 data << uint32(0);
4278 data << uint32(0);
4279 }
4280
4281 if (predictedPowerCount > 0)
4282 {
4283 // SMSG_SPELL_START (5.4.8): Power value then PowerType (WPP V5_4_8).
4284 data << int32(m_caster->GetPower((Powers)m_powerType));
4285 data << uint8(m_powerType);
4286 }
4287
4288 data << uint32(castFlags);
4289
4290 data.WriteByteSeq(casterGuid[5]);
4291 data.WriteByteSeq(casterGuid[7]);
4292 data.WriteByteSeq(casterGuid[1]);
4293
4294 data << uint8(m_cast_count);
4295
4296 data.WriteByteSeq(casterUnitGuid[7]);
4297 data.WriteByteSeq(casterUnitGuid[0]);
4298 data.WriteByteSeq(casterGuid[6]);
4299 data.WriteByteSeq(casterGuid[0]);
4300 data.WriteByteSeq(casterUnitGuid[1]);
4301
4302 if (hasAmmoInventoryType)
4303 data << uint8(0);
4304
4305 if (hasPredictedHeal)
4306 data << uint32(0);
4307
4308 data.WriteByteSeq(casterUnitGuid[6]);
4309 data.WriteByteSeq(casterUnitGuid[3]);
4310
4311 data << uint32(m_spellInfo->Id);
4312
4313 if (hasAmmoDisplayId)
4314 data << uint32(0);
4315
4316 data.WriteByteSeq(casterUnitGuid[4]);
4317 data.WriteByteSeq(casterUnitGuid[5]);
4318 data.WriteByteSeq(casterUnitGuid[2]);
4319
4320 if (hasTargetString)
4321 data.WriteString(m_targets.GetTargetString());
4322
4323 if (hasPredictedType)
4324 data << uint8(0);
4325
4326 data.WriteByteSeq(casterGuid[3]);
4327
4328 if (hasElevation)
4329 data << float(m_targets.GetElevation());
4330
4331 for (uint8 i = 0; i < runeCooldownPassedCount; ++i)
4332 {
4333 // float casts ensure the division is performed on floats as we need float result
4334 float baseCd = float(m_caster->ToPlayer()->GetRuneBaseCooldown(i));
4335 data << uint8((baseCd - float(m_caster->ToPlayer()->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
4336 }
4337
4338 m_caster->SendMessageToSet(&data, true);
4339}
4340
4342{
4343 // not send invisible spell casting
4344 if (!IsNeedSendToClient())
4345 return;
4346
4347 //SF_LOG_DEBUG("spells", "Sending SMSG_SPELL_GO id=%u", m_spellInfo->Id);
4348
4349 uint32 castFlags = CAST_FLAG_UNKNOWN_9;
4350
4351 // triggered spells with spell visual != 0
4352 if (((IsTriggered() && !m_spellInfo->IsAutoRepeatRangedSpell()) || m_triggeredByAuraSpell) && !m_cast_count)
4353 castFlags |= CAST_FLAG_PENDING;
4354
4355 if ((m_caster->GetTypeId() == TypeID::TYPEID_PLAYER ||
4356 (m_caster->GetTypeId() == TypeID::TYPEID_UNIT && m_caster->ToCreature()->IsPet()))
4358 castFlags |= CAST_FLAG_POWER_LEFT_SELF; // should only be sent to self, but the current messaging doesn't make that possible
4359
4360 if ((m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
4361 && (m_caster->getClass() == CLASS_DEATH_KNIGHT)
4362 && m_spellInfo->RuneCostID
4364 {
4365 castFlags |= CAST_FLAG_UNKNOWN_19; // same as in SMSG_SPELL_START
4366 castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list
4367 }
4368
4370 {
4371 castFlags |= CAST_FLAG_RUNE_LIST; // rune cooldowns list
4372 castFlags |= CAST_FLAG_UNKNOWN_19; // same as in SMSG_SPELL_START
4373 }
4374
4375 if (m_targets.HasTraj())
4376 castFlags |= CAST_FLAG_ADJUST_MISSILE;
4377
4378 ObjectGuid casterGuid = m_CastItem ? m_CastItem->GetGUID() : m_caster->GetGUID();
4379 ObjectGuid casterUnitGuid = m_caster->GetGUID();
4380 ObjectGuid targetGuid = m_targets.GetObjectTargetGUID();
4381 ObjectGuid itemTargetGuid = m_targets.GetItemTargetGUID();
4382 ObjectGuid unkGuid = 0;
4383 bool hasDestLocation = (m_targets.GetTargetMask() & TARGET_FLAG_DEST_LOCATION) && m_targets.GetDst();
4384 bool hasSourceLocation = (m_targets.GetTargetMask() & TARGET_FLAG_SOURCE_LOCATION) && m_targets.GetSrc();
4385 bool hasDestUnkByte = m_targets.GetTargetMask() & TARGET_FLAG_DEST_LOCATION;
4386 bool hasTargetString = m_targets.GetTargetMask() & TARGET_FLAG_STRING;
4387 bool hasPredictedHeal = castFlags & CAST_FLAG_HEAL_PREDICTION;
4388 bool hasPredictedType = castFlags & CAST_FLAG_HEAL_PREDICTION;
4389 bool hasTargetMask = m_targets.GetTargetMask() != 0;
4390 bool hasCastImmunities = castFlags & CAST_FLAG_IMMUNITY;
4391 bool hasCastSchoolImmunities = castFlags & CAST_FLAG_IMMUNITY;
4392 bool hasElevation = castFlags & CAST_FLAG_ADJUST_MISSILE;
4393 bool hasDelayTime = castFlags & CAST_FLAG_ADJUST_MISSILE;
4394 bool hasVisualChain = castFlags & CAST_FLAG_VISUAL_CHAIN;
4395 bool hasAmmoInventoryType = castFlags & CAST_FLAG_PROJECTILE;
4396 bool hasAmmoDisplayId = castFlags & CAST_FLAG_PROJECTILE;
4397 bool hasRunesStateBefore = (castFlags & CAST_FLAG_RUNE_LIST) && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER;
4398 bool hasRunesStateAfter = (castFlags & CAST_FLAG_RUNE_LIST) && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER;
4399 uint8 predictedPowerCount = castFlags & CAST_FLAG_POWER_LEFT_SELF ? 1 : 0;
4400 uint8 runeCooldownPassedCount = (castFlags & CAST_FLAG_RUNE_LIST) && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER ? MAX_RUNES : 0;
4401
4402 // This function also fill data for channeled spells:
4403 // m_needAliveTargetMask req for stop channelig if one target die
4404 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
4405 {
4406 if ((*ihit).effectMask == 0) // No effect apply - all immuned add state
4407 // possibly SPELL_MISS_IMMUNE2 for this??
4408 ihit->missCondition = SPELL_MISS_IMMUNE2;
4409 }
4410
4411 WorldPacket data(SMSG_SPELL_GO, 25);
4412
4413 data.WriteBit(casterUnitGuid[2]);
4414 data.WriteBit(1); // hasAmmoDisplayType
4415 data.WriteBit(hasSourceLocation);
4416 data.WriteBit(casterGuid[2]);
4417
4418 if (hasSourceLocation)
4419 {
4420 ObjectGuid srcTransportGuid = m_targets.GetSrc()->_transportGUID;
4421 data.WriteBit(srcTransportGuid[3]);
4422 data.WriteBit(srcTransportGuid[7]);
4423 data.WriteBit(srcTransportGuid[4]);
4424 data.WriteBit(srcTransportGuid[2]);
4425 data.WriteBit(srcTransportGuid[0]);
4426 data.WriteBit(srcTransportGuid[6]);
4427 data.WriteBit(srcTransportGuid[1]);
4428 data.WriteBit(srcTransportGuid[5]);
4429 }
4430
4431 data.WriteBit(casterGuid[6]);
4432 data.WriteBit(!hasDestUnkByte);
4433 data.WriteBit(casterUnitGuid[7]);
4434 data.WriteBits(0, 20); // Extra Target Count
4435
4436 size_t missTypeCountPos = data.bitwpos();
4437 data.WriteBits(0, 25); // Miss Type Count
4438
4439 size_t missCountPos = data.bitwpos();
4440 data.WriteBits(0, 24); // Miss Count
4441
4442 data.WriteBit(casterUnitGuid[1]);
4443 data.WriteBit(casterGuid[0]);
4444 data.WriteBits(0, 13); // Unknown bits
4445
4446 uint32 missCount = 0;
4447 for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
4448 {
4449 if (ihit->missCondition != SPELL_MISS_NONE)
4450 {
4451 ObjectGuid missGuid = ihit->targetGUID;
4452 data.WriteBit(missGuid[1]);
4453 data.WriteBit(missGuid[3]);
4454 data.WriteBit(missGuid[6]);
4455 data.WriteBit(missGuid[4]);
4456 data.WriteBit(missGuid[5]);
4457 data.WriteBit(missGuid[2]);
4458 data.WriteBit(missGuid[0]);
4459 data.WriteBit(missGuid[7]);
4460 missCount++;
4461 }
4462 }
4463
4464 //for (uint32 i = 0; i < extraTargetCount; ++i)
4465 //{
4466 //}
4467
4468 data.WriteBit(casterUnitGuid[5]);
4469 data.WriteBit(0); // Fake bit
4470 data.WriteBit(0); // Fake bit
4471 data.WriteBit(!hasTargetString);
4472
4473 data.WriteBit(itemTargetGuid[7]);
4474 data.WriteBit(itemTargetGuid[2]);
4475 data.WriteBit(itemTargetGuid[1]);
4476 data.WriteBit(itemTargetGuid[3]);
4477 data.WriteBit(itemTargetGuid[6]);
4478 data.WriteBit(itemTargetGuid[0]);
4479 data.WriteBit(itemTargetGuid[5]);
4480 data.WriteBit(itemTargetGuid[4]);
4481
4482 data.WriteBit(casterGuid[7]);
4483
4484 data.WriteBit(targetGuid[0]);
4485 data.WriteBit(targetGuid[6]);
4486 data.WriteBit(targetGuid[5]);
4487 data.WriteBit(targetGuid[7]);
4488 data.WriteBit(targetGuid[4]);
4489 data.WriteBit(targetGuid[2]);
4490 data.WriteBit(targetGuid[3]);
4491 data.WriteBit(targetGuid[1]);
4492
4493 data.WriteBit(!hasRunesStateBefore);
4494 data.WriteBits(predictedPowerCount, 21); // predictedPowerCount
4495 data.WriteBit(casterGuid[1]);
4496 data.WriteBit(!hasPredictedType);
4497 data.WriteBit(!hasTargetMask);
4498 data.WriteBit(casterUnitGuid[3]);
4499
4500 if (hasTargetString)
4501 data.WriteBits(uint32(m_targets.GetTargetString().length()), 7);
4502
4503 data.WriteBit(1); // Missing Predict heal
4504 data.WriteBit(0); // hasPowerData
4505 data.WriteBit(1); // has castImmunitiy
4506 data.WriteBit(casterUnitGuid[6]);
4507 data.WriteBit(0); // Fake bit
4508 data.WriteBit(hasVisualChain);
4509
4510 data.WriteBit(unkGuid[7]);
4511 data.WriteBit(unkGuid[6]);
4512 data.WriteBit(unkGuid[1]);
4513 data.WriteBit(unkGuid[2]);
4514 data.WriteBit(unkGuid[0]);
4515 data.WriteBit(unkGuid[5]);
4516 data.WriteBit(unkGuid[3]);
4517 data.WriteBit(unkGuid[4]);
4518
4519 data.WriteBit(!hasDelayTime);
4520 data.WriteBit(1); // has School Immunities
4521 data.WriteBits(runeCooldownPassedCount, 3); // runeCooldownPassedCount
4522 data.WriteBit(casterUnitGuid[0]);
4523
4524 uint32 missTypeCount = 0;
4525 for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
4526 {
4527 if (ihit->missCondition != SPELL_MISS_NONE)
4528 {
4529 data.WriteBits(ihit->missCondition, 4);
4530 if (ihit->missCondition == SPELL_MISS_REFLECT)
4531 data.WriteBits(ihit->reflectResult, 4);
4532
4533 ++missTypeCount;
4534 }
4535 }
4536
4537 if (hasTargetMask)
4538 data.WriteBits(m_targets.GetTargetMask(), 20);
4539
4540 data.WriteBit(!hasElevation);
4541 data.WriteBit(!hasRunesStateAfter);
4542 data.WriteBit(casterGuid[4]);
4543 data.WriteBit(1); // hasAmmodisplayID
4544 data.WriteBit(hasDestLocation);
4545 data.WriteBit(casterGuid[5]);
4546
4547 size_t hitCountPos = data.bitwpos();
4548 data.WriteBits(0, 24); // Hit Count
4549
4550 if (hasDestLocation)
4551 {
4552 ObjectGuid destTransportGuid = m_targets.GetDst()->_transportGUID;
4553 data.WriteBit(destTransportGuid[0]);
4554 data.WriteBit(destTransportGuid[3]);
4555 data.WriteBit(destTransportGuid[2]);
4556 data.WriteBit(destTransportGuid[1]);
4557 data.WriteBit(destTransportGuid[4]);
4558 data.WriteBit(destTransportGuid[5]);
4559 data.WriteBit(destTransportGuid[6]);
4560 data.WriteBit(destTransportGuid[7]);
4561 }
4562
4563 data.WriteBit(casterUnitGuid[4]);
4564
4565 uint32 hitCount = 0;
4566 for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
4567 {
4568 if ((*ihit).missCondition == SPELL_MISS_NONE)
4569 {
4570 ObjectGuid hitGuid = ihit->targetGUID;
4571 data.WriteBit(hitGuid[2]);
4572 data.WriteBit(hitGuid[7]);
4573 data.WriteBit(hitGuid[1]);
4574 data.WriteBit(hitGuid[6]);
4575 data.WriteBit(hitGuid[4]);
4576 data.WriteBit(hitGuid[5]);
4577 data.WriteBit(hitGuid[0]);
4578 data.WriteBit(hitGuid[3]);
4579 m_channelTargetEffectMask |= ihit->effectMask;
4580 ++hitCount;
4581 }
4582 }
4583
4584 for (std::list<GOTargetInfo>::const_iterator ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit)
4585 {
4586 ObjectGuid hitGuid = ighit->targetGUID; // Always hits
4587 data.WriteBit(hitGuid[2]);
4588 data.WriteBit(hitGuid[7]);
4589 data.WriteBit(hitGuid[1]);
4590 data.WriteBit(hitGuid[6]);
4591 data.WriteBit(hitGuid[4]);
4592 data.WriteBit(hitGuid[5]);
4593 data.WriteBit(hitGuid[0]);
4594 data.WriteBit(hitGuid[3]);
4595 ++hitCount;
4596 }
4597
4598 data.WriteBit(casterGuid[3]);
4599 data.FlushBits();
4600
4601 data.PutBits(missCountPos, missCount, 24);
4602 data.PutBits(missTypeCountPos, missTypeCount, 25);
4603 data.PutBits(hitCountPos, hitCount, 24);
4604
4605 data.WriteByteSeq(targetGuid[5]);
4606 data.WriteByteSeq(targetGuid[2]);
4607 data.WriteByteSeq(targetGuid[1]);
4608 data.WriteByteSeq(targetGuid[6]);
4609 data.WriteByteSeq(targetGuid[0]);
4610 data.WriteByteSeq(targetGuid[3]);
4611 data.WriteByteSeq(targetGuid[4]);
4612 data.WriteByteSeq(targetGuid[7]);
4613
4614 data.WriteByteSeq(itemTargetGuid[5]);
4615 data.WriteByteSeq(itemTargetGuid[2]);
4616 data.WriteByteSeq(itemTargetGuid[0]);
4617 data.WriteByteSeq(itemTargetGuid[6]);
4618 data.WriteByteSeq(itemTargetGuid[7]);
4619 data.WriteByteSeq(itemTargetGuid[3]);
4620 data.WriteByteSeq(itemTargetGuid[1]);
4621 data.WriteByteSeq(itemTargetGuid[4]);
4622
4623 data.WriteByteSeq(casterGuid[2]);
4624
4625 //for (uint32 i = 0; i < extraTargetCount; ++i)
4626 //{
4627 //}
4628
4629 for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
4630 {
4631 if ((*ihit).missCondition == SPELL_MISS_NONE)
4632 {
4633 ObjectGuid hitGuid = ihit->targetGUID;
4634 data.WriteByteSeq(hitGuid[0]);
4635 data.WriteByteSeq(hitGuid[6]);
4636 data.WriteByteSeq(hitGuid[2]);
4637 data.WriteByteSeq(hitGuid[7]);
4638 data.WriteByteSeq(hitGuid[5]);
4639 data.WriteByteSeq(hitGuid[4]);
4640 data.WriteByteSeq(hitGuid[3]);
4641 data.WriteByteSeq(hitGuid[1]);
4642 }
4643 }
4644
4645 for (std::list<GOTargetInfo>::const_iterator ighit = m_UniqueGOTargetInfo.begin(); ighit != m_UniqueGOTargetInfo.end(); ++ighit)
4646 {
4647 ObjectGuid hitGuid = ighit->targetGUID; // Always hits
4648 data.WriteByteSeq(hitGuid[0]);
4649 data.WriteByteSeq(hitGuid[6]);
4650 data.WriteByteSeq(hitGuid[2]);
4651 data.WriteByteSeq(hitGuid[7]);
4652 data.WriteByteSeq(hitGuid[5]);
4653 data.WriteByteSeq(hitGuid[4]);
4654 data.WriteByteSeq(hitGuid[3]);
4655 data.WriteByteSeq(hitGuid[1]);
4656 }
4657
4658 data.WriteByteSeq(unkGuid[6]);
4659 data.WriteByteSeq(unkGuid[2]);
4660 data.WriteByteSeq(unkGuid[7]);
4661 data.WriteByteSeq(unkGuid[1]);
4662 data.WriteByteSeq(unkGuid[4]);
4663 data.WriteByteSeq(unkGuid[3]);
4664 data.WriteByteSeq(unkGuid[5]);
4665 data.WriteByteSeq(unkGuid[0]);
4666
4667 if (hasDelayTime)
4668 data << uint32(m_delayMoment);
4669
4670 data << uint32(getMSTime());
4671
4672 for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
4673 {
4674 if (ihit->missCondition != SPELL_MISS_NONE)
4675 {
4676 ObjectGuid missGuid = ihit->targetGUID;
4677 data.WriteByteSeq(missGuid[4]);
4678 data.WriteByteSeq(missGuid[2]);
4679 data.WriteByteSeq(missGuid[0]);
4680 data.WriteByteSeq(missGuid[6]);
4681 data.WriteByteSeq(missGuid[7]);
4682 data.WriteByteSeq(missGuid[5]);
4683 data.WriteByteSeq(missGuid[1]);
4684 data.WriteByteSeq(missGuid[3]);
4685 }
4686 }
4687
4688 if (hasDestLocation)
4689 {
4690 float x, y, z;
4691 ObjectGuid destTransportGuid = m_targets.GetDst()->_transportGUID;
4692 if (destTransportGuid)
4693 m_targets.GetDst()->_transportOffset.GetPosition(x, y, z);
4694 else
4695 m_targets.GetDst()->_position.GetPosition(x, y, z);
4696
4697 data << z;
4698 data << y;
4699 data.WriteByteSeq(destTransportGuid[4]);
4700 data.WriteByteSeq(destTransportGuid[5]);
4701 data.WriteByteSeq(destTransportGuid[7]);
4702 data.WriteByteSeq(destTransportGuid[6]);
4703 data.WriteByteSeq(destTransportGuid[1]);
4704 data.WriteByteSeq(destTransportGuid[2]);
4705 data << x;
4706 data.WriteByteSeq(destTransportGuid[0]);
4707 data.WriteByteSeq(destTransportGuid[3]);
4708 }
4709
4710 data.WriteByteSeq(casterGuid[6]);
4711 data.WriteByteSeq(casterUnitGuid[7]);
4712 data.WriteByteSeq(casterGuid[1]);
4713
4714 if (hasVisualChain)
4715 {
4716 data << uint32(0);
4717 data << uint32(0);
4718 }
4719
4720 data << uint32(castFlags);
4721
4722 if (hasSourceLocation)
4723 {
4724 float x, y, z;
4725 ObjectGuid srcTransportGuid = m_targets.GetSrc()->_transportGUID;
4726 if (srcTransportGuid)
4727 m_targets.GetSrc()->_transportOffset.GetPosition(x, y, z);
4728 else
4729 m_targets.GetSrc()->_position.GetPosition(x, y, z);
4730
4731 data.WriteByteSeq(srcTransportGuid[2]);
4732 data << y;
4733 data << x;
4734 data.WriteByteSeq(srcTransportGuid[6]);
4735 data.WriteByteSeq(srcTransportGuid[5]);
4736 data.WriteByteSeq(srcTransportGuid[1]);
4737 data.WriteByteSeq(srcTransportGuid[7]);
4738 data << z;
4739 data.WriteByteSeq(srcTransportGuid[3]);
4740 data.WriteByteSeq(srcTransportGuid[0]);
4741 data.WriteByteSeq(srcTransportGuid[4]);
4742 }
4743
4744 data.WriteByteSeq(casterUnitGuid[6]);
4745
4746 if (hasPredictedType)
4747 data << uint8(0);
4748
4749 data.WriteByteSeq(casterGuid[4]);
4750 data.WriteByteSeq(casterUnitGuid[1]);
4751
4752 if (predictedPowerCount > 0)
4753 {
4754 // SMSG_SPELL_GO (5.4.8): PowerType then Power value (opposite of SPELL_START).
4755 data << uint8(m_powerType);
4756 data << int32(m_caster->GetPower((Powers)m_powerType));
4757 }
4758
4759 if (hasRunesStateAfter)
4760 data << uint8(m_caster->ToPlayer()->GetRunesState());
4761
4762 for (uint8 i = 0; i < runeCooldownPassedCount; ++i)
4763 {
4764 // float casts ensure the division is performed on floats as we need float result
4765 float baseCd = float(m_caster->ToPlayer()->GetRuneBaseCooldown(i));
4766 data << uint8((baseCd - float(m_caster->ToPlayer()->GetRuneCooldown(i))) / baseCd * 255); // rune cooldown passed
4767 }
4768
4769 if (hasRunesStateBefore)
4770 data << uint8(m_runesState);
4771
4772 data.WriteByteSeq(casterGuid[0]);
4773
4774 if (hasDestUnkByte)
4775 data << uint8(0);
4776
4777 data << uint8(m_cast_count);
4778
4779 data.WriteByteSeq(casterGuid[5]);
4780 data.WriteByteSeq(casterUnitGuid[2]);
4781 data.WriteByteSeq(casterGuid[3]);
4782 data.WriteByteSeq(casterUnitGuid[5]);
4783
4784 if (hasTargetString)
4785 data.WriteString(m_targets.GetTargetString());
4786
4787 data << uint32(m_spellInfo->Id);
4788
4789 if (hasElevation)
4790 data << m_targets.GetElevation();
4791
4792 data.WriteByteSeq(casterUnitGuid[0]);
4793 data.WriteByteSeq(casterUnitGuid[3]);
4794 data.WriteByteSeq(casterUnitGuid[4]);
4795 data.WriteByteSeq(casterGuid[7]);
4796
4797 // Reset m_needAliveTargetMask for non channeled spell
4798 if (!m_spellInfo->IsChanneled())
4800
4801 m_caster->SendMessageToSet(&data, true);
4802}
4803
4805{
4806 if (m_effectExecuteData.empty())
4807 return;
4808
4809 ObjectGuid casterGuid = m_caster->GetGUID();
4810 bool hasSpellCastLogData = false;
4811 uint32 spellCastLogDataCount = 0;
4812
4814
4815 data.WriteGuidMask(casterGuid, 0, 6, 5, 7, 2);
4816 data.WriteBits(m_effectExecuteData.size(), 19);
4817 data.WriteGuidMask(casterGuid, 4);
4818
4819 for (LogHelperMap::const_iterator itr = m_effectExecuteData.begin(); itr != m_effectExecuteData.end(); ++itr)
4820 {
4821 SpellLogHelper const& helper = itr->second;
4822
4823 data.WriteBits(helper.ExtraAttacks.size(), 21);
4824 for (std::list<SpellLogExtraAttacksHelper>::const_iterator extraAttack = helper.ExtraAttacks.begin(); extraAttack != helper.ExtraAttacks.end(); ++extraAttack)
4825 data.WriteGuidMask(extraAttack->Guid, 5, 4, 2, 3, 1, 0, 6, 7);
4826
4827 data.WriteBits(helper.Energizes.size(), 20);
4828 for (std::list<SpellLogEnergizeHelper>::const_iterator energize = helper.Energizes.begin(); energize != helper.Energizes.end(); ++energize)
4829 data.WriteGuidMask(energize->Guid, 0, 3, 1, 5, 6, 4, 7, 2);
4830
4831 data.WriteBits(0, 21); // Unknown counter
4832 data.WriteBits(helper.PetFeed.size(), 22);
4833 data.WriteBits(helper.CreatedItems.size(), 22);
4834
4835 data.WriteBits(helper.Targets.size(), 24);
4836 for (std::list<ObjectGuid>::const_iterator target = helper.Targets.begin(); target != helper.Targets.end(); ++target)
4837 data.WriteGuidMask(*target, 6, 5, 1, 0, 3, 4, 7, 2);
4838 }
4839
4840 data.WriteGuidMask(casterGuid, 1, 3);
4841
4842 data.WriteBit(hasSpellCastLogData);
4843 if (hasSpellCastLogData)
4844 data.WriteBits(spellCastLogDataCount, 21);
4845 data.FlushBits();
4846
4847 if (hasSpellCastLogData)
4848 {
4849 for (uint32 i = 0; i < spellCastLogDataCount; ++i)
4850 {
4851 data << uint32(0);
4852 data << uint32(0);
4853 }
4854
4855 data << uint32(0);
4856 data << uint32(0);
4857 data << uint32(0);
4858 }
4859
4860 for (LogHelperMap::const_iterator itr = m_effectExecuteData.begin(); itr != m_effectExecuteData.end(); ++itr)
4861 {
4862 uint32 effIndex = itr->first;
4863 SpellLogHelper const& helper = itr->second;
4864
4865 for (std::list<ObjectGuid>::const_iterator target = helper.Targets.begin(); target != helper.Targets.end(); ++target)
4866 data.WriteGuidBytes(*target, 7, 5, 1, 2, 6, 4, 0, 3);
4867
4868 for (std::list<SpellLogEnergizeHelper>::const_iterator energize = helper.Energizes.begin(); energize != helper.Energizes.end(); ++energize)
4869 {
4870 data.WriteGuidBytes(energize->Guid, 3, 7, 5, 2, 0);
4871 data << uint32(energize->PowerType);
4872 data << uint32(energize->Value);
4873 data.WriteGuidBytes(energize->Guid, 4, 1);
4874 data << float(energize->Multiplier);
4875 data.WriteGuidBytes(energize->Guid, 6);
4876 }
4877
4878 for (std::list<SpellLogExtraAttacksHelper>::const_iterator extraAttack = helper.ExtraAttacks.begin(); extraAttack != helper.ExtraAttacks.end(); ++extraAttack)
4879 {
4880 data.WriteGuidBytes(extraAttack->Guid, 0, 6, 4, 7, 2, 5, 3);
4881 data << uint32(extraAttack->Count);
4882 data.WriteGuidBytes(extraAttack->Guid, 1);
4883 }
4884
4885 for (std::list<uint32>::const_iterator petFeedEntry = helper.PetFeed.begin(); petFeedEntry != helper.PetFeed.end(); ++petFeedEntry)
4886 data << uint32(*petFeedEntry);
4887
4888 data << uint32(m_spellInfo->Effects[effIndex].Effect);
4889
4890 for (std::list<uint32>::const_iterator itemEntry = helper.CreatedItems.begin(); itemEntry != helper.CreatedItems.end(); ++itemEntry)
4891 data << uint32(*itemEntry);
4892 }
4893
4894 data << uint32(m_spellInfo->Id);
4895 data.WriteGuidBytes(casterGuid, 5, 7, 1, 6, 2, 0, 4, 3);
4896
4897 m_caster->SendMessageToSet(&data, true);
4898
4899 m_effectExecuteData.clear();
4900}
4901
4902void Spell::ExecuteLogEffectTakeTargetPower(uint8 effIndex, Unit* target, uint32 powerType, uint32 powerTaken, float gainMultiplier)
4903{
4904 ASSERT(effIndex < MAX_SPELL_EFFECTS);
4905 m_effectExecuteData[effIndex].AddEnergize(target->GetGUID(), gainMultiplier, powerTaken, powerType);
4906}
4907
4908void Spell::ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit* victim, uint32 attCount)
4909{
4910 ASSERT(effIndex < MAX_SPELL_EFFECTS);
4911 m_effectExecuteData[effIndex].AddExtraAttacks(victim->GetGUID(), attCount);
4912}
4913
4914void Spell::ExecuteLogEffectInterruptCast(uint8 /*effIndex*/, Unit* victim, uint32 spellId)
4915{
4916 ObjectGuid casterGuid = m_caster->GetGUID();
4917 ObjectGuid targetGuid = victim->GetGUID();
4918
4919 WorldPacket data(SMSG_SPELLINTERRUPTLOG, 8 + 8 + 4 + 4);
4920 data.WriteGuidMask(targetGuid, 7, 2, 4, 6);
4921 data.WriteGuidMask(casterGuid, 0, 2, 5, 1, 4);
4922 data.WriteGuidMask(targetGuid, 0, 3);
4923 data.WriteGuidMask(casterGuid, 7, 6);
4924 data.WriteGuidMask(targetGuid, 1);
4925 data.WriteGuidMask(casterGuid, 3);
4926 data.WriteGuidMask(targetGuid, 5);
4927
4928 data.WriteGuidBytes(targetGuid, 0);
4929 data.WriteGuidBytes(casterGuid, 2);
4930 data << uint32(spellId);
4931 data.WriteGuidBytes(casterGuid, 1);
4932 data.WriteGuidBytes(targetGuid, 2);
4933 data.WriteGuidBytes(casterGuid, 3);
4934 data << uint32(m_spellInfo->Id);
4935 data.WriteGuidBytes(targetGuid, 4);
4936 data.WriteGuidBytes(casterGuid, 4);
4937 data.WriteGuidBytes(targetGuid, 3, 1);
4938 data.WriteGuidBytes(casterGuid, 5, 6, 7);
4939 data.WriteGuidBytes(targetGuid, 5, 6);
4940 data.WriteGuidBytes(casterGuid, 0);
4941 data.WriteGuidBytes(targetGuid, 7);
4942
4943 m_caster->SendMessageToSet(&data, true);
4944}
4945
4946void Spell::ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit* /*victim*/, int32 /*itemId*/, int32 /*slot*/)
4947{
4948 ASSERT(effIndex < MAX_SPELL_EFFECTS);
4949 // Not represented in the 5.4.8 execute-log payload used here.
4950}
4951
4953{
4954 ASSERT(effIndex < MAX_SPELL_EFFECTS);
4955 m_effectExecuteData[effIndex].AddTarget(obj->GetGUID());
4956}
4957
4959{
4960 ASSERT(effIndex < MAX_SPELL_EFFECTS);
4961 m_effectExecuteData[effIndex].AddCreatedItem(entry);
4962}
4963
4965{
4966 ASSERT(effIndex < MAX_SPELL_EFFECTS);
4967 m_effectExecuteData[effIndex].AddPetFeed(entry);
4968}
4969
4971{
4972 ASSERT(effIndex < MAX_SPELL_EFFECTS);
4973 m_effectExecuteData[effIndex].AddTarget(obj->GetGUID());
4974}
4975
4977{
4978 ASSERT(effIndex < MAX_SPELL_EFFECTS);
4979 m_effectExecuteData[effIndex].AddTarget(obj->GetGUID());
4980}
4981
4983{
4984 ASSERT(effIndex < MAX_SPELL_EFFECTS);
4985 m_effectExecuteData[effIndex].AddTarget(target->GetGUID());
4986}
4987
4989{
4990 ObjectGuid guid = m_caster->GetGUID();
4991
4992 WorldPacket data(SMSG_SPELL_FAILURE, (8 + 4 + 1));
4993
4994 data.WriteGuidMask(guid, 7, 3, 6, 2, 1, 5, 0, 4);
4995
4996 data.WriteGuidBytes(guid, 2, 6, 7, 0, 3, 1);
4997
4998 data << uint8(m_cast_count);
4999 data << uint32(m_spellInfo->Id);
5000 data << uint8(result); // problem
5001
5002 data.WriteGuidBytes(guid, 4, 5);
5003
5004 m_caster->SendMessageToSet(&data, true);
5005
5006 data.Initialize(SMSG_SPELL_FAILED_OTHER, 8 + 1 + 4 + 1);
5007 data.WriteGuidMask(guid, 7, 0, 5, 6, 1, 4, 3, 2);
5008
5009 data.WriteGuidBytes(guid, 0, 1);
5010
5011 data << uint8(result);
5012
5013 data.WriteGuidBytes(guid, 7, 5, 6);
5014
5015 data << uint32(m_spellInfo->Id);
5016 data << uint8(m_cast_count);
5017
5018 data.WriteGuidBytes(guid, 4, 2, 3);
5019
5020 m_caster->SendMessageToSet(&data, true);
5021}
5022
5024{
5025 if (time == 0)
5026 {
5027 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, 0);
5028 m_caster->SetUInt32Value(UNIT_FIELD_CHANNEL_SPELL, 0);
5029 }
5030
5031 ObjectGuid CasterGUID = m_caster->GetGUID();
5032
5034 data.WriteGuidMask(CasterGUID, 0, 3, 4, 1, 5, 2, 6, 7);
5035 data.WriteGuidBytes(CasterGUID, 4, 7, 1, 2, 6, 5);
5036 data << uint32(time);
5037 data.WriteGuidBytes(CasterGUID, 0, 3);
5038 m_caster->SendMessageToSet(&data, true);
5039}
5040
5042{
5043 uint64 channelTarget = m_targets.GetObjectTargetGUID();
5044 if (!channelTarget && !m_spellInfo->NeedsExplicitUnitTarget())
5045 if (m_UniqueTargetInfo.size() + m_UniqueGOTargetInfo.size() == 1) // this is for TARGET_SELECT_CATEGORY_NEARBY
5046 channelTarget = !m_UniqueTargetInfo.empty() ? m_UniqueTargetInfo.front().targetGUID : m_UniqueGOTargetInfo.front().targetGUID;
5047
5048 uint32 SchoolImmunityMask = m_caster->GetSchoolImmunityMask();
5049 uint32 MechanicImmunityMask = m_caster->GetMechanicImmunityMask();
5050 ObjectGuid CasterGUID = m_caster->GetGUID();
5051
5052 WorldPacket data(SMSG_SPELL_CHANNEL_START, (8 + 4 + 4/*+8+4+1+8*/));
5053
5054 data.WriteBit(CasterGUID[7]);
5055 data.WriteBit(CasterGUID[5]);
5056 data.WriteBit(CasterGUID[4]);
5057 data.WriteBit(CasterGUID[1]);
5058
5059 data.WriteBit(0); // healPrediction
5060
5061 data.WriteBit(CasterGUID[3]);
5062 data.WriteBit(CasterGUID[2]);
5063 data.WriteBit(CasterGUID[0]);
5064 data.WriteBit(CasterGUID[6]);
5065
5066 if (SchoolImmunityMask || MechanicImmunityMask)
5067 data.WriteBit(1);
5068 else
5069 data.WriteBit(0);
5070
5071 /*
5072 if (healPrediction)
5073 {
5074 data.appendPackGUID(channelTarget); // target packguid
5075 data << uint32(); // spellid
5076 data << uint8(0); // unk3
5077 if (unk3 == 2)
5078 data.append(); // unk packed guid (unused ?)
5079 }
5080 */
5081
5082 if (SchoolImmunityMask || MechanicImmunityMask)
5083 {
5084 data << uint32(SchoolImmunityMask); // SchoolImmunityMask
5085 data << uint32(MechanicImmunityMask); // MechanicImmunityMask
5086 }
5087
5088 data.WriteByteSeq(CasterGUID[6]);
5089 data.WriteByteSeq(CasterGUID[7]);
5090 data.WriteByteSeq(CasterGUID[3]);
5091 data.WriteByteSeq(CasterGUID[1]);
5092 data.WriteByteSeq(CasterGUID[0]);
5093 data << uint32(duration);
5094 data.WriteByteSeq(CasterGUID[5]);
5095 data.WriteByteSeq(CasterGUID[4]);
5096 data.WriteByteSeq(CasterGUID[2]);
5097 data << uint32(m_spellInfo->Id);
5098
5099 m_caster->SendMessageToSet(&data, true);
5100
5101 m_timer = duration;
5102 if (channelTarget)
5103 m_caster->SetUInt64Value(UNIT_FIELD_CHANNEL_OBJECT, channelTarget);
5104
5105 m_caster->SetUInt32Value(UNIT_FIELD_CHANNEL_SPELL, m_spellInfo->Id);
5106}
5107
5109{
5110 // get ressurector name for creature resurrections, otherwise packet will be not accepted
5111 // for player resurrections the name is looked up by guid
5112 std::string const sentName(m_caster->GetTypeId() == TypeID::TYPEID_PLAYER
5113 ? ""
5114 : m_caster->GetNameForLocaleIdx(target->GetSession()->GetSessionDbLocaleIndex()));
5115
5116 ObjectGuid guid = m_caster->GetGUID();
5117 WorldPacket data(SMSG_RESURRECT_REQUEST, (8 + 4 + sentName.size() + 1 + 1 + 1 + 4));
5118 data << uint32(sentName.size() + 1);
5119 data << uint32(m_spellInfo->Id);
5120 data << uint32(0);
5121
5122 data.WriteBit(guid[3]);
5123 data.WriteBit(m_caster->GetTypeId() == TypeID::TYPEID_PLAYER ? 0 : 1);
5124 data.WriteBit(false);
5125 data.WriteBit(guid[1]);
5126 data.WriteBit(guid[5]);
5127 data.WriteBit(guid[2]);
5128 data.WriteBit(guid[6]);
5129 data.WriteBit(guid[0]);
5130 data.WriteBit(guid[4]);
5131 data.WriteBit(guid[7]);
5132 data.WriteBits(sentName.size(), 6);
5133
5134 data.WriteByteSeq(guid[7]);
5135 data.WriteByteSeq(guid[3]);
5136 data.WriteByteSeq(guid[5]);
5137 data.WriteString(sentName);
5138 data.WriteByteSeq(guid[2]);
5139 data.WriteByteSeq(guid[4]);
5140 data.WriteByteSeq(guid[1]);
5141 data.WriteByteSeq(guid[6]);
5142 data.WriteByteSeq(guid[0]);
5143
5144 target->GetSession()->SendPacket(&data);
5145}
5146
5148{
5149 if (!m_CastItem)
5150 return;
5151
5152 Player* player = m_caster->ToPlayer();
5153 if (!player)
5154 return;
5155
5156 // not remove cast item at triggered spell (equipping, weapon damage, etc)
5158 return;
5159
5160 ItemTemplate const* proto = m_CastItem->GetTemplate();
5161
5162 if (!proto)
5163 {
5164 // This code is to avoid a crash
5165 // I'm not sure, if this is really an error, but I guess every item needs a prototype
5166 SF_LOG_ERROR("spells", "Cast item has no item prototype highId=%d, lowId=%d", m_CastItem->GetGUIDHigh(), m_CastItem->GetGUIDLow());
5167 return;
5168 }
5169
5170 bool expendable = false;
5171 bool withoutCharges = false;
5172
5173 for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
5174 {
5175 if (proto->Spells[i].SpellId)
5176 {
5177 // item has limited charges
5178 if (proto->Spells[i].SpellCharges)
5179 {
5180 if (proto->Spells[i].SpellCharges < 0)
5181 expendable = true;
5182
5183 int32 charges = m_CastItem->GetSpellCharges(i);
5184
5185 // item has charges left
5186 if (charges)
5187 {
5188 (charges > 0) ? --charges : ++charges; // abs(charges) less at 1 after use
5189 if (proto->Stackable == 1)
5190 m_CastItem->SetSpellCharges(i, charges);
5191 m_CastItem->SetState(ITEM_CHANGED, player);
5192 }
5193
5194 // all charges used
5195 withoutCharges = (charges == 0);
5196 }
5197 }
5198 }
5199
5200 if (expendable && withoutCharges)
5201 {
5202 uint32 count = 1;
5203 m_caster->ToPlayer()->DestroyItemCount(m_CastItem, count, true);
5204
5205 // prevent crash at access to deleted m_targets.GetItemTarget
5206 if (m_CastItem == m_targets.GetItemTarget())
5207 m_targets.SetItemTarget(NULL);
5208
5209 m_CastItem = NULL;
5210 }
5211}
5212
5214{
5216 return;
5217
5218 //Don't take power if the spell is cast while .cheat power is enabled.
5219 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
5220 {
5221 if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_POWER))
5222 return;
5223 }
5224
5225 Powers powerType = Powers(m_powerType);
5226 bool hit = true;
5227 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
5228 {
5229 if (powerType == POWER_RAGE || powerType == POWER_ENERGY || powerType == POWER_RUNES || powerType == POWER_CHI)
5230 if (uint64 targetGUID = m_targets.GetUnitTargetGUID())
5231 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
5232 if (ihit->targetGUID == targetGUID)
5233 {
5234 if (ihit->missCondition != SPELL_MISS_NONE)
5235 {
5236 hit = false;
5237 //lower spell cost on fail (by talent aura)
5238 if (Player* modOwner = m_caster->ToPlayer()->GetSpellModOwner())
5239 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_SPELL_COST_REFUND_ON_FAIL, m_powerCost);
5240 }
5241 break;
5242 }
5243 }
5244
5245 if (powerType == POWER_RUNES)
5246 {
5247 TakeRunePower(hit);
5248 return;
5249 }
5250
5251 if (!m_powerCost)
5252 return;
5253
5254 // health as power used
5255 if (powerType == POWER_HEALTH)
5256 {
5257 m_caster->ModifyHealth(-(int32)m_powerCost);
5258 return;
5259 }
5260
5261 if (powerType >= MAX_POWERS)
5262 {
5263 SF_LOG_ERROR("spells", "Spell::TakePower: Unknown power type '%d'", powerType);
5264 return;
5265 }
5266
5267 if (hit)
5268 m_caster->ModifyPower(powerType, -m_powerCost);
5269 else
5270 m_caster->ModifyPower(powerType, -(std::rand() % m_powerCost) / 4);
5271}
5272
5274{
5275 if (m_powerType != POWER_RUNES || !runeCostID)
5277
5278 Player* player = m_caster->ToPlayer();
5279 if (!player)
5281
5282 if (player->getClass() != CLASS_DEATH_KNIGHT)
5284
5285 SpellRuneCostEntry const* src = sSpellRuneCostStore.LookupEntry(runeCostID);
5286 if (!src)
5288
5289 if (src->NoRuneCost())
5291
5292 int32 runeCost[uint8(RuneType::NUM_RUNE_TYPES)]; // blood, frost, unholy, death
5293
5294 for (uint8 i = 0; i < uint8(RuneType::NUM_RUNE_TYPES); ++i)
5295 {
5296 runeCost[i] = src->RuneCost[i];
5297 if (Player* modOwner = m_caster->GetSpellModOwner())
5298 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i], this);
5299 }
5300
5301 runeCost[uint8(RuneType::RUNE_DEATH)] = MAX_RUNES; // calculated later
5302
5303 for (uint32 i = 0; i < MAX_RUNES; ++i)
5304 {
5305 uint8 rune = uint8(player->GetCurrentRune(i));
5306 if ((player->GetRuneCooldown(i) == 0) && (runeCost[rune] > 0))
5307 runeCost[rune]--;
5308 }
5309
5310 for (uint32 i = 0; i < uint8(RuneType::RUNE_DEATH); ++i)
5311 if (runeCost[i] > 0)
5312 runeCost[uint8(RuneType::RUNE_DEATH)] += runeCost[i];
5313
5314 if (runeCost[uint8(RuneType::RUNE_DEATH)] > MAX_RUNES)
5315 return SpellCastResult::SPELL_FAILED_NO_POWER; // not sure if result code is correct
5316
5318}
5319
5320void Spell::TakeRunePower(bool didHit)
5321{
5322 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER || m_caster->getClass() != CLASS_DEATH_KNIGHT)
5323 return;
5324
5325 SpellRuneCostEntry const* runeCostData = sSpellRuneCostStore.LookupEntry(m_spellInfo->RuneCostID);
5326 if (!runeCostData || (runeCostData->NoRuneCost() && runeCostData->NoRunicPowerGain()))
5327 return;
5328
5329 Player* player = m_caster->ToPlayer();
5330 m_runesState = player->GetRunesState(); // store previous state
5331
5332 int32 runeCost[uint8(RuneType::NUM_RUNE_TYPES)]; // blood, frost, unholy, death
5333
5334 for (uint32 i = 0; i < uint8(RuneType::NUM_RUNE_TYPES); ++i)
5335 {
5336 runeCost[i] = runeCostData->RuneCost[i];
5337 if (Player* modOwner = m_caster->GetSpellModOwner())
5338 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i], this);
5339 }
5340
5341 runeCost[uint8(RuneType::RUNE_DEATH)] = 0; // calculated later
5342
5343 for (uint32 i = 0; i < MAX_RUNES; ++i)
5344 {
5345 uint8 rune = uint8(player->GetCurrentRune(i));
5346 if (!player->GetRuneCooldown(i) && runeCost[rune] > 0)
5347 {
5348 player->SetRuneCooldown(i, didHit ? player->GetRuneBaseCooldown(i) : uint32(RUNE_MISS_COOLDOWN));
5349 player->SetLastUsedRune(RuneType(rune));
5350 runeCost[rune]--;
5351 }
5352 }
5353
5355
5356 if (runeCost[uint8(RuneType::RUNE_DEATH)] > 0)
5357 {
5358 for (uint32 i = 0; i < MAX_RUNES; ++i)
5359 {
5360 RuneType rune = player->GetCurrentRune(i);
5361 if (!player->GetRuneCooldown(i) && rune == RuneType::RUNE_DEATH)
5362 {
5363 player->SetRuneCooldown(i, didHit ? player->GetRuneBaseCooldown(i) : uint32(RUNE_MISS_COOLDOWN));
5364 player->SetLastUsedRune(rune);
5365 runeCost[uint8(rune)]--;
5366
5367 // keep Death Rune type if missed
5368 if (didHit)
5369 player->RestoreBaseRune(i);
5370
5371 if (runeCost[uint8(RuneType::RUNE_DEATH)] == 0)
5372 break;
5373 }
5374 }
5375 }
5376
5377 // you can gain some runic power when use runes
5378 if (didHit)
5379 if (int32 rp = int32(runeCostData->runePowerGain * sWorld->getRate(Rates::RATE_POWER_RUNICPOWER_INCOME)))
5380 player->ModifyPower(POWER_RUNIC_POWER, int32(rp));
5381}
5382
5384{
5385 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
5386 return;
5387
5388 ItemTemplate const* castItemTemplate = m_CastItem ? m_CastItem->GetTemplate() : NULL;
5389
5390 // do not take reagents for these item casts
5391 if (castItemTemplate && castItemTemplate->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST)
5392 return;
5393
5394 Player* p_caster = m_caster->ToPlayer();
5395 if (p_caster->CanNoReagentCast(m_spellInfo))
5396 return;
5397
5398 for (uint32 x = 0; x < MAX_SPELL_REAGENTS; ++x)
5399 {
5400 if (m_spellInfo->Reagent[x] <= 0)
5401 continue;
5402
5403 uint32 itemid = m_spellInfo->Reagent[x];
5404 uint32 itemcount = m_spellInfo->ReagentCount[x];
5405
5406 // if CastItem is also spell reagent
5407 if (castItemTemplate && castItemTemplate->ItemId == itemid)
5408 {
5409 for (int s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
5410 {
5411 // CastItem will be used up and does not count as reagent
5412 int32 charges = m_CastItem->GetSpellCharges(s);
5413 if (castItemTemplate->Spells[s].SpellCharges < 0 && abs(charges) < 2)
5414 {
5415 ++itemcount;
5416 break;
5417 }
5418 }
5419
5420 m_CastItem = NULL;
5421 }
5422
5423 // if GetItemTarget is also spell reagent
5424 if (m_targets.GetItemTargetEntry() == itemid)
5425 m_targets.SetItemTarget(NULL);
5426
5427 p_caster->DestroyItemCount(itemid, itemcount, true);
5428 }
5429}
5430
5432{
5433 if (m_UniqueTargetInfo.empty())
5434 return;
5435
5436 if ((m_spellInfo->AttributesEx & SPELL_ATTR1_NO_THREAT) ||
5437 (m_spellInfo->AttributesEx3 & SPELL_ATTR3_NO_INITIAL_AGGRO))
5438 return;
5439
5440 float threat = 0.0f;
5441 if (SpellThreatEntry const* threatEntry = sSpellMgr->GetSpellThreatEntry(m_spellInfo->Id))
5442 {
5443 if (threatEntry->apPctMod != 0.0f)
5444 threat += threatEntry->apPctMod * m_caster->GetTotalAttackPowerValue(WeaponAttackType::BASE_ATTACK);
5445
5446 threat += threatEntry->flatMod;
5447 }
5448 else if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_NO_INITIAL_THREAT) == 0)
5449 threat += m_spellInfo->SpellLevel;
5450
5451 // past this point only multiplicative effects occur
5452 if (threat == 0.0f)
5453 return;
5454
5455 // 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
5456 threat /= m_UniqueTargetInfo.size();
5457
5458 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
5459 {
5460 if (ihit->missCondition != SPELL_MISS_NONE)
5461 continue;
5462
5463 Unit* target = ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID);
5464 if (!target)
5465 continue;
5466
5467 // positive spells distribute threat among all units that are in combat with target, like healing
5468 if (m_spellInfo->_IsPositiveSpell())
5470 // for negative spells threat gets distributed among affected targets
5471 else
5472 {
5473 if (!target->CanHaveThreatList())
5474 continue;
5475
5476 target->AddThreat(m_caster, threat, m_spellInfo->GetSchoolMask(), m_spellInfo);
5477 }
5478 }
5479 SF_LOG_DEBUG("spells", "Spell %u, added an additional %f threat for %s %u target(s)", m_spellInfo->Id, threat, m_spellInfo->_IsPositiveSpell() ? "assisting" : "harming", uint32(m_UniqueTargetInfo.size()));
5480}
5481
5483{
5484 if (!caster)
5485 return;
5486
5487 bool hit = true;
5488 Player* modOwner = caster->GetSpellModOwner();
5489
5490 m_powerCost = caster->GetPower(POWER_HOLY_POWER); // Always use all the holy power we have
5491
5492 if (!m_powerCost || !modOwner)
5493 return;
5494
5495 if (uint64 targetGUID = m_targets.GetUnitTargetGUID())
5496 {
5497 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
5498 {
5499 if (ihit->targetGUID == targetGUID)
5500 {
5501 if (ihit->missCondition != SPELL_MISS_NONE && ihit->missCondition != SPELL_MISS_MISS)
5502 hit = false;
5503
5504 break;
5505 }
5506 }
5507
5508 // The spell did hit the target, apply aura cost mods if there are any.
5509 if (hit)
5510 {
5512 m_caster->ModifyPower(POWER_HOLY_POWER, -m_powerCost);
5513 }
5514 }
5515}
5516
5517void Spell::HandleEffects(Unit* pUnitTarget, Item* pItemTarget, GameObject* pGOTarget, uint32 i, SpellEffectHandleMode mode)
5518{
5519 effectHandleMode = mode;
5520 unitTarget = pUnitTarget;
5521 itemTarget = pItemTarget;
5522 gameObjTarget = pGOTarget;
5523 destTarget = &m_destTargets[i]._position;
5524
5525 uint8 eff = m_spellInfo->Effects[i].Effect;
5526
5527 SF_LOG_DEBUG("spells", "Spell: %u Effect : %u", m_spellInfo->Id, eff);
5528
5530
5531 bool preventDefault = CallScriptEffectHandlers((SpellEffIndex)i, mode);
5532
5533 if (!preventDefault && eff < TOTAL_SPELL_EFFECTS)
5534 {
5535 (this->*SpellEffects[eff])((SpellEffIndex)i);
5536 }
5537}
5538
5540{
5541 // check death state
5542 if (!m_caster->IsAlive() && !(m_spellInfo->Attributes & SPELL_ATTR0_PASSIVE) && !((m_spellInfo->Attributes & SPELL_ATTR0_CASTABLE_WHILE_DEAD) || (IsTriggered() && !m_triggeredByAuraSpell)))
5544
5545 // check cooldowns to prevent cheating
5546 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && !(m_spellInfo->Attributes & SPELL_ATTR0_PASSIVE))
5547 {
5548 //can cast triggered (by aura only?) spells while have this flag
5551
5552 if (m_caster->ToPlayer()->HasSpellCooldown(m_spellInfo->Id))
5553 {
5556 else
5558 }
5559 }
5560
5562 {
5565 }
5566
5567 // Check global cooldown
5570
5571 // only triggered spells can be processed an ended battleground
5572 if (!IsTriggered() && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
5573 if (Battleground* bg = m_caster->ToPlayer()->GetBattleground())
5574 if (bg->GetStatus() == STATUS_WAIT_LEAVE)
5576
5577 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && VMAP::VMapFactory::createOrGetVMapManager()->isLineOfSightCalcEnabled())
5578 {
5579 if (m_spellInfo->Attributes & SPELL_ATTR0_OUTDOORS_ONLY &&
5580 !m_caster->GetMap()->IsOutdoors(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ()))
5582
5583 if (m_spellInfo->Attributes & SPELL_ATTR0_INDOORS_ONLY &&
5584 m_caster->GetMap()->IsOutdoors(m_caster->GetPositionX(), m_caster->GetPositionY(), m_caster->GetPositionZ()))
5586 }
5587
5588 // only check at first call, Stealth auras are already removed at second call
5589 // for now, ignore triggered spells
5591 {
5592 bool checkForm = true;
5593 // Ignore form req aura
5594 Unit::AuraEffectList const& ignore = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_IGNORE_SHAPESHIFT);
5595 for (Unit::AuraEffectList::const_iterator i = ignore.begin(); i != ignore.end(); ++i)
5596 {
5597 if (!(*i)->IsAffectingSpell(m_spellInfo))
5598 continue;
5599 checkForm = false;
5600 break;
5601 }
5602 if (checkForm)
5603 {
5604 // Cannot be used in this stance/form
5605 SpellCastResult shapeError = m_spellInfo->CheckShapeshift(m_caster->GetShapeshiftForm());
5606 if (shapeError != SpellCastResult::SPELL_CAST_OK)
5607 return shapeError;
5608
5609 if ((m_spellInfo->Attributes & SPELL_ATTR0_ONLY_STEALTHED) && !(m_caster->HasStealthAura()))
5611 }
5612 }
5613
5614 Unit::AuraEffectList const& blockSpells = m_caster->GetAuraEffectsByType(SPELL_AURA_BLOCK_SPELL_FAMILY);
5615 for (Unit::AuraEffectList::const_iterator blockItr = blockSpells.begin(); blockItr != blockSpells.end(); ++blockItr)
5616 if (uint32((*blockItr)->GetMiscValue()) == m_spellInfo->SpellFamilyName)
5618
5619 bool reqCombat = true;
5620 Unit::AuraEffectList const& stateAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_ABILITY_IGNORE_AURASTATE);
5621 for (Unit::AuraEffectList::const_iterator j = stateAuras.begin(); j != stateAuras.end(); ++j)
5622 {
5623 if ((*j)->IsAffectingSpell(m_spellInfo))
5624 {
5625 m_needComboPoints = false;
5626 if ((*j)->GetMiscValue() == 1)
5627 {
5628 reqCombat = false;
5629 break;
5630 }
5631 }
5632 }
5633
5634 // caster state requirements
5635 // not for triggered spells (needed by execute)
5637 {
5638 if (m_spellInfo->CasterAuraState && !m_caster->HasAuraState(AuraStateType(m_spellInfo->CasterAuraState), m_spellInfo, m_caster))
5640 if (m_spellInfo->CasterAuraStateNot && m_caster->HasAuraState(AuraStateType(m_spellInfo->CasterAuraStateNot), m_spellInfo, m_caster))
5642
5643 // Note: spell 62473 requres casterAuraSpell = triggering spell
5644 if (m_spellInfo->CasterAuraSpell && !m_caster->HasAura(sSpellMgr->GetSpellIdForDifficulty(m_spellInfo->CasterAuraSpell, m_caster)))
5646 if (m_spellInfo->ExcludeCasterAuraSpell && m_caster->HasAura(sSpellMgr->GetSpellIdForDifficulty(m_spellInfo->ExcludeCasterAuraSpell, m_caster)))
5648
5649 if (reqCombat && m_caster->IsInCombat() && !m_spellInfo->CanBeUsedInCombat())
5651 }
5652
5653 // cancel autorepeat spells if cast start when moving
5654 // (not wand currently autorepeat cast delayed to moving stop anyway in spell update code)
5655 // Do not cancel spells which are affected by a SPELL_AURA_CAST_WHILE_WALKING effect
5656 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && m_caster->ToPlayer()->isMoving() && !m_caster->HasAuraTypeWithAffectMask(SPELL_AURA_CAST_WHILE_WALKING, m_spellInfo))
5657 {
5658 // skip stuck spell to allow use it in falling case and apply spell limitations at movement
5659 if ((!m_caster->HasUnitMovementFlag(MOVEMENTFLAG_FALLING_FAR) || m_spellInfo->Effects[0].Effect != SPELL_EFFECT_STUCK) &&
5660 (IsAutoRepeat() || (m_spellInfo->AuraInterruptFlags & AURA_INTERRUPT_FLAG_NOT_SEATED) != 0))
5662 }
5663
5664 // Check vehicle flags
5666 {
5667 SpellCastResult vehicleCheck = m_spellInfo->CheckVehicle(m_caster);
5668 if (vehicleCheck != SpellCastResult::SPELL_CAST_OK)
5669 return vehicleCheck;
5670 }
5671
5672 // check spell cast conditions from database
5673 {
5675 condInfo.mConditionTargets[1] = m_targets.GetObjectTarget();
5676 ConditionList conditions = sConditionMgr->GetConditionsForNotGroupedEntry(CONDITION_SOURCE_TYPE_SPELL, m_spellInfo->Id);
5677 if (!conditions.empty() && !sConditionMgr->IsObjectMeetToConditions(condInfo, conditions))
5678 {
5679 // mLastFailedCondition can be NULL if there was an error processing the condition in Condition::Meets (i.e. wrong data for ConditionTarget or others)
5681 {
5685 }
5686 if (!condInfo.mLastFailedCondition || !condInfo.mLastFailedCondition->ConditionTarget)
5689 }
5690 }
5691
5692 // Don't check explicit target for passive spells (workaround) (check should be skipped only for learn case)
5693 // those spells may have incorrect target entries or not filled at all (for example 15332)
5694 // such spells when learned are not targeting anyone using targeting system, they should apply directly to caster instead
5695 // also, such casts shouldn't be sent to client
5696 if (!((m_spellInfo->Attributes & SPELL_ATTR0_PASSIVE) && (!m_targets.GetUnitTarget() || m_targets.GetUnitTarget() == m_caster)))
5697 {
5698 // Check explicit target for m_originalCaster - todo: get rid of such workarounds
5699 SpellCastResult castResult = m_spellInfo->CheckExplicitTarget(m_originalCaster ? m_originalCaster : m_caster, m_targets.GetObjectTarget(), m_targets.GetItemTarget());
5700 if (castResult != SpellCastResult::SPELL_CAST_OK)
5701 return castResult;
5702 }
5703
5704 if (Unit* target = m_targets.GetUnitTarget())
5705 {
5706 SpellCastResult castResult = m_spellInfo->CheckTarget(m_caster, target, false);
5707 if (castResult != SpellCastResult::SPELL_CAST_OK)
5708 return castResult;
5709
5710 if (target != m_caster)
5711 {
5712 // Must be behind the target
5713 if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET) && target->HasInArc(static_cast<float>(M_PI), m_caster))
5715
5716 // Target must be facing you
5717 if ((m_spellInfo->AttributesCu & SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER) && !target->HasInArc(static_cast<float>(M_PI), m_caster))
5719
5720 if (m_caster->GetEntry() != WORLD_TRIGGER) // Ignore LOS for gameobjects casts (wrongly casted by a trigger)
5721 if (!(m_spellInfo->AttributesEx2 & SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS) && !DisableMgr::IsDisabledFor(DISABLE_TYPE_SPELL, m_spellInfo->Id, NULL, SPELL_DISABLE_LOS) && !m_caster->IsWithinLOSInMap(target))
5723 }
5724 }
5725
5726 // Check for line of sight for spells with dest
5727 if (m_targets.HasDst())
5728 {
5729 float x, y, z;
5730 m_targets.GetDstPos()->GetPosition(x, y, z);
5731
5734 }
5735
5736 // check pet presence
5737 for (int j = 0; j < MAX_SPELL_EFFECTS; ++j)
5738 {
5739 if (m_spellInfo->Effects[j].TargetA.GetTarget() == TARGET_UNIT_PET)
5740 {
5741 if (!m_caster->GetGuardianPet())
5742 {
5743 if (m_triggeredByAuraSpell) // not report pet not existence for triggered spells
5745 else
5747 }
5748 break;
5749 }
5750 }
5751
5752 // Spell casted only on battleground
5753 if ((m_spellInfo->AttributesEx3 & SPELL_ATTR3_BATTLEGROUND) && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
5754 if (!m_caster->ToPlayer()->InBattleground())
5756
5757 // do not allow spells to be cast in arenas or rated battlegrounds
5758 if (Player* player = m_caster->ToPlayer())
5759 if (player->InArena()/* || player->InRatedBattleGround() NYI*/)
5760 {
5762 if (castResult != SpellCastResult::SPELL_CAST_OK)
5763 return castResult;
5764 }
5765
5766 // zone check
5767 if (m_caster->GetTypeId() == TypeID::TYPEID_UNIT || !m_caster->ToPlayer()->IsGameMaster())
5768 {
5769 uint32 zone, area;
5770 m_caster->GetZoneAndAreaId(zone, area);
5771
5772 SpellCastResult locRes = m_spellInfo->CheckLocation(m_caster->GetMapId(), zone, area,
5773 m_caster->GetTypeId() == TypeID::TYPEID_PLAYER ? m_caster->ToPlayer() : NULL);
5774 if (locRes != SpellCastResult::SPELL_CAST_OK)
5775 return locRes;
5776 }
5777
5778 // not let players cast spells at mount (and let do it to creatures)
5780 !m_spellInfo->IsPassive() && !(m_spellInfo->Attributes & SPELL_ATTR0_CASTABLE_WHILE_MOUNTED))
5781 {
5782 if (m_caster->IsInFlight())
5784 else
5786 }
5787
5788 // check spell focus object
5789 if (m_spellInfo->RequiresSpellFocus)
5790 {
5792 if (!focusObject)
5794 }
5795
5797
5798 // always (except passive spells) check items (only player related checks)
5799 if (!m_spellInfo->IsPassive())
5800 {
5801 castResult = CheckItems();
5802 if (castResult != SpellCastResult::SPELL_CAST_OK)
5803 return castResult;
5804 }
5805
5806 // Triggered spells also have range check
5808 castResult = CheckRange(strict);
5809 if (castResult != SpellCastResult::SPELL_CAST_OK)
5810 return castResult;
5811
5813 {
5814 castResult = CheckPower();
5815 if (castResult != SpellCastResult::SPELL_CAST_OK)
5816 return castResult;
5817 }
5818
5820 {
5821 castResult = CheckCasterAuras();
5822 if (castResult != SpellCastResult::SPELL_CAST_OK)
5823 return castResult;
5824 }
5825
5826 // script hook
5827 castResult = CallScriptCheckCastHandlers();
5828 if (castResult != SpellCastResult::SPELL_CAST_OK)
5829 return castResult;
5830
5831 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
5832 {
5833 // for effects of spells that have only one target
5834 switch (m_spellInfo->Effects[i].Effect)
5835 {
5836 case SPELL_EFFECT_DUMMY:
5837 {
5838 if (m_spellInfo->Id == 19938) // Awaken Peon
5839 {
5840 Unit* unit = m_targets.GetUnitTarget();
5841 if (!unit || !unit->HasAura(17743))
5843 }
5844 else if (m_spellInfo->Id == 31789) // Righteous Defense
5845 {
5846 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
5848
5849 Unit* target = m_targets.GetUnitTarget();
5850 if (!target || !target->IsFriendlyTo(m_caster) || target->getAttackers().empty())
5852 }
5853 break;
5854 }
5856 {
5857 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
5859
5860 if (m_spellInfo->Effects[i].TargetA.GetTarget() != TARGET_UNIT_PET)
5861 break;
5862
5863 Pet* pet = m_caster->ToPlayer()->GetPet();
5864
5865 if (!pet)
5867
5868 SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[i].TriggerSpell);
5869
5870 if (!learn_spellproto)
5872
5873 if (m_spellInfo->SpellLevel > pet->getLevel())
5875
5876 break;
5877 }
5879 {
5880 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
5882 if (Guild* guild = m_caster->ToPlayer()->GetGuild())
5883 if (guild->GetLeaderGUID() != m_caster->ToPlayer()->GetGUID())
5885 break;
5886 }
5888 {
5889 // check target only for unit target case
5890 if (Unit* unitTarget = m_targets.GetUnitTarget())
5891 {
5892 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
5894
5895 Pet* pet = unitTarget->ToPet();
5896 if (!pet || pet->GetOwner() != m_caster)
5898
5899 SpellInfo const* learn_spellproto = sSpellMgr->GetSpellInfo(m_spellInfo->Effects[i].TriggerSpell);
5900
5901 if (!learn_spellproto)
5903
5904 if (m_spellInfo->SpellLevel > pet->getLevel())
5906 }
5907 break;
5908 }
5910 {
5911 uint32 glyphId = m_spellInfo->Effects[i].MiscValue;
5912 if (GlyphPropertiesEntry const* gp = sGlyphPropertiesStore.LookupEntry(glyphId))
5913 if (m_caster->HasAura(gp->SpellId))
5915 break;
5916 }
5918 {
5919 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
5921
5922 Item* foodItem = m_targets.GetItemTarget();
5923 if (!foodItem)
5925
5926 Pet* pet = m_caster->ToPlayer()->GetPet();
5927
5928 if (!pet)
5930
5931 if (!pet->HaveInDiet(foodItem->GetTemplate()))
5933
5934 if (!pet->GetCurrentFoodBenefitLevel(foodItem->GetTemplate()->ItemLevel))
5936
5937 if (m_caster->IsInCombat() || pet->IsInCombat())
5939
5940 break;
5941 }
5944 {
5945 // Can be area effect, Check only for players and not check if target - caster (spell can have multiply drain/burn effects)
5946 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
5947 if (Unit* target = m_targets.GetUnitTarget())
5948 if (target != m_caster && target->getPowerType() != Powers(m_spellInfo->Effects[i].MiscValue))
5950 break;
5951 }
5953 {
5954 if (m_caster->HasUnitState(UNIT_STATE_ROOT))
5956
5957 if (GetSpellInfo()->NeedsExplicitUnitTarget())
5958 {
5959 Unit* target = m_targets.GetUnitTarget();
5960 if (!target)
5962
5963 Position pos;
5966
5967 m_preGeneratedPath.SetPathLengthLimit(m_spellInfo->GetMaxRange(true) * 1.5f);
5968 bool result = m_preGeneratedPath.CalculatePath(pos.m_positionX, pos.m_positionY, pos.m_positionZ + target->GetObjectSize());
5969 if (m_preGeneratedPath.GetPathType() & PATHFIND_SHORT)
5971 else if (!result || m_preGeneratedPath.GetPathType() & PATHFIND_NOPATH)
5973 }
5974 break;
5975 }
5977 {
5978 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER || !m_targets.GetUnitTarget() || m_targets.GetUnitTarget()->GetTypeId() != TypeID::TYPEID_UNIT)
5980
5981 if (!(m_targets.GetUnitTarget()->GetUInt32Value(UNIT_FIELD_FLAGS) & UNIT_FLAG_SKINNABLE))
5983
5984 Creature* creature = m_targets.GetUnitTarget()->ToCreature();
5985 if (creature->GetCreatureType() != CREATURE_TYPE_CRITTER && !creature->loot.isLooted())
5987
5988 uint32 skill = creature->GetCreatureTemplate()->GetRequiredLootSkill();
5989
5990 int32 skillValue = m_caster->ToPlayer()->GetSkillValue(skill);
5991 int32 TargetLevel = m_targets.GetUnitTarget()->getLevel();
5992 int32 ReqValue = (skillValue < 100 ? (TargetLevel - 10) * 10 : TargetLevel * 5);
5993 if (ReqValue > skillValue)
5995
5996 // chance for fail at orange skinning attempt
5997 if ((m_selfContainer && (*m_selfContainer) == this) &&
5998 skillValue < sWorld->GetConfigMaxSkillValue() &&
5999 (ReqValue < 0 ? 0 : ReqValue) > (std::rand() % (skillValue + 37) + (skillValue - 25)))
6001
6002 break;
6003 }
6005 {
6006 if (m_spellInfo->Effects[i].TargetA.GetTarget() != TARGET_GAMEOBJECT_TARGET &&
6007 m_spellInfo->Effects[i].TargetA.GetTarget() != TARGET_GAMEOBJECT_ITEM_TARGET)
6008 break;
6009
6010 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER // only players can open locks, gather etc.
6011 // we need a go target in case of TARGET_GAMEOBJECT_TARGET
6012 || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_TARGET && !m_targets.GetGOTarget()))
6014
6015 Item* pTempItem = NULL;
6016 if (m_targets.GetTargetMask() & TARGET_FLAG_TRADE_ITEM)
6017 {
6018 if (TradeData* pTrade = m_caster->ToPlayer()->GetTradeData())
6019 pTempItem = pTrade->GetTraderData()->GetItem(TradeSlots(m_targets.GetItemTargetGUID()));
6020 }
6021 else if (m_targets.GetTargetMask() & TARGET_FLAG_ITEM)
6022 pTempItem = m_caster->ToPlayer()->GetItemByGuid(m_targets.GetItemTargetGUID());
6023
6024 // we need a go target, or an openable item target in case of TARGET_GAMEOBJECT_ITEM_TARGET
6025 if (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET &&
6026 !m_targets.GetGOTarget() &&
6027 (!pTempItem || !pTempItem->GetTemplate()->LockID || !pTempItem->IsLocked()))
6029
6030 if (m_spellInfo->Id != 1842 || (m_targets.GetGOTarget() &&
6031 m_targets.GetGOTarget()->GetGOInfo()->type != GAMEOBJECT_TYPE_TRAP))
6032 if (m_caster->ToPlayer()->InBattleground() && // In Battleground players can use only flags and banners
6033 !m_caster->ToPlayer()->CanUseBattlegroundObject(m_targets.GetGOTarget()))
6035
6036 // get the lock entry
6037 uint32 lockId = 0;
6038 if (GameObject* go = m_targets.GetGOTarget())
6039 {
6040 lockId = go->GetGOInfo()->GetLockId();
6041 if (!lockId)
6043 }
6044 else if (Item* itm = m_targets.GetItemTarget())
6045 lockId = itm->GetTemplate()->LockID;
6046
6047 SkillType skillId = SKILL_NONE;
6048 int32 reqSkillValue = 0;
6049 int32 skillValue = 0;
6050
6051 // check lock compatibility
6052 SpellCastResult res = CanOpenLock(i, lockId, skillId, reqSkillValue, skillValue);
6054 return res;
6055
6056 // chance for fail at orange mining/herb/LockPicking gathering attempt
6057 // second check prevent fail at rechecks
6058 if (skillId != SKILL_NONE && (!m_selfContainer || ((*m_selfContainer) != this)))
6059 {
6060 bool canFailAtMax = skillId != SKILL_HERBALISM && skillId != SKILL_MINING;
6061
6062 // chance for failure in orange gather / lockpick (gathering skill can't fail at maxskill)
6063 if ((canFailAtMax || skillValue < sWorld->GetConfigMaxSkillValue()) && reqSkillValue > (std::rand() % (skillValue + 37) + (skillValue - 25)))
6065 }
6066 break;
6067 }
6069 {
6070 Creature* pet = m_caster->GetGuardianPet();
6071
6072 if (pet && pet->IsAlive())
6074
6075 break;
6076 }
6077 // This is generic summon effect
6079 {
6080 SummonPropertiesEntry const* SummonProperties = sSummonPropertiesStore.LookupEntry(m_spellInfo->Effects[i].MiscValueB);
6081 if (!SummonProperties)
6082 break;
6083 switch (SummonProperties->Category)
6084 {
6086 if (m_caster->GetPetGUID())
6089 if (m_caster->GetCharmGUID())
6091 break;
6092 }
6093 break;
6094 }
6096 {
6097 if (m_targets.GetUnitTarget())
6098 {
6099 if (m_targets.GetUnitTarget()->GetTypeId() != TypeID::TYPEID_PLAYER)
6101 if (m_targets.GetUnitTarget()->GetPetGUID())
6103 }
6104 break;
6105 }
6107 {
6108 if (m_caster->GetPetGUID()) //let warlock do a replacement summon
6109 {
6110 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && m_caster->getClass() == CLASS_WARLOCK)
6111 {
6112 if (strict) //starting cast, trigger pet stun (cast by pet so it doesn't attack player)
6113 if (Pet* pet = m_caster->ToPlayer()->GetPet())
6114 pet->CastSpell(pet, 32752, true, NULL, NULL, pet->GetGUID());
6115 }
6116 else
6118 }
6119
6120 if (m_caster->GetCharmGUID())
6122 break;
6123 }
6125 {
6126 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
6128 if (!m_caster->GetTarget())
6130
6131 Player* target = ObjectAccessor::FindPlayer(m_caster->ToPlayer()->GetTarget());
6132 if (!target || m_caster->ToPlayer() == target || (!target->IsInSameRaidWith(m_caster->ToPlayer()) && m_spellInfo->Id != 48955)) // refer-a-friend spell
6134
6135 // check if our map is dungeon or raid
6136 MapEntry const* map = sMapStore.LookupEntry(m_caster->GetMapId());
6137 if (map->IsInstance())
6138 {
6139 uint32 mapId = m_caster->GetMap()->GetId();
6140 DifficultyID difficulty = m_caster->GetMap()->GetDifficulty();
6141 if (map->IsRaid())
6142 if (InstancePlayerBind* targetBind = target->GetBoundInstance(mapId, difficulty))
6143 if (InstancePlayerBind* casterBind = m_caster->ToPlayer()->GetBoundInstance(mapId, difficulty))
6144 if (targetBind->perm && targetBind->save != casterBind->save)
6146
6147 InstanceTemplate const* instance = sObjectMgr->GetInstanceTemplate(mapId);
6148 if (!instance)
6150 if (!target->Satisfy(sObjectMgr->GetAccessRequirement(mapId, difficulty), mapId))
6152 }
6153 break;
6154 }
6155 // RETURN HERE
6157 {
6158 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
6160
6161 Player* playerCaster = m_caster->ToPlayer();
6162 //
6163 if (!(playerCaster->GetTarget()))
6165
6166 Player* target = playerCaster->GetSelectedPlayer();
6167
6168 if (!target ||
6169 !(target->GetSession()->GetRecruiterId() == playerCaster->GetSession()->GetAccountId() || target->GetSession()->GetAccountId() == playerCaster->GetSession()->GetRecruiterId()))
6171
6172 break;
6173 }
6174 case SPELL_EFFECT_LEAP:
6176 {
6177 //Do not allow to cast it before BG starts.
6178 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
6179 if (Battleground const* bg = m_caster->ToPlayer()->GetBattleground())
6180 if (bg->GetStatus() != STATUS_IN_PROGRESS)
6182 break;
6183 }
6185 {
6186 if (m_targets.GetUnitTarget() == m_caster)
6188 break;
6189 }
6191 {
6192 if (m_caster->HasUnitState(UNIT_STATE_ROOT))
6193 {
6194 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
6196 else
6198 }
6199 break;
6200 }
6202 // can't change during already started arena/battleground
6203 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
6204 if (Battleground const* bg = m_caster->ToPlayer()->GetBattleground())
6205 if (bg->GetStatus() == STATUS_IN_PROGRESS)
6207 break;
6208 default:
6209 break;
6210 }
6211 }
6212
6213 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
6214 {
6215 switch (m_spellInfo->Effects[i].ApplyAuraName)
6216 {
6218 {
6219 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
6221
6222 Pet* pet = m_caster->ToPlayer()->GetPet();
6223 if (!pet)
6225
6226 if (pet->GetCharmerGUID())
6228 break;
6229 }
6233 {
6234 if (m_caster->GetCharmerGUID())
6236
6237 if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_CHARM
6238 || m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MOD_POSSESS)
6239 {
6240 if (m_caster->GetPetGUID())
6242
6243 if (m_caster->GetCharmGUID())
6245 }
6246
6247 if (Unit* target = m_targets.GetUnitTarget())
6248 {
6249 if (target->GetTypeId() == TypeID::TYPEID_UNIT && target->ToCreature()->IsVehicle())
6251
6252 if (target->IsMounted())
6254
6255 if (target->GetCharmerGUID())
6257
6258 if (target->GetOwner() && target->GetOwner()->GetTypeId() == TypeID::TYPEID_PLAYER)
6260
6261 int32 damage = CalculateDamage(i, target);
6262 if (damage && int32(target->getLevel()) > damage)
6264 }
6265
6266 break;
6267 }
6268 case SPELL_AURA_MOUNTED:
6269 {
6270 if (m_caster->IsInWater())
6272
6273 // Ignore map check if spell have AreaId. AreaId already checked and this prevent special mount spells
6274 bool allowMount = !m_caster->GetMap()->IsInstance() || m_caster->GetMap()->IsBattlegroundOrArena();
6275 InstanceTemplate const* it = sObjectMgr->GetInstanceTemplate(m_caster->GetMapId());
6276 if (it)
6277 allowMount = it->AllowMount;
6278 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER && !allowMount && !m_spellInfo->AreaGroupId)
6280
6281 if (m_caster->IsInDisallowedMountForm())
6283
6284 break;
6285 }
6287 {
6288 if (!m_targets.GetUnitTarget())
6290
6291 // can be casted at non-friendly unit or own pet/charm
6292 if (m_caster->IsFriendlyTo(m_targets.GetUnitTarget()))
6294
6295 break;
6296 }
6297 case SPELL_AURA_FLY:
6299 {
6300 // not allow cast fly spells if not have req. skills (all spells is self target)
6301 // allow always ghost flight spells
6302 if (m_originalCaster && m_originalCaster->GetTypeId() == TypeID::TYPEID_PLAYER && m_originalCaster->IsAlive())
6303 {
6304 Battlefield* Bf = sBattlefieldMgr->GetBattlefieldToZoneId(m_originalCaster->GetZoneId());
6305 if (AreaTableEntry const* area = GetAreaEntryByAreaID(m_originalCaster->GetAreaId()))
6306 if (area->m_flags & AREA_FLAG_NO_FLY_ZONE || (Bf && !Bf->CanFlyIn()))
6308 }
6309 break;
6310 }
6312 {
6313 if (m_spellInfo->Effects[i].IsTargetingArea())
6314 break;
6315
6316 if (!m_targets.GetUnitTarget())
6318
6319 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER || m_CastItem)
6320 break;
6321
6322 if (m_targets.GetUnitTarget()->getPowerType() != POWER_MANA)
6324
6325 break;
6326 }
6327 default:
6328 break;
6329 }
6330 }
6331
6332 // check trade slot case (last, for allow catch any another cast problems)
6333 if (m_targets.GetTargetMask() & TARGET_FLAG_TRADE_ITEM)
6334 {
6335 if (m_CastItem)
6337
6338 if (m_caster->GetTypeId() != TypeID::TYPEID_PLAYER)
6340
6341 TradeData* my_trade = m_caster->ToPlayer()->GetTradeData();
6342
6343 if (!my_trade)
6345
6346 TradeSlots slot = TradeSlots(m_targets.GetItemTargetGUID());
6347 if (slot != TRADE_SLOT_NONTRADED)
6349
6350 if (!IsTriggered())
6351 if (my_trade->GetSpell())
6353 }
6354
6355 // check if caster has at least 1 combo point for spells that require combo points
6357 if (Player* plrCaster = m_caster->ToPlayer())
6358 if (!plrCaster->GetComboPoints())
6360
6361 // all ok
6363}
6364
6366{
6367 if (m_caster->HasUnitState(UNIT_STATE_CASTING) && !(_triggeredCastFlags & TRIGGERED_IGNORE_CAST_IN_PROGRESS)) //prevent spellcast interruption by another spellcast
6369
6370 // dead owner (pets still alive when owners ressed?)
6371 if (Unit* owner = m_caster->GetCharmerOrOwner())
6372 if (!owner->IsAlive())
6374
6375 if (!target && m_targets.GetUnitTarget())
6376 target = m_targets.GetUnitTarget();
6377
6378 if (m_spellInfo->NeedsExplicitUnitTarget())
6379 {
6380 if (!target)
6382 m_targets.SetUnitTarget(target);
6383 }
6384
6385 // cooldown
6386 if (Creature const* creatureCaster = m_caster->ToCreature())
6387 if (creatureCaster->HasSpellCooldown(m_spellInfo->Id))
6389
6390 // Check if spell is affected by GCD
6391 if (m_spellInfo->StartRecoveryCategory > 0)
6392 if (m_caster->GetCharmInfo() && m_caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo))
6394
6395 return CheckCast(true);
6396}
6397
6399{
6400 // spells totally immuned to caster auras (wsg flag drop, give marks etc)
6401 if (m_spellInfo->AttributesEx6 & SPELL_ATTR6_IGNORE_CASTER_AURAS)
6403
6404 uint8 school_immune = 0;
6405 uint32 mechanic_immune = 0;
6406 uint32 dispel_immune = 0;
6407
6408 // Check if the spell grants school or mechanic immunity.
6409 // We use bitmasks so the loop is done only once and not on every aura check below.
6411 {
6412 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
6413 {
6414 if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_SCHOOL_IMMUNITY)
6415 school_immune |= uint32(m_spellInfo->Effects[i].MiscValue);
6416 else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_MECHANIC_IMMUNITY)
6417 mechanic_immune |= 1 << uint32(m_spellInfo->Effects[i].MiscValue);
6418 else if (m_spellInfo->Effects[i].ApplyAuraName == SPELL_AURA_DISPEL_IMMUNITY)
6419 dispel_immune |= SpellInfo::GetDispelMask(DispelType(m_spellInfo->Effects[i].MiscValue));
6420 }
6421 // immune movement impairment and loss of control
6422 if (m_spellInfo->Id == 42292 || m_spellInfo->Id == 59752 || m_spellInfo->Id == 19574)
6424 }
6425
6426 bool usableInStun = m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_STUNNED;
6427
6428 // Glyph of Pain Suppression
6429 // Allow Pain Suppression and Guardian Spirit to be cast while stunned
6430 // there is no other way to handle it
6431 if ((m_spellInfo->Id == 33206 || m_spellInfo->Id == 47788) && !m_caster->HasAura(63248))
6432 usableInStun = false;
6433
6434 // Check whether the cast should be prevented by any state you might have.
6436 // Have to check if there is a stun aura. Otherwise will have problems with ghost aura apply while logging out
6437 uint32 unitflag = m_caster->GetUInt32Value(UNIT_FIELD_FLAGS); // Get unit state
6438 if (unitflag & UNIT_FLAG_STUNNED)
6439 {
6440 // spell is usable while stunned, check if caster has only mechanic stun auras, another stun types must prevent cast spell
6441 if (usableInStun)
6442 {
6443 bool foundNotStun = false;
6444 Unit::AuraEffectList const& stunAuras = m_caster->GetAuraEffectsByType(SPELL_AURA_MOD_STUN);
6445 for (Unit::AuraEffectList::const_iterator i = stunAuras.begin(); i != stunAuras.end(); ++i)
6446 {
6447 uint32 auraMechanicMask = (*i)->GetSpellInfo()->GetAllEffectsMechanicMask();
6448 if (auraMechanicMask && !Skyfire::Spells::HasMechanic(auraMechanicMask, MECHANIC_STUN))
6449 {
6450 foundNotStun = true;
6451 break;
6452 }
6453 }
6454 if (foundNotStun && m_spellInfo->Id != 22812)
6455 prevented_reason = SpellCastResult::SPELL_FAILED_STUNNED;
6456 }
6457 else
6458 prevented_reason = SpellCastResult::SPELL_FAILED_STUNNED;
6459 }
6460 else if (unitflag & UNIT_FLAG_CONFUSED && !(m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_CONFUSED))
6461 prevented_reason = SpellCastResult::SPELL_FAILED_CONFUSED;
6462 else if (unitflag & UNIT_FLAG_FLEEING && !(m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_FEARED))
6463 prevented_reason = SpellCastResult::SPELL_FAILED_FLEEING;
6464 else if (unitflag & UNIT_FLAG_SILENCED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
6465 prevented_reason = SpellCastResult::SPELL_FAILED_SILENCED;
6466 else if (unitflag & UNIT_FLAG_PACIFIED && m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY)
6467 prevented_reason = SpellCastResult::SPELL_FAILED_PACIFIED;
6468
6469 // Attr must make flag drop spell totally immune from all effects
6470 if (prevented_reason != SpellCastResult::SPELL_CAST_OK)
6471 {
6472 if (school_immune || mechanic_immune || dispel_immune)
6473 {
6474 //Checking auras is needed now, because you are prevented by some state but the spell grants immunity.
6475 Unit::AuraApplicationMap const& auras = m_caster->GetAppliedAuras();
6476 for (Unit::AuraApplicationMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
6477 {
6478 Aura const* aura = itr->second->GetBase();
6479 SpellInfo const* auraInfo = aura->GetSpellInfo();
6480 if (auraInfo->GetAllEffectsMechanicMask() & mechanic_immune)
6481 continue;
6482 if (auraInfo->GetSchoolMask() & school_immune && !(auraInfo->AttributesEx & SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE))
6483 continue;
6484 if (auraInfo->GetDispelMask() & dispel_immune)
6485 continue;
6486
6487 //Make a second check for spell failed so the right SPELL_FAILED message is returned.
6488 //That is needed when your casting is prevented by multiple states and you are only immune to some of them.
6489 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
6490 {
6491 if (AuraEffect* part = aura->GetEffect(i))
6492 {
6493 switch (part->GetAuraType())
6494 {
6496 if (!usableInStun || !Skyfire::Spells::HasMechanic(auraInfo->GetAllEffectsMechanicMask(), MECHANIC_STUN))
6498 break;
6500 if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_CONFUSED))
6502 break;
6504 if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR5_USABLE_WHILE_FEARED))
6506 break;
6510 if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY)
6512 else if (m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
6514 break;
6515 default: break;
6516 }
6517 }
6518 }
6519 }
6520 }
6521 // You are prevented from casting and the spell casted does not grant immunity. Return a failed error.
6522 else
6523 return prevented_reason;
6524 }
6526}
6527
6529{
6530 bool isRatedBattleground = false; // NYI
6531 bool isArena = !isRatedBattleground;
6532
6533 // check USABLE attributes
6534 // USABLE takes precedence over NOT_USABLE
6535 if (isRatedBattleground && m_spellInfo->AttributesEx9 & SPELL_ATTR9_USABLE_IN_RATED_BATTLEGROUNDS)
6537
6538 if (isArena && m_spellInfo->AttributesEx4 & SPELL_ATTR4_USABLE_IN_ARENA)
6540
6541 // check NOT_USABLE attributes
6544
6545 if (isArena && m_spellInfo->AttributesEx9 & SPELL_ATTR9_NOT_USABLE_IN_ARENA)
6547
6548 // check cooldowns
6549 uint32 spellCooldown = m_spellInfo->GetRecoveryTime();
6550 if (isArena && spellCooldown > 10 * MINUTE * IN_MILLISECONDS) // not sure if still needed
6552
6553 if (isRatedBattleground && spellCooldown > 15 * MINUTE * IN_MILLISECONDS)
6555
6557}
6558
6560{
6561 uint64 targetguid = target->GetGUID();
6562
6563 for (uint32 j = 0; j < MAX_SPELL_EFFECTS; ++j)
6564 {
6565 if (m_spellInfo->Effects[j].Effect == SPELL_EFFECT_APPLY_AURA)
6566 {
6567 if (m_spellInfo->StackAmount <= 1)
6568 {
6569 if (target->HasAuraEffect(m_spellInfo->Id, j))
6570 return false;
6571 }
6572 else
6573 {
6574 if (AuraEffect* aureff = target->GetAuraEffect(m_spellInfo->Id, j))
6575 if (aureff->GetBase()->GetStackAmount() >= m_spellInfo->StackAmount)
6576 return false;
6577 }
6578 }
6579 else if (m_spellInfo->Effects[j].IsAreaAuraEffect())
6580 {
6581 if (target->HasAuraEffect(m_spellInfo->Id, j))
6582 return false;
6583 }
6584 }
6585
6586 SpellCastResult result = CheckPetCast(target);
6587
6589 {
6591 //check if among target units, our WANTED target is as well (->only self cast spells return false)
6592 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
6593 if (ihit->targetGUID == targetguid)
6594 return true;
6595 }
6596 return false; //target invalid
6597}
6598
6600{
6601 // Don't check for instant cast spells
6602 if (!strict && m_casttime == 0)
6604
6605 uint32 range_type = 0;
6606
6607 if (m_spellInfo->RangeEntry)
6608 {
6609 // check needed by 68766 51693 - both spells are cast on enemies and have 0 max range
6610 // these are triggered by other spells - possibly we should omit range check in that case?
6611 if (m_spellInfo->RangeEntry->ID == 1)
6613
6614 range_type = m_spellInfo->RangeEntry->type;
6615 }
6616
6617 Unit* target = m_targets.GetUnitTarget();
6618 float max_range = m_caster->GetSpellMaxRangeForTarget(target, m_spellInfo);
6619 float min_range = m_caster->GetSpellMinRangeForTarget(target, m_spellInfo);
6620
6621 if (Player* modOwner = m_caster->GetSpellModOwner())
6622 modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, max_range, this);
6623
6624 if (target && target != m_caster)
6625 {
6626 if (range_type == SPELL_RANGE_MELEE)
6627 {
6628 // Because of lag, we can not check too strictly here.
6629 if (!m_caster->IsWithinMeleeRange(target, max_range))
6631 }
6632 else if (!m_caster->IsWithinCombatRange(target, max_range))
6634
6635 if (range_type == SPELL_RANGE_RANGED)
6636 {
6637 if (m_caster->IsWithinMeleeRange(target))
6639 }
6640 else if (min_range && m_caster->IsWithinCombatRange(target, min_range)) // skip this check if min_range = 0
6642
6643 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER &&
6644 (m_spellInfo->FacingCasterFlags & SPELL_FACING_FLAG_INFRONT) && !m_caster->HasInArc(static_cast<float>(M_PI), target))
6646 }
6647
6648 if (m_targets.HasDst() && !m_targets.HasTraj())
6649 {
6650 if (!m_caster->IsWithinDist3d(m_targets.GetDstPos(), max_range))
6652 if (min_range && m_caster->IsWithinDist3d(m_targets.GetDstPos(), min_range))
6654 }
6655
6657}
6658
6660{
6661 // item cast not used power
6662 if (m_CastItem)
6664
6665 // health as power used - need check health amount
6667 {
6668 if (int32(m_caster->GetHealth()) <= m_powerCost)
6671 }
6672 // Check valid power type
6673 if (m_powerType >= MAX_POWERS)
6674 {
6675 SF_LOG_ERROR("spells", "Spell::CheckPower: Unknown power type '%d'", m_powerType);
6677 }
6678
6679 //check rune cost only if a spell has PowerType == POWER_RUNES
6680 if (m_powerType == POWER_RUNES)
6681 {
6682 SpellCastResult failReason = CheckRuneCost(m_spellInfo->RuneCostID);
6683 if (failReason != SpellCastResult::SPELL_CAST_OK)
6684 return failReason;
6685 }
6686
6687 // Check power amount
6688 Powers powerType = Powers(m_powerType);
6689 if (int32(m_caster->GetPower(powerType)) < m_powerCost)
6691 else
6693}
6694
6696{
6697 Player* player = m_caster->ToPlayer();
6698 if (!player)
6700
6701 if (!m_CastItem)
6702 {
6703 if (m_castItemGUID)
6705 }
6706 else
6707 {
6708 uint32 itemid = m_CastItem->GetEntry();
6709 if (!player->HasItemCount(itemid))
6711
6712 ItemTemplate const* proto = m_CastItem->GetTemplate();
6713 if (!proto)
6715
6716 for (uint8 i = 0; i < MAX_ITEM_SPELLS; ++i)
6717 if (proto->Spells[i].SpellCharges)
6718 if (m_CastItem->GetSpellCharges(i) == 0)
6720
6721 // consumable cast item checks
6722 if (proto->Class == ITEM_CLASS_CONSUMABLE && m_targets.GetUnitTarget())
6723 {
6724 // such items should only fail if there is no suitable effect at all - see Rejuvenation Potions for example
6726 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
6727 {
6728 // skip check, pet not required like checks, and for TARGET_UNIT_PET m_targets.GetUnitTarget() is not the real target but the caster
6729 if (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_PET)
6730 continue;
6731
6732 if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_HEAL)
6733 {
6734 if (m_targets.GetUnitTarget()->IsFullHealth())
6735 {
6737 continue;
6738 }
6739 else
6740 {
6741 failReason = SpellCastResult::SPELL_CAST_OK;
6742 break;
6743 }
6744 }
6745
6746 // Mana Potion, Rage Potion, Thistle Tea(Rogue), ...
6747 if (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_ENERGIZE)
6748 {
6749 if (m_spellInfo->Effects[i].MiscValue < 0 || m_spellInfo->Effects[i].MiscValue >= int8(MAX_POWERS))
6750 {
6752 continue;
6753 }
6754
6755 Powers power = Powers(m_spellInfo->Effects[i].MiscValue);
6756 if (m_targets.GetUnitTarget()->GetPower(power) == m_targets.GetUnitTarget()->GetMaxPower(power))
6757 {
6759 continue;
6760 }
6761 else
6762 {
6763 failReason = SpellCastResult::SPELL_CAST_OK;
6764 break;
6765 }
6766 }
6767 }
6768 if (failReason != SpellCastResult::SPELL_CAST_OK)
6769 return failReason;
6770 }
6771 }
6772
6773 // check target item
6774 if (m_targets.GetItemTargetGUID())
6775 {
6776 if (!m_targets.GetItemTarget())
6778
6779 if (!m_targets.GetItemTarget()->IsFitToSpellRequirements(m_spellInfo))
6781 }
6782 // if not item target then required item must be equipped
6783 else
6784 {
6788 }
6789
6790 // do not take reagents for these item casts
6791 if (!(m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST))
6792 {
6794 // Not own traded item (in trader trade slot) requires reagents even if triggered spell
6795 if (!checkReagents)
6796 if (Item* targetItem = m_targets.GetItemTarget())
6797 if (targetItem->GetOwnerGUID() != m_caster->GetGUID())
6798 checkReagents = true;
6799
6800 // check reagents (ignore triggered spells with reagents processed by original spell) and special reagent ignore case.
6801 if (checkReagents)
6802 {
6803 for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++)
6804 {
6805 if (m_spellInfo->Reagent[i] <= 0)
6806 continue;
6807
6808 uint32 itemid = m_spellInfo->Reagent[i];
6809 uint32 itemcount = m_spellInfo->ReagentCount[i];
6810
6811 // if CastItem is also spell reagent
6812 if (m_CastItem && m_CastItem->GetEntry() == itemid)
6813 {
6814 ItemTemplate const* proto = m_CastItem->GetTemplate();
6815 if (!proto)
6817 for (uint8 s = 0; s < MAX_ITEM_PROTO_SPELLS; ++s)
6818 {
6819 // CastItem will be used up and does not count as reagent
6820 int32 charges = m_CastItem->GetSpellCharges(s);
6821 if (proto->Spells[s].SpellCharges < 0 && abs(charges) < 2)
6822 {
6823 ++itemcount;
6824 break;
6825 }
6826 }
6827 }
6828 if (!player->HasItemCount(itemid, itemcount))
6830 }
6831 }
6832
6833 // check totem-item requirements (items presence in inventory)
6834 uint32 totems = 2;
6835 for (uint8 i = 0; i < 2; ++i)
6836 {
6837 if (m_spellInfo->Totem[i] != 0)
6838 {
6839 if (player->HasItemCount(m_spellInfo->Totem[i]))
6840 {
6841 totems -= 1;
6842 continue;
6843 }
6844 }
6845 else
6846 totems -= 1;
6847 }
6848 if (totems != 0)
6850 }
6851
6852 // special checks for spell effects
6853 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
6854 {
6855 switch (m_spellInfo->Effects[i].Effect)
6856 {
6859 {
6860 if (!IsTriggered() && m_spellInfo->Effects[i].ItemType)
6861 {
6862 ItemPosCountVec dest;
6863 InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1);
6864 if (msg != EQUIP_ERR_OK)
6865 {
6866 ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(m_spellInfo->Effects[i].ItemType);
6868 if (pProto && !(pProto->ItemLimitCategory))
6869 {
6870 player->SendEquipError(msg, NULL, NULL, m_spellInfo->Effects[i].ItemType);
6872 }
6873 else
6874 {
6875 if (!(m_spellInfo->SpellFamilyName == SPELLFAMILY_MAGE && (m_spellInfo->SpellFamilyFlags[0] & 0x40000000)))
6877 else if (!(player->HasItemCount(m_spellInfo->Effects[i].ItemType)))
6879 else
6880 player->CastSpell(m_caster, m_spellInfo->Effects[EFFECT_1].CalcValue(), false); // move this to anywhere
6882 }
6883 }
6884 }
6885 break;
6886 }
6888 if (m_spellInfo->Effects[i].ItemType && m_targets.GetItemTarget()
6889 && (m_targets.GetItemTarget()->IsVellum()))
6890 {
6891 // cannot enchant vellum for other player
6892 if (m_targets.GetItemTarget()->GetOwner() != m_caster)
6894 // do not allow to enchant vellum from scroll made by vellum-prevent exploit
6895 if (m_CastItem && m_CastItem->GetTemplate()->Flags & ITEM_PROTO_FLAG_TRIGGERED_CAST)
6897 ItemPosCountVec dest;
6898 InventoryResult msg = player->CanStoreNewItem(NULL_BAG, NULL_SLOT, dest, m_spellInfo->Effects[i].ItemType, 1);
6899 if (msg != EQUIP_ERR_OK)
6900 {
6901 player->SendEquipError(msg, NULL, NULL, m_spellInfo->Effects[i].ItemType);
6903 }
6904 }
6905 // no break
6907 {
6908 Item* targetItem = m_targets.GetItemTarget();
6909 if (!targetItem)
6911
6912 if (targetItem->GetTemplate()->ItemLevel < m_spellInfo->BaseLevel)
6914
6915 bool isItemUsable = false;
6916 for (uint8 e = 0; e < MAX_ITEM_PROTO_SPELLS; ++e)
6917 {
6918 ItemTemplate const* proto = targetItem->GetTemplate();
6919 if (proto->Spells[e].SpellId && (
6922 {
6923 isItemUsable = true;
6924 break;
6925 }
6926 }
6927
6928 SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(m_spellInfo->Effects[i].MiscValue);
6929 // do not allow adding usable enchantments to items that have use effect already
6930 if (pEnchant && isItemUsable)
6931 for (uint8 s = 0; s < MAX_ITEM_ENCHANTMENT_EFFECTS; ++s)
6932 if (pEnchant->type[s] == ITEM_ENCHANTMENT_TYPE_USE_SPELL)
6934
6935 // Not allow enchant in trade slot for some enchant type
6936 if (targetItem->GetOwner() != m_caster)
6937 {
6938 if (!pEnchant)
6940 if (pEnchant->slot & ENCHANTMENT_CAN_SOULBOUND)
6942 }
6943 break;
6944 }
6946 {
6947 Item* item = m_targets.GetItemTarget();
6948 if (!item)
6950 // Not allow enchant in trade slot for some enchant type
6951 if (item->GetOwner() != m_caster)
6952 {
6953 uint32 enchant_id = m_spellInfo->Effects[i].MiscValue;
6954 SpellItemEnchantmentEntry const* pEnchant = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
6955 if (!pEnchant)
6957 if (pEnchant->slot & ENCHANTMENT_CAN_SOULBOUND)
6959 }
6960 break;
6961 }
6963 // check item existence in effect code (not output errors at offhand hold item effect to main hand for example
6964 break;
6966 {
6967 if (!m_targets.GetItemTarget())
6969
6970 // prevent disenchanting in trade slot
6971 if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID())
6973
6974 ItemTemplate const* itemProto = m_targets.GetItemTarget()->GetTemplate();
6975 if (!itemProto)
6977
6978 uint32 item_quality = itemProto->Quality;
6979 // 2.0.x addon: Check player enchanting level against the item disenchanting requirements
6980 uint32 item_disenchantskilllevel = itemProto->RequiredDisenchantSkill;
6981 if (item_disenchantskilllevel == uint32(-1))
6983 if (item_disenchantskilllevel > player->GetSkillValue(SKILL_ENCHANTING))
6985 if (item_quality > 4 || item_quality < 2)
6987 if (itemProto->Class != ITEM_CLASS_WEAPON && itemProto->Class != ITEM_CLASS_ARMOR)
6989 if (!itemProto->DisenchantID)
6991 break;
6992 }
6994 {
6995 if (!m_targets.GetItemTarget())
6997 //ensure item is a prospectable ore
6998 if (!(m_targets.GetItemTarget()->GetTemplate()->Flags & ITEM_PROTO_FLAG_PROSPECTABLE))
7000 //prevent prospecting in trade slot
7001 if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID())
7003 //Check for enough skill in jewelcrafting
7004 uint32 item_prospectingskilllevel = m_targets.GetItemTarget()->GetTemplate()->RequiredSkillRank;
7005 if (item_prospectingskilllevel > player->GetSkillValue(SKILL_JEWELCRAFTING))
7007 //make sure the player has the required ores in inventory
7008 if (m_targets.GetItemTarget()->GetCount() < 5)
7010
7011 if (!LootTemplates_Prospecting.HaveLootFor(m_targets.GetItemTargetEntry()))
7013
7014 break;
7015 }
7017 {
7018 if (!m_targets.GetItemTarget())
7020 //ensure item is a millable herb
7021 if (!(m_targets.GetItemTarget()->GetTemplate()->Flags & ITEM_PROTO_FLAG_MILLABLE))
7023 //prevent milling in trade slot
7024 if (m_targets.GetItemTarget()->GetOwnerGUID() != m_caster->GetGUID())
7026 //Check for enough skill in inscription
7027 uint32 item_millingskilllevel = m_targets.GetItemTarget()->GetTemplate()->RequiredSkillRank;
7028 if (item_millingskilllevel > player->GetSkillValue(SKILL_INSCRIPTION))
7030 //make sure the player has the required herbs in inventory
7031 if (m_targets.GetItemTarget()->GetCount() < 5)
7033
7034 if (!LootTemplates_Milling.HaveLootFor(m_targets.GetItemTargetEntry()))
7036
7037 break;
7038 }
7041 {
7043 break;
7044
7045 Item* pItem = player->GetWeaponForAttack(m_attackType);
7046 if (!pItem || pItem->IsBroken())
7048
7049 switch (pItem->GetTemplate()->SubClass)
7050 {
7052 {
7053 uint32 ammo = pItem->GetEntry();
7054 if (!player->HasItemCount(ammo))
7056 break;
7057 }
7062 break;
7063 default:
7064 break;
7065 }
7066 break;
7067 }
7069 {
7070 uint32 item_id = m_spellInfo->Effects[i].ItemType;
7071 ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(item_id);
7072
7073 if (!pProto)
7075
7076 if (Item* pitem = player->GetItemByEntry(item_id))
7077 {
7078 for (int x = 0; x < MAX_ITEM_PROTO_SPELLS; ++x)
7079 if (pProto->Spells[x].SpellCharges != 0 && pitem->GetSpellCharges(x) == pProto->Spells[x].SpellCharges)
7081 }
7082 break;
7083 }
7084 default:
7085 break;
7086 }
7087 }
7088
7089 // check weapon presence in slots for main/offhand weapons
7091 {
7092 // main hand weapon required
7093 if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_MAIN_HAND)
7094 {
7095 Item* item = m_caster->ToPlayer()->GetWeaponForAttack(WeaponAttackType::BASE_ATTACK);
7096
7097 // skip spell if no weapon in slot or broken
7098 if (!item || item->IsBroken())
7100
7101 // skip spell if weapon not fit to triggered spell
7104 }
7105
7106 // offhand hand weapon required
7107 if (m_spellInfo->AttributesEx3 & SPELL_ATTR3_REQ_OFFHAND)
7108 {
7109 Item* item = m_caster->ToPlayer()->GetWeaponForAttack(WeaponAttackType::OFF_ATTACK);
7110
7111 // skip spell if no weapon in slot or broken
7112 if (!item || item->IsBroken())
7114
7115 // skip spell if weapon not fit to triggered spell
7118 }
7119 }
7120
7122}
7123
7124void Spell::Delayed() // only called in DealDamage()
7125{
7126 if (!m_caster)// || m_caster->GetTypeId() != TYPEID_PLAYER)
7127 return;
7128
7129 //if (m_spellState == SPELL_STATE_DELAYED)
7130 // return; // spell is active and can't be time-backed
7131
7132 if (isDelayableNoMore()) // Spells may only be delayed twice
7133 return;
7134
7135 // spells not loosing casting time (slam, dynamites, bombs..)
7136 //if (!(m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_DAMAGE))
7137 // return;
7138
7139 //check pushback reduce
7140 int32 delaytime = 500; // spellcasting delay is normally 500ms
7141 int32 delayReduce = 100; // must be initialized to 100 for percent modifiers
7142 m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_NOT_LOSE_CASTING_TIME, delayReduce, this);
7143 delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100;
7144 if (delayReduce >= 100)
7145 return;
7146
7147 AddPct(delaytime, -delayReduce);
7148
7149 if (m_timer + delaytime > m_casttime)
7150 {
7151 delaytime = m_casttime - m_timer;
7153 }
7154 else
7155 m_timer += delaytime;
7156
7157 SF_LOG_INFO("spells", "Spell %u partially interrupted for (%d) ms at damage", m_spellInfo->Id, delaytime);
7158
7159 ObjectGuid guid = m_caster->GetGUID();
7160
7161 WorldPacket data(SMSG_SPELL_DELAYED, 8 + 4);
7162 data.WriteGuidMask(guid, 6, 7, 2, 0, 4, 3, 1, 5);
7163
7164 data.WriteGuidBytes(guid, 2, 6, 1, 7, 0, 5, 3);
7165 data << uint32(delaytime);
7166 data.WriteGuidBytes(guid, 4);
7167 m_caster->SendMessageToSet(&data, true);
7168}
7169
7171{
7172 if (!m_caster || m_caster->GetTypeId() != TypeID::TYPEID_PLAYER || getState() != SPELL_STATE_CASTING)
7173 return;
7174
7175 if (isDelayableNoMore()) // Spells may only be delayed twice
7176 return;
7177
7178 //check pushback reduce
7179 int32 delaytime = CalculatePct(m_spellInfo->GetDuration(), 25); // channeling delay is normally 25% of its time per hit
7180 int32 delayReduce = 100; // must be initialized to 100 for percent modifiers
7181 m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_NOT_LOSE_CASTING_TIME, delayReduce, this);
7182 delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100;
7183 if (delayReduce >= 100)
7184 return;
7185
7186 AddPct(delaytime, -delayReduce);
7187
7188 if (m_timer <= delaytime)
7189 {
7190 delaytime = m_timer;
7191 m_timer = 0;
7192 }
7193 else
7194 m_timer -= delaytime;
7195
7196 SF_LOG_DEBUG("spells", "Spell %u partially interrupted for %i ms, new duration: %u ms", m_spellInfo->Id, delaytime, m_timer);
7197
7198 for (std::list<TargetInfo>::const_iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
7199 if ((*ihit).missCondition == SPELL_MISS_NONE)
7200 if (Unit* unit = (m_caster->GetGUID() == ihit->targetGUID) ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID))
7201 unit->DelayOwnedAuras(m_spellInfo->Id, m_originalCasterGUID, delaytime);
7202
7203 // partially interrupt persistent area auras
7204 if (DynamicObject* dynObj = m_caster->GetDynObject(m_spellInfo->Id))
7205 dynObj->Delay(delaytime);
7206
7208}
7209
7211{
7212 if (m_originalCasterGUID == m_caster->GetGUID())
7214 else
7215 {
7217 if (m_originalCaster && !m_originalCaster->IsInWorld())
7218 m_originalCaster = NULL;
7219 }
7220
7221 if (m_castItemGUID && m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
7222 m_CastItem = m_caster->ToPlayer()->GetItemByGuid(m_castItemGUID);
7223
7224 m_targets.Update(m_caster);
7225
7226 // further actions done only for dest targets
7227 if (!m_targets.HasDst())
7228 return;
7229
7230 // cache last transport
7231 WorldObject* transport = NULL;
7232
7233 // update effect destinations (in case of moved transport dest target)
7234 for (uint8 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex)
7235 {
7236 SpellDestination& dest = m_destTargets[effIndex];
7237 if (!dest._transportGUID)
7238 continue;
7239
7240 if (!transport || transport->GetGUID() != dest._transportGUID)
7242
7243 if (transport)
7244 {
7245 dest._position.Relocate(transport);
7247 }
7248 }
7249}
7250
7252{
7254 return (CURRENT_MELEE_SPELL);
7255 else if (IsAutoRepeat())
7256 return (CURRENT_AUTOREPEAT_SPELL);
7257 else if (m_spellInfo->IsChanneled())
7258 return (CURRENT_CHANNELED_SPELL);
7259 else
7260 return (CURRENT_GENERIC_SPELL);
7261}
7262
7263bool Spell::CheckEffectTarget(Unit const* target, uint32 eff) const
7264{
7265 switch (m_spellInfo->Effects[eff].ApplyAuraName)
7266 {
7271 if (target->GetTypeId() == TypeID::TYPEID_UNIT && target->IsVehicle())
7272 return false;
7273 if (target->IsMounted())
7274 return false;
7275 if (target->GetCharmerGUID())
7276 return false;
7277 if (int32 damage = CalculateDamage(eff, target))
7278 if ((int32)target->getLevel() > damage)
7279 return false;
7280 break;
7281 default:
7282 break;
7283 }
7284
7286 return true;
7287
7289 //Check targets for LOS visibility (except spells without range limitations)
7290 switch (m_spellInfo->Effects[eff].Effect)
7291 {
7293 // player far away, maybe his corpse near?
7294 if (target != m_caster && !target->IsWithinLOSInMap(m_caster))
7295 {
7296 if (!m_targets.GetCorpseTargetGUID())
7297 return false;
7298
7299 Corpse* corpse = ObjectAccessor::GetCorpse(*m_caster, m_targets.GetCorpseTargetGUID());
7300 if (!corpse)
7301 return false;
7302
7303 if (target->GetGUID() != corpse->GetOwnerGUID())
7304 return false;
7305
7306 if (!corpse->IsWithinLOSInMap(m_caster))
7307 return false;
7308 }
7309
7310 // all ok by some way or another, skip normal check
7311 break;
7312 default: // normal case
7313 // Get GO cast coordinates if original caster -> GO
7314 WorldObject* caster = NULL;
7316 caster = m_caster->GetMap()->GetGameObject(m_originalCasterGUID);
7317 if (!caster)
7318 caster = m_caster;
7319 if (target != m_caster && !target->IsWithinLOSInMap(caster))
7320 return false;
7321 break;
7322 }
7323
7324 return true;
7325}
7326
7328{
7329 return m_spellInfo->Attributes & SPELL_ATTR0_ON_NEXT_SWING;
7330}
7331
7333{
7335 return !IsTriggered() && (m_spellInfo->InterruptFlags & SPELL_INTERRUPT_FLAG_INTERRUPT);
7336}
7337
7339{
7340 return m_spellInfo->SpellVisual[0] || m_spellInfo->SpellVisual[1] || m_spellInfo->IsChanneled() ||
7341 (m_spellInfo->AttributesEx8 & SPELL_ATTR8_AURA_SEND_AMOUNT) || m_spellInfo->Speed > 0.0f || (!m_triggeredByAuraSpell && !IsTriggered());
7342}
7343
7345{
7346 for (std::list<TargetInfo>::const_iterator itr = m_UniqueTargetInfo.begin(); itr != m_UniqueTargetInfo.end(); ++itr)
7347 if (itr->effectMask & (1 << effect))
7348 return true;
7349
7350 for (std::list<GOTargetInfo>::const_iterator itr = m_UniqueGOTargetInfo.begin(); itr != m_UniqueGOTargetInfo.end(); ++itr)
7351 if (itr->effectMask & (1 << effect))
7352 return true;
7353
7354 for (std::list<ItemTargetInfo>::const_iterator itr = m_UniqueItemInfo.begin(); itr != m_UniqueItemInfo.end(); ++itr)
7355 if (itr->effectMask & (1 << effect))
7356 return true;
7357
7358 return false;
7359}
7360
7362{
7363 m_Spell = spell;
7364}
7365
7367{
7368 if (m_Spell->getState() != SPELL_STATE_FINISHED)
7369 m_Spell->cancel();
7370
7371 if (m_Spell->IsDeletable())
7372 {
7373 delete m_Spell;
7374 }
7375 else
7376 {
7377 SF_LOG_ERROR("spells", "~SpellEvent: %s %u tried to delete non-deletable spell %u. Was not deleted, causes memory leak.",
7378 (m_Spell->GetCaster()->GetTypeId() == TypeID::TYPEID_PLAYER ? "Player" : "Creature"), m_Spell->GetCaster()->GetGUIDLow(), m_Spell->m_spellInfo->Id);
7379 ASSERT(false);
7380 }
7381}
7382
7384{
7385 // update spell if it is not finished
7386 if (m_Spell->getState() != SPELL_STATE_FINISHED)
7387 m_Spell->update(p_time);
7388
7389 // check spell state to process
7390 switch (m_Spell->getState())
7391 {
7393 {
7394 // spell was finished, check deletable state
7395 if (m_Spell->IsDeletable())
7396 {
7397 // check, if we do have unfinished triggered spells
7398 return true; // spell is deletable, finish event
7399 }
7400 // event will be re-added automatically at the end of routine)
7401 } break;
7402
7404 {
7405 // first, check, if we have just started
7406 if (m_Spell->GetDelayStart() != 0)
7407 {
7408 // no, we aren't, do the typical update
7409 // check, if we have channeled spell on our hands
7410 /*
7411 if (m_Spell->m_spellInfo->IsChanneled())
7412 {
7413 // evented channeled spell is processed separately, casted once after delay, and not destroyed till finish
7414 // check, if we have casting anything else except this channeled spell and autorepeat
7415 if (m_Spell->GetCaster()->IsNonMeleeSpellCasted(false, true, true))
7416 {
7417 // another non-melee non-delayed spell is casted now, abort
7418 m_Spell->cancel();
7419 }
7420 else
7421 {
7422 // Set last not triggered spell for apply spellmods
7423 ((Player*)m_Spell->GetCaster())->SetSpellModTakingSpell(m_Spell, true);
7424 // do the action (pass spell to channeling state)
7425 m_Spell->handle_immediate();
7426
7427 // And remove after effect handling
7428 ((Player*)m_Spell->GetCaster())->SetSpellModTakingSpell(m_Spell, false);
7429 }
7430 // event will be re-added automatically at the end of routine)
7431 }
7432 else
7433 */
7434 {
7435 // run the spell handler and think about what we can do next
7436 uint64 t_offset = e_time - m_Spell->GetDelayStart();
7437 uint64 n_offset = m_Spell->handle_delayed(t_offset);
7438 if (n_offset)
7439 {
7440 // re-add us to the queue
7441 m_Spell->GetCaster()->m_Events.AddEvent(this, m_Spell->GetDelayStart() + n_offset, false);
7442 return false; // event not complete
7443 }
7444 // event complete
7445 // finish update event will be re-added automatically at the end of routine)
7446 }
7447 }
7448 else
7449 {
7450 // delaying had just started, record the moment
7451 m_Spell->SetDelayStart(e_time);
7452 // re-plan the event for the delay moment
7453 m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + m_Spell->GetDelayMoment(), false);
7454 return false; // event not complete
7455 }
7456 } break;
7457
7458 default:
7459 {
7460 // all other states
7461 // event will be re-added automatically at the end of routine)
7462 } break;
7463 }
7464
7465 // spell processing not complete, plan event on the next update interval
7466 m_Spell->GetCaster()->m_Events.AddEvent(this, e_time + 1, false);
7467 return false; // event not complete
7468}
7469
7471{
7472 // oops, the spell we try to do is aborted
7473 if (m_Spell->getState() != SPELL_STATE_FINISHED)
7474 m_Spell->cancel();
7475}
7476
7478{
7479 return m_Spell->IsDeletable();
7480}
7481
7482bool Spell::IsValidDeadOrAliveTarget(Unit const* target) const
7483{
7484 if (target->IsAlive())
7485 return !m_spellInfo->IsRequiringDeadTarget();
7486 if (m_spellInfo->IsAllowingDeadTarget())
7487 return true;
7488 return false;
7489}
7490
7492{
7493 // handle effects with SPELL_EFFECT_HANDLE_LAUNCH mode
7494 for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
7495 {
7496 // don't do anything for empty effect
7497 if (!m_spellInfo->Effects[i].IsEffect())
7498 continue;
7499
7500 HandleEffects(NULL, NULL, NULL, i, SPELL_EFFECT_HANDLE_LAUNCH);
7501 }
7502
7503 float multiplier[MAX_SPELL_EFFECTS];
7504 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
7505 if (m_applyMultiplierMask & (1 << i))
7506 multiplier[i] = m_spellInfo->Effects[i].CalcDamageMultiplier(m_originalCaster, this);
7507
7508 bool usesAmmo = m_spellInfo->AttributesCu & SPELL_ATTR0_CU_DIRECT_DAMAGE;
7509
7510 for (std::list<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit)
7511 {
7512 TargetInfo& target = *ihit;
7513
7514 uint32 mask = target.effectMask;
7515 if (!mask)
7516 continue;
7517
7518 // do not consume ammo anymore for Hunter's volley spell
7519 if (IsTriggered() && m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && m_spellInfo->IsTargetingArea())
7520 usesAmmo = false;
7521
7522 if (usesAmmo)
7523 {
7524 bool ammoTaken = false;
7525 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; i++)
7526 {
7527 if (!(mask & 1 << i))
7528 continue;
7529 switch (m_spellInfo->Effects[i].Effect)
7530 {
7536 ammoTaken = true;
7537 //TakeAmmo();
7538 }
7539 if (ammoTaken)
7540 break;
7541 }
7542 }
7543 DoAllEffectOnLaunchTarget(target, multiplier);
7544 }
7545}
7546
7547void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier)
7548{
7549 Unit* unit = NULL;
7550 // In case spell hit target, do all effect on that target
7551 if (targetInfo.missCondition == SPELL_MISS_NONE)
7552 unit = m_caster->GetGUID() == targetInfo.targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, targetInfo.targetGUID);
7553 // In case spell reflect from target, do all effect on caster (if hit)
7554 else if (targetInfo.missCondition == SPELL_MISS_REFLECT && targetInfo.reflectResult == SPELL_MISS_NONE)
7555 unit = m_caster;
7556 if (!unit)
7557 return;
7558
7559 for (uint32 i = 0; i < MAX_SPELL_EFFECTS; ++i)
7560 {
7561 if (targetInfo.effectMask & (1 << i))
7562 {
7563 m_damage = 0;
7564 m_healing = 0;
7565
7567
7568 if (m_damage > 0)
7569 {
7570 if (m_spellInfo->Effects[i].IsTargetingArea())
7571 {
7573 if (m_caster->GetTypeId() == TypeID::TYPEID_UNIT)
7575
7576 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
7577 {
7578 uint32 targetAmount = m_UniqueTargetInfo.size();
7579 if (targetAmount > 10)
7580 m_damage = m_damage * 10 / targetAmount;
7581 }
7582 }
7583 }
7584
7585 if (m_applyMultiplierMask & (1 << i))
7586 {
7588 m_damageMultipliers[i] *= multiplier[i];
7589 }
7590 targetInfo.damage += m_damage;
7591 }
7592 }
7593
7594 targetInfo.crit = m_caster->isSpellCrit(unit, m_spellInfo, m_spellSchoolMask, m_attackType);
7595}
7596
7597SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& skillId, int32& reqSkillValue, int32& skillValue)
7598{
7599 if (!lockId) // possible case for GO and maybe for items.
7601
7602 // Get LockInfo
7603 LockEntry const* lockInfo = sLockStore.LookupEntry(lockId);
7604
7605 if (!lockInfo)
7607
7608 bool reqKey = false; // some locks not have reqs
7609
7610 for (int j = 0; j < MAX_LOCK_CASE; ++j)
7611 {
7612 switch (lockInfo->Type[j])
7613 {
7614 // check key item (many fit cases can be)
7615 case LOCK_KEY_ITEM:
7616 if (lockInfo->Index[j] && m_CastItem && m_CastItem->GetEntry() == lockInfo->Index[j])
7618 reqKey = true;
7619 break;
7620 // check key skill (only single first fit case can be)
7621 case LOCK_KEY_SKILL:
7622 {
7623 reqKey = true;
7624
7625 // wrong locktype, skip
7626 if (uint32(m_spellInfo->Effects[effIndex].MiscValue) != lockInfo->Index[j])
7627 continue;
7628
7629 skillId = SkillByLockType(LockType(lockInfo->Index[j]));
7630
7631 if (skillId != SKILL_NONE)
7632 {
7633 reqSkillValue = lockInfo->Skill[j];
7634
7635 // castitem check: rogue using skeleton keys. the skill values should not be added in this case.
7636 skillValue = m_CastItem || m_caster->GetTypeId() != TypeID::TYPEID_PLAYER ?
7637 0 : m_caster->ToPlayer()->GetSkillValue(skillId);
7638
7639 // skill bonus provided by casting spell (mostly item spells)
7640 // add the effect base points modifier from the spell casted (cheat lock / skeleton key etc.)
7641 if (m_spellInfo->Effects[effIndex].TargetA.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET || m_spellInfo->Effects[effIndex].TargetB.GetTarget() == TARGET_GAMEOBJECT_ITEM_TARGET)
7642 skillValue += m_spellInfo->Effects[effIndex].CalcValue();
7643
7644 if (skillValue < reqSkillValue)
7646 }
7647
7649 }
7650 }
7651 }
7652
7653 if (reqKey)
7655
7657}
7658
7660{
7661 switch (mod)
7662 {
7664 m_spellValue->EffectBasePoints[0] = m_spellInfo->Effects[EFFECT_0].CalcBaseValue(value);
7665 break;
7667 m_spellValue->EffectBasePoints[1] = m_spellInfo->Effects[EFFECT_1].CalcBaseValue(value);
7668 break;
7670 m_spellValue->EffectBasePoints[2] = m_spellInfo->Effects[EFFECT_2].CalcBaseValue(value);
7671 break;
7673 m_spellValue->RadiusMod = (float)value / 10000;
7674 break;
7676 m_spellValue->MaxAffectedTargets = (uint32)value;
7677 break;
7679 m_spellValue->AuraStackAmount = uint8(value);
7680 break;
7681 }
7682}
7683
7688
7693
7695{
7696 ASSERT(m_effectExecuteData.empty());
7697}
7698
7700{
7701 sScriptMgr->CreateSpellScripts(m_spellInfo->Id, m_loadedScripts);
7702 for (std::list<SpellScript*>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end();)
7703 {
7704 if (!(*itr)->_Load(this))
7705 {
7706 std::list<SpellScript*>::iterator bitr = itr;
7707 ++itr;
7708 delete (*bitr);
7709 m_loadedScripts.erase(bitr);
7710 continue;
7711 }
7712 SF_LOG_DEBUG("spells", "Spell::LoadScripts: Script `%s` for spell `%u` is loaded now", (*itr)->_GetScriptName()->c_str(), m_spellInfo->Id);
7713 (*itr)->Register();
7714 ++itr;
7715 }
7716}
7717
7719{
7720 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7721 {
7722 (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_CAST);
7723 std::list<SpellScript::CastHandler>::iterator hookItrEnd = (*scritr)->BeforeCast.end(), hookItr = (*scritr)->BeforeCast.begin();
7724 for (; hookItr != hookItrEnd; ++hookItr)
7725 (*hookItr).Call(*scritr);
7726
7727 (*scritr)->_FinishScriptCall();
7728 }
7729}
7730
7732{
7733 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7734 {
7735 (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_ON_CAST);
7736 std::list<SpellScript::CastHandler>::iterator hookItrEnd = (*scritr)->OnCast.end(), hookItr = (*scritr)->OnCast.begin();
7737 for (; hookItr != hookItrEnd; ++hookItr)
7738 (*hookItr).Call(*scritr);
7739
7740 (*scritr)->_FinishScriptCall();
7741 }
7742}
7743
7745{
7746 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7747 {
7748 (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_AFTER_CAST);
7749 std::list<SpellScript::CastHandler>::iterator hookItrEnd = (*scritr)->AfterCast.end(), hookItr = (*scritr)->AfterCast.begin();
7750 for (; hookItr != hookItrEnd; ++hookItr)
7751 (*hookItr).Call(*scritr);
7752
7753 (*scritr)->_FinishScriptCall();
7754 }
7755}
7756
7758{
7760 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7761 {
7762 (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_CHECK_CAST);
7763 std::list<SpellScript::CheckCastHandler>::iterator hookItrEnd = (*scritr)->OnCheckCast.end(), hookItr = (*scritr)->OnCheckCast.begin();
7764 for (; hookItr != hookItrEnd; ++hookItr)
7765 {
7766 SpellCastResult tempResult = (*hookItr).Call(*scritr);
7767 if (retVal == SpellCastResult::SPELL_CAST_OK)
7768 retVal = tempResult;
7769 }
7770
7771 (*scritr)->_FinishScriptCall();
7772 }
7773 return retVal;
7774}
7775
7777{
7778 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7779 (*scritr)->_InitHit();
7780}
7781
7783{
7784 // execute script effect handler hooks and check if effects was prevented
7785 bool preventDefault = false;
7786 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7787 {
7788 std::list<SpellScript::EffectHandler>::iterator effItr, effEndItr;
7789 SpellScriptHookType hookType;
7790 switch (mode)
7791 {
7793 effItr = (*scritr)->OnEffectLaunch.begin();
7794 effEndItr = (*scritr)->OnEffectLaunch.end();
7796 break;
7798 effItr = (*scritr)->OnEffectLaunchTarget.begin();
7799 effEndItr = (*scritr)->OnEffectLaunchTarget.end();
7801 break;
7803 effItr = (*scritr)->OnEffectHit.begin();
7804 effEndItr = (*scritr)->OnEffectHit.end();
7806 break;
7808 effItr = (*scritr)->OnEffectHitTarget.begin();
7809 effEndItr = (*scritr)->OnEffectHitTarget.end();
7811 break;
7812 default:
7813 ASSERT(false);
7814 return false;
7815 }
7816 (*scritr)->_PrepareScriptCall(hookType);
7817 for (; effItr != effEndItr; ++effItr)
7818 // effect execution can be prevented
7819 if (!(*scritr)->_IsEffectPrevented(effIndex) && (*effItr).IsEffectAffected(m_spellInfo, effIndex))
7820 (*effItr).Call(*scritr, effIndex);
7821
7822 if (!preventDefault)
7823 preventDefault = (*scritr)->_IsDefaultEffectPrevented(effIndex);
7824
7825 (*scritr)->_FinishScriptCall();
7826 }
7827 return preventDefault;
7828}
7829
7831{
7832 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7833 {
7834 (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_BEFORE_HIT);
7835 std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->BeforeHit.end(), hookItr = (*scritr)->BeforeHit.begin();
7836 for (; hookItr != hookItrEnd; ++hookItr)
7837 (*hookItr).Call(*scritr);
7838
7839 (*scritr)->_FinishScriptCall();
7840 }
7841}
7842
7844{
7845 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7846 {
7847 (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_HIT);
7848 std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->OnHit.end(), hookItr = (*scritr)->OnHit.begin();
7849 for (; hookItr != hookItrEnd; ++hookItr)
7850 (*hookItr).Call(*scritr);
7851
7852 (*scritr)->_FinishScriptCall();
7853 }
7854}
7855
7857{
7858 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7859 {
7860 (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_AFTER_HIT);
7861 std::list<SpellScript::HitHandler>::iterator hookItrEnd = (*scritr)->AfterHit.end(), hookItr = (*scritr)->AfterHit.begin();
7862 for (; hookItr != hookItrEnd; ++hookItr)
7863 (*hookItr).Call(*scritr);
7864
7865 (*scritr)->_FinishScriptCall();
7866 }
7867}
7868
7869void Spell::CallScriptObjectAreaTargetSelectHandlers(std::list<WorldObject*>& targets, SpellEffIndex effIndex)
7870{
7871 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7872 {
7873 (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT);
7874 std::list<SpellScript::ObjectAreaTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnObjectAreaTargetSelect.end(), hookItr = (*scritr)->OnObjectAreaTargetSelect.begin();
7875 for (; hookItr != hookItrEnd; ++hookItr)
7876 if ((*hookItr).IsEffectAffected(m_spellInfo, effIndex))
7877 (*hookItr).Call(*scritr, targets);
7878
7879 (*scritr)->_FinishScriptCall();
7880 }
7881}
7882
7884{
7885 for (std::list<SpellScript*>::iterator scritr = m_loadedScripts.begin(); scritr != m_loadedScripts.end(); ++scritr)
7886 {
7887 (*scritr)->_PrepareScriptCall(SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT);
7888 std::list<SpellScript::ObjectTargetSelectHandler>::iterator hookItrEnd = (*scritr)->OnObjectTargetSelect.end(), hookItr = (*scritr)->OnObjectTargetSelect.begin();
7889 for (; hookItr != hookItrEnd; ++hookItr)
7890 if ((*hookItr).IsEffectAffected(m_spellInfo, effIndex))
7891 (*hookItr).Call(*scritr, target);
7892
7893 (*scritr)->_FinishScriptCall();
7894 }
7895}
7896
7898{
7899 // Skip if there are not any script
7900 if (!m_loadedScripts.size())
7901 return true;
7902
7903 for (std::list<SpellScript*>::iterator itr = m_loadedScripts.begin(); itr != m_loadedScripts.end(); ++itr)
7904 {
7905 std::list<SpellScript::ObjectTargetSelectHandler>::iterator targetSelectHookEnd = (*itr)->OnObjectTargetSelect.end(), targetSelectHookItr = (*itr)->OnObjectTargetSelect.begin();
7906 for (; targetSelectHookItr != targetSelectHookEnd; ++targetSelectHookItr)
7907 if (((*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) ||
7908 (!(*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && (*targetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)))
7909 return false;
7910
7911 std::list<SpellScript::ObjectAreaTargetSelectHandler>::iterator areaTargetSelectHookEnd = (*itr)->OnObjectAreaTargetSelect.end(), areaTargetSelectHookItr = (*itr)->OnObjectAreaTargetSelect.begin();
7912 for (; areaTargetSelectHookItr != areaTargetSelectHookEnd; ++areaTargetSelectHookItr)
7913 if (((*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && !(*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)) ||
7914 (!(*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndex) && (*areaTargetSelectHookItr).IsEffectAffected(m_spellInfo, effIndexToCheck)))
7915 return false;
7916 }
7917 return true;
7918}
7919
7920bool Spell::CanExecuteTriggersOnHit(uint32 effMask, SpellInfo const* triggeredByAura) const
7921{
7922 bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER));
7923 // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a casted spell with TARGET_UNIT_CASTER
7924 for (uint8 i = 0; i < MAX_SPELL_EFFECTS; ++i)
7925 {
7926 if ((effMask & (1 << i)) && (!only_on_caster || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CASTER)))
7927 return true;
7928 }
7929 return false;
7930}
7931
7933{
7934 // handle SPELL_AURA_ADD_TARGET_TRIGGER auras:
7935 // save auras which were present on spell caster on cast, to prevent triggered auras from affecting caster
7936 // and to correctly calculate proc chance when combopoints are present
7937 Unit::AuraEffectList const& targetTriggers = m_caster->GetAuraEffectsByType(SPELL_AURA_ADD_TARGET_TRIGGER);
7938 for (Unit::AuraEffectList::const_iterator i = targetTriggers.begin(); i != targetTriggers.end(); ++i)
7939 {
7940 if (!(*i)->IsAffectingSpell(m_spellInfo))
7941 continue;
7942 SpellInfo const* auraSpellInfo = (*i)->GetSpellInfo();
7943 uint32 auraSpellIdx = (*i)->GetEffIndex();
7944 if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(auraSpellInfo->Effects[auraSpellIdx].TriggerSpell))
7945 {
7946 // calculate the chance using spell base amount, because aura amount is not updated on combo-points change
7947 // this possibly needs fixing
7948 int32 auraBaseAmount = (*i)->GetBaseAmount();
7949 // proc chance is stored in effect amount
7950 int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount);
7951 // build trigger and add to the list
7952 HitTriggerSpell spellTriggerInfo;
7953 spellTriggerInfo.triggeredSpell = spellInfo;
7954 spellTriggerInfo.triggeredByAura = auraSpellInfo;
7955 spellTriggerInfo.chance = chance * (*i)->GetBase()->GetStackAmount();
7956 m_hitTriggerSpells.push_back(spellTriggerInfo);
7957 }
7958 }
7959}
7960
7961// Global cooldowns management
7963{
7964 MIN_GCD = 1000,
7965 MAX_GCD = 1500
7966};
7967
7969{
7970 // Only player or controlled units have global cooldown
7971 if (m_caster->GetCharmInfo())
7972 return m_caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
7973 else if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
7974 return m_caster->ToPlayer()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
7975 else
7976 return false;
7977}
7978
7980{
7981 int32 gcd = m_spellInfo->StartRecoveryTime;
7982 if (!gcd)
7983 return;
7984
7985 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
7986 if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN))
7987 return;
7988
7989 // Global cooldown can't leave range 1..1.5 secs
7990 // There are some spells (mostly not casted directly by player) that have < 1 sec and > 1.5 sec global cooldowns
7991 // but as tests show are not affected by any spell mods.
7992 if (m_spellInfo->StartRecoveryTime >= MIN_GCD && m_spellInfo->StartRecoveryTime <= MAX_GCD)
7993 {
7994 // gcd modifier auras are applied only to own spells and only players have such mods
7995 if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
7996 m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_GLOBAL_COOLDOWN, gcd, this);
7997
7998 // Apply haste rating
7999 gcd = int32(float(gcd) * m_caster->GetFloatValue(UNIT_FIELD_MOD_CASTING_SPEED));
8000 if (gcd < MIN_GCD)
8001 gcd = MIN_GCD;
8002 else if (gcd > MAX_GCD)
8003 gcd = MAX_GCD;
8004 }
8005
8006 // Only players or controlled units have global cooldown
8007 if (m_caster->GetCharmInfo())
8008 m_caster->GetCharmInfo()->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
8009 else if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
8010 m_caster->ToPlayer()->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
8011}
8012
8014{
8015 if (!m_spellInfo->StartRecoveryTime)
8016 return;
8017
8018 // Cancel global cooldown when interrupting current cast
8019 if (m_caster->GetCurrentSpell(CURRENT_GENERIC_SPELL) != this)
8020 return;
8021
8022 // Only players or controlled units have global cooldown
8023 if (m_caster->GetCharmInfo())
8024 m_caster->GetCharmInfo()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
8025 else if (m_caster->GetTypeId() == TypeID::TYPEID_PLAYER)
8026 m_caster->ToPlayer()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
8027}
8028
8029namespace Skyfire
8030{
8031
8033 SpellTargetCheckTypes selectionType, ConditionList* condList) : _caster(caster), _referer(referer), _spellInfo(spellInfo),
8034 _targetSelectionType(selectionType), _condList(condList)
8035 {
8036 if (condList)
8037 _condSrcInfo = new ConditionSourceInfo(NULL, caster);
8038 else
8039 _condSrcInfo = NULL;
8040 }
8041
8047
8049 {
8050 if (_spellInfo->CheckTarget(_caster, target, true) != SpellCastResult::SPELL_CAST_OK)
8051 return false;
8052 Unit* unitTarget = target->ToUnit();
8053 if (Corpse* corpseTarget = target->ToCorpse())
8054 {
8055 // use ofter for party/assistance checks
8056 if (Player* owner = ObjectAccessor::FindPlayer(corpseTarget->GetOwnerGUID()))
8057 unitTarget = owner;
8058 else
8059 return false;
8060 }
8061 if (unitTarget)
8062 {
8063 switch (_targetSelectionType)
8064 {
8065 case TARGET_CHECK_ENEMY:
8066 if (unitTarget->IsTotem())
8067 return false;
8068 if (!_caster->_IsValidAttackTarget(unitTarget, _spellInfo))
8069 return false;
8070 break;
8071 case TARGET_CHECK_ALLY:
8072 if (unitTarget->IsTotem())
8073 return false;
8074 if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
8075 return false;
8076 break;
8077 case TARGET_CHECK_PARTY:
8078 if (unitTarget->IsTotem())
8079 return false;
8080 if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
8081 return false;
8082 if (!_referer->IsInPartyWith(unitTarget))
8083 return false;
8084 break;
8086 if (_referer->getClass() != unitTarget->getClass())
8087 return false;
8088 // nobreak;
8089 case TARGET_CHECK_RAID:
8090 if (unitTarget->IsTotem())
8091 return false;
8092 if (!_caster->_IsValidAssistTarget(unitTarget, _spellInfo))
8093 return false;
8094 if (!_referer->IsInRaidWith(unitTarget))
8095 return false;
8096 break;
8097 default:
8098 break;
8099 }
8100 }
8101 if (!_condSrcInfo)
8102 return true;
8103 _condSrcInfo->mConditionTargets[0] = target;
8104 return sConditionMgr->IsObjectMeetToConditions(*_condSrcInfo, *_condList);
8105 }
8106
8108 SpellTargetCheckTypes selectionType, ConditionList* condList)
8109 : WorldObjectSpellTargetCheck(caster, caster, spellInfo, selectionType, condList), _range(range), _position(caster) { }
8110
8112 {
8113 float dist = target->GetDistance(*_position);
8114 if (dist < _range && WorldObjectSpellTargetCheck::operator ()(target))
8115 {
8116 _range = dist;
8117 return true;
8118 }
8119 return false;
8120 }
8121
8123 Unit* referer, SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList)
8124 : WorldObjectSpellTargetCheck(caster, referer, spellInfo, selectionType, condList), _range(range), _position(position) { }
8125
8127 {
8128 if (!target->IsWithinDist3d(_position, _range) && !(target->ToGameObject() && target->ToGameObject()->IsInRange(_position->GetPositionX(), _position->GetPositionY(), _position->GetPositionZ(), _range)))
8129 return false;
8131 }
8132
8134 SpellInfo const* spellInfo, SpellTargetCheckTypes selectionType, ConditionList* condList)
8135 : WorldObjectSpellAreaTargetCheck(range, caster, caster, caster, spellInfo, selectionType, condList), _coneAngle(coneAngle) { }
8136
8138 {
8139 if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_BACK)
8140 {
8141 if (!_caster->isInBack(target, _coneAngle))
8142 return false;
8143 }
8144 else if (_spellInfo->AttributesCu & SPELL_ATTR0_CU_CONE_LINE)
8145 {
8146 if (!_caster->HasInLine(target, _caster->GetObjectSize()))
8147 return false;
8148 }
8149 else
8150 {
8151 if (!_caster->isInFront(target, _coneAngle))
8152 return false;
8153 }
8155 }
8156
8157 WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo)
8158 : WorldObjectSpellAreaTargetCheck(range, position, caster, caster, spellInfo, TARGET_CHECK_DEFAULT, NULL) { }
8159
8161 {
8162 // return all targets on missile trajectory (0 - size of a missile)
8163 if (!_caster->HasInLine(target, 0))
8164 return false;
8166 }
8167
8168} //namespace Skyfire
#define sBattlefieldMgr
@ STATUS_WAIT_LEAVE
@ STATUS_IN_PROGRESS
@ IN_MILLISECONDS
Definition Common.h:125
@ MINUTE
Definition Common.h:119
#define M_PI
Definition Common.h:192
#define sConditionMgr
@ CONDITION_SOURCE_TYPE_SPELL
std::list< Condition * > ConditionList
@ CREATURE_FLAG_EXTRA_ALL_DIMINISH
Definition Creature.h:43
#define MAX_SPELL_REAGENTS
@ ACHIEVEMENT_TIMED_TYPE_SPELL_CASTER
Definition DBCEnums.h:160
@ ACHIEVEMENT_TIMED_TYPE_ITEM
Definition DBCEnums.h:163
@ ACHIEVEMENT_TIMED_TYPE_SPELL_TARGET
Definition DBCEnums.h:161
@ ITEM_ENCHANTMENT_TYPE_USE_SPELL
Definition DBCEnums.h:416
@ ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2
Definition DBCEnums.h:232
@ ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM
Definition DBCEnums.h:206
@ ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET
Definition DBCEnums.h:193
@ ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL
Definition DBCEnums.h:194
@ ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2
Definition DBCEnums.h:265
DifficultyID
Definition DBCEnums.h:330
@ AREA_FLAG_NO_FLY_ZONE
Definition DBCEnums.h:325
DBCStorage< SpellItemEnchantmentEntry > sSpellItemEnchantmentStore(SpellItemEnchantmentfmt)
DBCStorage< SummonPropertiesEntry > sSummonPropertiesStore(SummonPropertiesfmt)
DBCStorage< LockEntry > sLockStore(LockEntryfmt)
DBCStorage< SpellRuneCostEntry > sSpellRuneCostStore(SpellRuneCostfmt)
DBCStorage< SpellPowerEntry > sSpellPowerStore(SpellPowerEntryfmt)
DBCStorage< GtNPCManaCostScalerEntry > sGtNPCManaCostScalerStore(GtNPCManaCostScalerfmt)
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
DBCStorage< GlyphPropertiesEntry > sGlyphPropertiesStore(GlyphPropertiesfmt)
AreaTableEntry const * GetAreaEntryByAreaID(uint32 area_id)
#define MAX_LOCK_CASE
#define MAX_SPELL_EFFECTS
#define MAX_ITEM_ENCHANTMENT_EFFECTS
std::int32_t int32
Definition Define.h:73
#define UI64FMTD
Definition Define.h:64
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::int8_t int8
Definition Define.h:75
std::uint64_t uint64
Definition Define.h:76
@ SPELL_DISABLE_LOS
Definition DisableMgr.h:33
@ DISABLE_TYPE_SPELL
Definition DisableMgr.h:15
#define ASSERT
Definition Errors.h:29
CoordPair< TOTAL_NUMBER_OF_CELLS_PER_MAP > CellCoord
@ GRID_MAP_TYPE_MASK_PLAYER
Definition GridDefines.h:63
@ GRID_MAP_TYPE_MASK_CREATURE
Definition GridDefines.h:60
@ GRID_MAP_TYPE_MASK_ALL
Definition GridDefines.h:65
@ GRID_MAP_TYPE_MASK_GAMEOBJECT
Definition GridDefines.h:62
@ GRID_MAP_TYPE_MASK_CORPSE
Definition GridDefines.h:59
#define MAX_ITEM_SPELLS
Definition Item.h:197
@ ENCHANTMENT_CAN_SOULBOUND
Definition Item.h:183
InventoryResult
Definition Item.h:27
@ EQUIP_ERR_OK
Definition Item.h:28
@ ITEM_CHANGED
Definition Item.h:192
@ ITEM_SUBCLASS_WEAPON_CROSSBOW
@ ITEM_SUBCLASS_WEAPON_GUN
@ ITEM_SUBCLASS_WEAPON_BOW
@ ITEM_SUBCLASS_WEAPON_WAND
@ ITEM_SUBCLASS_WEAPON_THROWN
@ ITEM_SPELLTRIGGER_ON_USE
@ ITEM_SPELLTRIGGER_ON_NO_DELAY_USE
@ ITEM_PROTO_FLAG_TRIGGERED_CAST
@ ITEM_PROTO_FLAG_MILLABLE
@ ITEM_PROTO_FLAG_PROSPECTABLE
#define MAX_ITEM_PROTO_SPELLS
@ ITEM_CLASS_ARMOR
@ ITEM_CLASS_WEAPON
@ ITEM_CLASS_CONSUMABLE
#define SF_LOG_DEBUG(filterType__,...)
Definition Log.h:134
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
LootStore LootTemplates_Milling("milling_loot_template", "item entry (herb)", true)
LootStore LootTemplates_Prospecting("prospecting_loot_template", "item entry (ore)", true)
@ TYPEID_PLAYER
Definition Object.h:55
@ TYPEID_UNIT
Definition Object.h:54
@ TYPEID_CORPSE
Definition Object.h:58
#define CONTACT_DISTANCE
Definition Object.h:20
#define DEFAULT_WORLD_OBJECT_SIZE
Definition Object.h:29
bool IS_GAMEOBJECT_GUID(uint64 guid)
@ HIGHGUID_PET
@ HIGHGUID_GAMEOBJECT
@ HIGHGUID_TRANSPORT
@ HIGHGUID_CORPSE
@ HIGHGUID_PLAYER
@ HIGHGUID_MO_TRANSPORT
@ HIGHGUID_UNIT
@ HIGHGUID_VEHICLE
uint32 GUID_HIPART(uint64 guid)
#define sObjectMgr
Definition ObjectMgr.h:1617
@ PATHFIND_NOPATH
@ PATHFIND_SHORT
#define PET_FOLLOW_DIST
Definition PetDefines.h:57
std::vector< ItemPosCount > ItemPosCountVec
Definition Player.h:777
RuneType
Definition Player.h:485
@ RUNE_FROST
Definition Player.h:488
@ NUM_RUNE_TYPES
Definition Player.h:490
@ RUNE_DEATH
Definition Player.h:489
@ RUNE_UNHOLY
Definition Player.h:487
@ RUNE_BLOOD
Definition Player.h:486
#define MAX_RUNES
Definition Player.h:476
@ PLAYER_FLAGS_ALLOW_ONLY_ABILITY
Definition Player.h:560
@ RUNE_MISS_COOLDOWN
Definition Player.h:481
@ CHEAT_COOLDOWN
Definition Player.h:990
@ CHEAT_POWER
Definition Player.h:991
@ CHEAT_CASTTIME
Definition Player.h:989
TradeSlots
Definition Player.h:780
@ TRADE_SLOT_NONTRADED
Definition Player.h:783
#define sScriptMgr
Definition ScriptMgr.h:764
@ GAMEOBJECT_TYPE_TRAP
@ GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING
SpellEffIndex
@ EFFECT_1
@ EFFECT_0
@ EFFECT_2
@ SPELL_ATTR0_ON_NEXT_SWING
@ SPELL_ATTR0_STOP_ATTACK_TARGET
@ SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY
@ SPELL_ATTR0_PASSIVE
@ SPELL_ATTR0_CASTABLE_WHILE_DEAD
@ SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION
@ SPELL_ATTR0_ABILITY
@ SPELL_ATTR0_OUTDOORS_ONLY
@ SPELL_ATTR0_ONLY_STEALTHED
@ SPELL_ATTR0_INDOORS_ONLY
@ SPELL_ATTR0_CASTABLE_WHILE_MOUNTED
Powers
@ MAX_POWERS
@ POWER_RAGE
@ POWER_DEMONIC_FURY
@ POWER_HEALTH
@ POWER_RUNIC_POWER
@ POWER_ENERGY
@ POWER_CHI
@ POWER_RUNES
@ POWER_MANA
@ POWER_HOLY_POWER
SpellEffects
@ SPELL_EFFECT_DUMMY
@ SPELL_EFFECT_LEAP
@ SPELL_EFFECT_POWER_BURN
@ SPELL_EFFECT_SUMMON_PET
@ SPELL_EFFECT_DISENCHANT
@ SPELL_EFFECT_PROSPECTING
@ SPELL_EFFECT_ENCHANT_HELD_ITEM
@ SPELL_EFFECT_ENCHANT_ITEM
@ SPELL_EFFECT_STUCK
@ SPELL_EFFECT_GAMEOBJECT_REPAIR
@ SPELL_EFFECT_SUMMON_RAF_FRIEND
@ SPELL_EFFECT_WEAPON_DAMAGE
@ SPELL_EFFECT_APPLY_GLYPH
@ SPELL_EFFECT_HEAL
@ SPELL_EFFECT_NORMALIZED_WEAPON_DMG
@ SPELL_EFFECT_FEED_PET
@ SPELL_EFFECT_SUMMON_PLAYER
@ SPELL_EFFECT_DISPEL
@ SPELL_EFFECT_MILLING
@ SPELL_EFFECT_TELEPORT_UNITS_FACE_CASTER
@ SPELL_EFFECT_RESURRECT_PET
@ SPELL_EFFECT_CREATE_MANA_GEM
@ SPELL_EFFECT_ADD_EXTRA_ATTACKS
@ SPELL_EFFECT_WEAPON_PERCENT_DAMAGE
@ SPELL_EFFECT_ACTIVATE_RUNE
@ SPELL_EFFECT_CREATE_ITEM_2
@ SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL
@ SPELL_EFFECT_LEAP_BACK
@ SPELL_EFFECT_SUMMON
@ SPELL_EFFECT_ENERGIZE
@ SPELL_EFFECT_BIND
@ SPELL_EFFECT_UNLOCK_GUILD_VAULT_TAB
@ SPELL_EFFECT_POWER_DRAIN
@ SPELL_EFFECT_CHARGE
@ SPELL_EFFECT_RESURRECT_NEW
@ SPELL_EFFECT_SCHOOL_DAMAGE
@ SPELL_EFFECT_TALENT_SPEC_SELECT
@ TOTAL_SPELL_EFFECTS
@ SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE
@ SPELL_EFFECT_GAMEOBJECT_DAMAGE
@ SPELL_EFFECT_LEARN_SPELL
@ SPELL_EFFECT_SKINNING
@ SPELL_EFFECT_TELEPORT_UNITS
@ SPELL_EFFECT_ENCHANT_ITEM_PRISMATIC
@ SPELL_EFFECT_CREATE_TAMED_PET
@ SPELL_EFFECT_ENCHANT_ITEM_TEMPORARY
@ SPELL_EFFECT_OPEN_LOCK
@ SPELL_EFFECT_STEAL_BENEFICIAL_BUFF
@ SPELL_EFFECT_CREATE_ITEM
@ SPELL_EFFECT_APPLY_AURA
@ SPELL_EFFECT_LEARN_PET_SPELL
#define CLASSMASK_WAND_USERS
@ SPELL_PREVENTION_TYPE_SILENCE
@ SPELL_PREVENTION_TYPE_PACIFY
@ SPELL_ATTR1_NO_THREAT
@ SPELL_ATTR1_DISPEL_AURAS_ON_IMMUNITY
@ SPELL_ATTR1_UNAFFECTED_BY_SCHOOL_IMMUNE
@ SPELL_ATTR1_DRAIN_ALL_POWER
@ SPELL_ATTR1_CANT_BE_REFLECTED
@ TARGET_UNIT_PASSENGER_1
@ TARGET_DEST_TARGET_ANY
@ TARGET_UNIT_TARGET_CHAINHEAL_ALLY
@ TARGET_DEST_CASTER_RANDOM
@ TARGET_DEST_DB
@ TARGET_DEST_DYNOBJ_ENEMY
@ TARGET_UNIT_PASSENGER_6
@ TARGET_DEST_CASTER_FRONT_LEAP
@ TARGET_DEST_CHANNEL_TARGET
@ TARGET_DEST_DEST_RANDOM
@ TARGET_UNIT_VEHICLE
@ TARGET_UNIT_PASSENGER_2
@ TARGET_UNIT_CHANNEL_TARGET
@ TARGET_DEST_CASTER_FISHING
@ TARGET_DEST_TARGET_RANDOM
@ TARGET_DEST_DEST
@ TARGET_UNIT_PASSENGER_4
@ TARGET_UNIT_PASSENGER_7
@ TARGET_DEST_TARGET_ENEMY
@ TARGET_UNIT_PET
@ TARGET_DEST_DYNOBJ_NONE
@ TARGET_DEST_DYNOBJ_ALLY
@ TARGET_UNIT_MASTER
@ TARGET_DEST_TRAJ
@ TARGET_UNIT_PASSENGER_5
@ TARGET_UNIT_PASSENGER_3
@ TARGET_DEST_CASTER_SUMMON
@ TARGET_DEST_CASTER
@ TARGET_UNIT_CASTER
@ TARGET_GAMEOBJECT_TARGET
@ TARGET_GAMEOBJECT_ITEM_TARGET
@ TARGET_UNIT_SUMMONER
@ TARGET_UNIT_PASSENGER_0
@ TARGET_DEST_HOME
@ TARGET_DEST_CHANNEL_CASTER
@ SPELL_ATTR7_IS_CHEAT_SPELL
@ SPELL_ATTR2_AUTOREPEAT_FLAG
@ SPELL_ATTR2_CAN_TARGET_DEAD
@ SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS
@ SPELL_ATTR2_NOT_RESET_AUTO_ACTIONS
@ SPELL_ATTR2_TRIGGERED_CAN_TRIGGER_PROC
LockType
@ CREATURE_TYPE_HUMANOID
@ CREATURE_TYPE_CRITTER
@ SPELL_DAMAGE_CLASS_RANGED
@ SPELL_DAMAGE_CLASS_MAGIC
@ SPELL_DAMAGE_CLASS_NONE
@ SPELL_DAMAGE_CLASS_MELEE
@ SPELL_ATTR4_NOT_USABLE_IN_ARENA_OR_RATED_BG
@ SPELL_ATTR4_AREA_TARGET_CHAIN
@ SPELL_ATTR4_USABLE_IN_ARENA
@ SPELL_ATTR4_UNK4
@ SPELL_ATTR4_PROC_ONLY_ON_CASTER
@ SPELL_ATTR4_TRIGGERED
@ LOCK_KEY_ITEM
@ LOCK_KEY_SKILL
@ SPELL_ATTR6_IGNORE_CASTER_AURAS
@ SPELL_ATTR6_CAST_BY_CHARMER
@ CLASS_WARLOCK
@ CLASS_DEATH_KNIGHT
@ CLASS_PALADIN
@ SPELL_ATTR3_MAIN_HAND
@ SPELL_ATTR3_ONLY_TARGET_PLAYERS
@ SPELL_ATTR3_ONLY_TARGET_GHOSTS
@ SPELL_ATTR3_NO_INITIAL_AGGRO
@ SPELL_ATTR3_BATTLEGROUND
@ SPELL_ATTR3_CANT_TRIGGER_PROC
@ SPELL_ATTR3_REQ_OFFHAND
@ SPELL_ATTR3_TRIGGERED_CAN_TRIGGER_PROC_2
@ SPELLFAMILY_PRIEST
@ SPELLFAMILY_WARLOCK
@ SPELLFAMILY_MAGE
@ SPELLFAMILY_GENERIC
@ SPELLFAMILY_HUNTER
@ SPELLFAMILY_DRUID
SpellCustomErrors
@ SPELL_CUSTOM_ERROR_NONE
@ SPELL_CUSTOM_ERROR_GM_ONLY
@ SPELL_ATTR5_USABLE_WHILE_CONFUSED
@ SPELL_ATTR5_USABLE_WHILE_FEARED
@ SPELL_ATTR5_HASTE_AFFECT_DURATION
@ SPELL_ATTR5_USABLE_WHILE_STUNNED
@ DIMINISHING_LEVEL_1
#define IMMUNE_TO_MOVEMENT_IMPAIRMENT_AND_LOSS_CONTROL_MASK
@ SPELL_ATTR9_USABLE_IN_RATED_BATTLEGROUNDS
@ SPELL_ATTR9_SPECIAL_DELAY_CALCULATION
@ SPELL_ATTR9_NOT_USABLE_IN_ARENA
SpellMissInfo
@ SPELL_MISS_PARRY
@ SPELL_MISS_IMMUNE
@ SPELL_MISS_DODGE
@ SPELL_MISS_IMMUNE2
@ SPELL_MISS_NONE
@ SPELL_MISS_RESIST
@ SPELL_MISS_MISS
@ SPELL_MISS_EVADE
@ SPELL_MISS_REFLECT
AuraStateType
DiminishingReturnsType
@ DRTYPE_PLAYER
@ DRTYPE_ALL
@ MECHANIC_STUN
DispelType
@ SPELL_ATTR8_AURA_SEND_AMOUNT
SkillType SkillByLockType(LockType locktype)
@ SUMMON_CATEGORY_PET
@ SUMMON_CATEGORY_PUPPET
SkillType
@ SKILL_INSCRIPTION
@ SKILL_MINING
@ SKILL_NONE
@ SKILL_ENCHANTING
@ SKILL_JEWELCRAFTING
@ SKILL_HERBALISM
SpellSchoolMask
SpellCastResult
@ SPELL_FAILED_NOT_IN_RATED_BATTLEGROUND
@ SPELL_FAILED_ITEM_ENCHANT_TRADE_WINDOW
@ SPELL_FAILED_ALREADY_AT_FULL_HEALTH
@ SPELL_FAILED_EQUIPPED_ITEM_CLASS_MAINHAND
@ SPELL_FAILED_TARGET_IS_PLAYER_CONTROLLED
@ SPELL_FAILED_TARGET_NOT_IN_INSTANCE
@ SPELL_FAILED_TARGET_LOCKED_TO_RAID_INSTANCE
@ SPELL_FAILED_EQUIPPED_ITEM_CLASS_OFFHAND
@ SPELL_FAILED_ITEM_ALREADY_ENCHANTED
@ SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW
static float tangent(float x)
Definition Spell.cpp:1620
#define CHECK_DIST
#define DEBUG_TRAJ(a)
Definition Spell.cpp:1632
GCDLimits
Definition Spell.cpp:7963
@ MIN_GCD
Definition Spell.cpp:7964
@ MAX_GCD
Definition Spell.cpp:7965
@ SPELL_RANGE_MELEE
Definition Spell.h:69
@ SPELL_RANGE_RANGED
Definition Spell.h:70
SpellEffectHandleMode
Definition Spell.h:273
@ SPELL_EFFECT_HANDLE_LAUNCH_TARGET
Definition Spell.h:275
@ SPELL_EFFECT_HANDLE_LAUNCH
Definition Spell.h:274
@ SPELL_EFFECT_HANDLE_HIT
Definition Spell.h:276
@ SPELL_EFFECT_HANDLE_HIT_TARGET
Definition Spell.h:277
@ SPELL_STATE_DELAYED
Definition Spell.h:269
@ SPELL_STATE_NULL
Definition Spell.h:264
@ SPELL_STATE_FINISHED
Definition Spell.h:267
@ SPELL_STATE_PREPARING
Definition Spell.h:265
@ SPELL_STATE_CASTING
Definition Spell.h:266
@ CAST_FLAG_UNKNOWN_19
Definition Spell.h:50
@ CAST_FLAG_VISUAL_CHAIN
Definition Spell.h:51
@ CAST_FLAG_ADJUST_MISSILE
Definition Spell.h:49
@ CAST_FLAG_HEAL_PREDICTION
Definition Spell.h:62
@ CAST_FLAG_UNKNOWN_9
Definition Spell.h:40
@ CAST_FLAG_PROJECTILE
Definition Spell.h:37
@ CAST_FLAG_POWER_LEFT_SELF
Definition Spell.h:43
@ CAST_FLAG_HAS_TRAJECTORY
Definition Spell.h:33
@ CAST_FLAG_RUNE_LIST
Definition Spell.h:53
@ CAST_FLAG_PENDING
Definition Spell.h:32
@ CAST_FLAG_IMMUNITY
Definition Spell.h:58
void(Spell::* pEffect)(SpellEffIndex effIndex)
Definition Spell.h:828
@ SPELL_AURA_DISPEL_IMMUNITY
@ SPELL_AURA_ABILITY_IGNORE_AURASTATE
@ SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE
@ SPELL_AURA_MOD_IGNORE_SHAPESHIFT
@ SPELL_AURA_PERIODIC_MANA_LEECH
@ SPELL_AURA_MOD_POSSESS_PET
@ SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS
@ SPELL_AURA_MOD_FEAR
@ SPELL_AURA_CAST_WHILE_WALKING
@ SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE
@ SPELL_AURA_FLY
@ SPELL_AURA_MOD_PACIFY
@ SPELL_AURA_MOD_SILENCE
@ SPELL_AURA_MOD_POWER_COST_SCHOOL_PCT
@ SPELL_AURA_ADD_TARGET_TRIGGER
@ SPELL_AURA_MOD_CHARM
@ SPELL_AURA_SCHOOL_IMMUNITY
@ SPELL_AURA_MOUNTED
@ SPELL_AURA_MOD_POWER_COST_SCHOOL
@ SPELL_AURA_MECHANIC_IMMUNITY
@ SPELL_AURA_MOD_PACIFY_SILENCE
@ SPELL_AURA_AOE_CHARM
@ SPELL_AURA_REDUCE_PUSHBACK
@ SPELL_AURA_IGNORE_MELEE_RESET
@ SPELL_AURA_MOD_CONFUSE
@ SPELL_AURA_MOD_POSSESS
@ SPELL_AURA_MOD_STEALTH
@ SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED
@ SPELL_AURA_BLOCK_SPELL_FAMILY
@ SPELL_AURA_MOD_STUN
@ SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER
Definition SpellInfo.h:78
@ SPELL_ATTR0_CU_DIRECT_DAMAGE
Definition SpellInfo.h:71
@ SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET
Definition SpellInfo.h:79
@ SPELL_ATTR0_CU_CONE_BACK
Definition SpellInfo.h:66
@ SPELL_ATTR0_CU_AURA_CC
Definition SpellInfo.h:70
@ SPELL_ATTR0_CU_PICKPOCKET
Definition SpellInfo.h:73
@ SPELL_ATTR0_CU_CONE_LINE
Definition SpellInfo.h:67
@ SPELL_ATTR0_CU_NO_INITIAL_THREAT
Definition SpellInfo.h:69
int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const *spellproto)
Definition SpellMgr.cpp:235
DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const *spellproto, bool triggered)
Definition SpellMgr.cpp:45
DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group)
Definition SpellMgr.cpp:205
#define sSpellMgr
Definition SpellMgr.h:744
@ SPELL_LINK_HIT
Definition SpellMgr.h:87
@ PROC_EX_NONE
Definition SpellMgr.h:184
@ PROC_EX_INTERNAL_CANT_PROC
Definition SpellMgr.h:206
@ PROC_EX_CRITICAL_HIT
Definition SpellMgr.h:186
@ PROC_EX_NORMAL_HIT
Definition SpellMgr.h:185
@ PROC_EX_INTERNAL_TRIGGERED
Definition SpellMgr.h:209
@ PROC_EX_INTERNAL_REQ_FAMILY
Definition SpellMgr.h:210
@ PROC_FLAG_DONE_SPELL_RANGED_DMG_CLASS
Definition SpellMgr.h:110
@ PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS
Definition SpellMgr.h:119
@ PROC_FLAG_TAKEN_RANGED_AUTO_ATTACK
Definition SpellMgr.h:108
@ PROC_FLAG_DONE_PERIODIC
Definition SpellMgr.h:125
@ PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS
Definition SpellMgr.h:113
@ PROC_FLAG_DONE_SPELL_MELEE_DMG_CLASS
Definition SpellMgr.h:104
@ PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG
Definition SpellMgr.h:123
@ PROC_FLAG_TAKEN_SPELL_RANGED_DMG_CLASS
Definition SpellMgr.h:111
@ PROC_FLAG_TAKEN_PERIODIC
Definition SpellMgr.h:126
@ PROC_FLAG_DONE_MAINHAND_ATTACK
Definition SpellMgr.h:131
@ PROC_FLAG_DONE_RANGED_AUTO_ATTACK
Definition SpellMgr.h:107
@ PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG
Definition SpellMgr.h:117
@ PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG
Definition SpellMgr.h:116
@ PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_POS
Definition SpellMgr.h:120
@ PROC_FLAG_TAKEN_DAMAGE
Definition SpellMgr.h:128
@ PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_POS
Definition SpellMgr.h:114
@ PROC_FLAG_TAKEN_SPELL_MELEE_DMG_CLASS
Definition SpellMgr.h:105
@ PROC_FLAG_DONE_TRAP_ACTIVATION
Definition SpellMgr.h:129
@ PROC_FLAG_DONE_OFFHAND_ATTACK
Definition SpellMgr.h:132
@ PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG
Definition SpellMgr.h:122
SpellScriptHookType
@ SPELL_SCRIPT_HOOK_AFTER_CAST
@ SPELL_SCRIPT_HOOK_EFFECT_HIT
@ SPELL_SCRIPT_HOOK_AFTER_HIT
@ SPELL_SCRIPT_HOOK_EFFECT_LAUNCH
@ SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT
@ SPELL_SCRIPT_HOOK_BEFORE_HIT
@ SPELL_SCRIPT_HOOK_CHECK_CAST
@ SPELL_SCRIPT_HOOK_EFFECT_LAUNCH_TARGET
@ SPELL_SCRIPT_HOOK_HIT
@ SPELL_SCRIPT_HOOK_BEFORE_CAST
@ SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT
@ SPELL_SCRIPT_HOOK_EFFECT_HIT_TARGET
@ SPELL_SCRIPT_HOOK_ON_CAST
uint32 GetTargetFlagMask(SpellTargetObjectTypes objType)
@ EFFECT_IMPLICIT_TARGET_CASTER
@ EFFECT_IMPLICIT_TARGET_EXPLICIT
@ TARGET_SELECT_CATEGORY_CONE
@ TARGET_SELECT_CATEGORY_AREA
@ TARGET_SELECT_CATEGORY_DEFAULT
@ TARGET_SELECT_CATEGORY_NEARBY
@ TARGET_SELECT_CATEGORY_NYI
@ TARGET_SELECT_CATEGORY_CHANNEL
SpellTargetCheckTypes
@ TARGET_CHECK_PARTY
@ TARGET_CHECK_ENEMY
@ TARGET_CHECK_DEFAULT
@ TARGET_CHECK_ENTRY
@ TARGET_CHECK_RAID_CLASS
@ TARGET_CHECK_ALLY
@ TARGET_CHECK_RAID
@ TARGET_FLAG_TRADE_ITEM
@ TARGET_FLAG_GAMEOBJECT
@ TARGET_FLAG_STRING
@ TARGET_FLAG_NONE
@ TARGET_FLAG_UNIT_RAID
@ TARGET_FLAG_UNIT_ENEMY
@ TARGET_FLAG_CORPSE_ALLY
@ TARGET_FLAG_ITEM
@ TARGET_FLAG_UNIT_MINIPET
@ TARGET_FLAG_GAMEOBJECT_ITEM
@ TARGET_FLAG_DEST_LOCATION
@ TARGET_FLAG_UNIT_ALLY
@ TARGET_FLAG_SOURCE_LOCATION
@ TARGET_FLAG_ITEM_MASK
@ TARGET_FLAG_UNIT
@ TARGET_FLAG_UNIT_MASK
@ TARGET_FLAG_CORPSE_ENEMY
@ TARGET_FLAG_CORPSE_MASK
@ TARGET_FLAG_GAMEOBJECT_MASK
@ TARGET_FLAG_UNIT_PARTY
SpellTargetObjectTypes
@ TARGET_OBJECT_TYPE_UNIT
@ TARGET_OBJECT_TYPE_CORPSE
@ TARGET_OBJECT_TYPE_UNIT_AND_DEST
@ TARGET_OBJECT_TYPE_DEST
@ TARGET_OBJECT_TYPE_GOBJ
@ TARGET_OBJECT_TYPE_CORPSE_ALLY
@ TARGET_OBJECT_TYPE_CORPSE_ENEMY
@ TARGET_OBJECT_TYPE_GOBJ_ITEM
@ TARGET_OBJECT_TYPE_SRC
@ TARGET_REFERENCE_TYPE_SRC
@ TARGET_REFERENCE_TYPE_TARGET
@ TARGET_REFERENCE_TYPE_LAST
@ TARGET_REFERENCE_TYPE_CASTER
@ TARGET_REFERENCE_TYPE_DEST
uint32 getMSTime()
Definition Timer.h:12
@ AURA_INTERRUPT_FLAG_SPELL_ATTACK
Definition Unit.h:54
@ AURA_INTERRUPT_FLAG_CAST
Definition Unit.h:43
@ AURA_INTERRUPT_FLAG_TALK
Definition Unit.h:51
@ AURA_INTERRUPT_FLAG_HITBYSPELL
Definition Unit.h:41
@ AURA_INTERRUPT_FLAG_NOT_SEATED
Definition Unit.h:59
@ MOVEMENTFLAG_FALLING_FAR
Definition Unit.h:735
@ UNIT_MASK_PUPPET
Definition Unit.h:811
#define WORLD_TRIGGER
Definition Unit.h:20
@ SPELLMOD_RANGE
Definition Unit.h:78
@ SPELLMOD_NOT_LOSE_CASTING_TIME
Definition Unit.h:82
@ SPELLMOD_SPELL_COST_REFUND_ON_FAIL
Definition Unit.h:103
@ SPELLMOD_GLOBAL_COOLDOWN
Definition Unit.h:94
@ SPELLMOD_DURATION
Definition Unit.h:74
@ SPELLMOD_JUMP_TARGETS
Definition Unit.h:90
@ SPELLMOD_COST
Definition Unit.h:87
SpellValueMod
Definition Unit.h:113
@ SPELLVALUE_AURA_STACK
Definition Unit.h:119
@ SPELLVALUE_BASE_POINT1
Definition Unit.h:115
@ SPELLVALUE_RADIUS_MOD
Definition Unit.h:117
@ SPELLVALUE_MAX_TARGETS
Definition Unit.h:118
@ SPELLVALUE_BASE_POINT2
Definition Unit.h:116
@ SPELLVALUE_BASE_POINT0
Definition Unit.h:114
@ JUST_DIED
Definition Unit.h:504
@ UNIT_STAND_STATE_STAND
Definition Unit.h:162
@ AURA_REMOVE_BY_CANCEL
Definition Unit.h:408
TriggerCastFlags
Definition Unit.h:415
@ TRIGGERED_IGNORE_EQUIPPED_ITEM_REQUIREMENT
Will return SPELL_FAILED_DONT_REPORT in CheckCast functions.
Definition Unit.h:433
@ TRIGGERED_FULL_MASK
Will ignore most target checks (mostly DBC target checks).
Definition Unit.h:435
@ TRIGGERED_IGNORE_POWER_AND_REAGENT_COST
Will ignore Spell and Category cooldowns.
Definition Unit.h:419
@ TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD
Will ignore GCD.
Definition Unit.h:418
@ TRIGGERED_CAST_DIRECTLY
Will ignore combo point requirement.
Definition Unit.h:424
@ TRIGGERED_IGNORE_TARGET_CHECK
Will ignore equipped item requirements.
Definition Unit.h:434
@ TRIGGERED_IGNORE_CASTER_AURASTATE
Will ignore shapeshift checks.
Definition Unit.h:428
@ TRIGGERED_IGNORE_AURA_SCALING
Will not take away cast item or update related achievement criteria.
Definition Unit.h:421
@ TRIGGERED_IGNORE_CAST_IN_PROGRESS
Will ignore aura scaling.
Definition Unit.h:422
@ TRIGGERED_IGNORE_CASTER_MOUNTED_OR_ON_VEHICLE
Will ignore caster aura states including combat requirements and death state.
Definition Unit.h:429
@ TRIGGERED_IGNORE_SHAPESHIFT
Will not adjust facing to target (if any).
Definition Unit.h:427
@ TRIGGERED_IGNORE_AURA_INTERRUPT_FLAGS
In Spell::prepare, will be cast directly without setting containers for executed spell.
Definition Unit.h:425
@ TRIGGERED_IGNORE_CAST_ITEM
Will ignore power and reagent cost.
Definition Unit.h:420
@ TRIGGERED_IGNORE_COMBO_POINTS
Will not check if a current cast is in progress.
Definition Unit.h:423
@ TRIGGERED_IGNORE_GCD
Not triggered.
Definition Unit.h:417
@ TRIGGERED_DISALLOW_PROC_EVENTS
Will ignore caster aura restrictions or requirements.
Definition Unit.h:431
@ TRIGGERED_IGNORE_CASTER_AURAS
Will ignore mounted/on vehicle restrictions.
Definition Unit.h:430
@ TRIGGERED_DONT_REPORT_CAST_ERROR
Disallows proc events from triggered spell (default).
Definition Unit.h:432
@ TRIGGERED_IGNORE_SET_FACING
Will ignore interruptible aura's at cast.
Definition Unit.h:426
@ NULL_BAG
Definition Unit.h:336
@ NULL_SLOT
Definition Unit.h:337
CurrentSpellTypes
Definition Unit.h:1107
@ CURRENT_CHANNELED_SPELL
Definition Unit.h:1110
@ CURRENT_GENERIC_SPELL
Definition Unit.h:1109
@ CURRENT_MELEE_SPELL
Definition Unit.h:1108
@ CURRENT_AUTOREPEAT_SPELL
Definition Unit.h:1111
@ SPELL_INTERRUPT_FLAG_INTERRUPT
Definition Unit.h:27
@ SPELL_INTERRUPT_FLAG_MOVEMENT
Definition Unit.h:24
@ SPELL_FACING_FLAG_INFRONT
Definition Unit.h:152
@ UNIT_STATE_ATTACK_PLAYER
Definition Unit.h:526
@ UNIT_STATE_ROOT
Definition Unit.h:522
@ UNIT_STATE_CASTING
Definition Unit.h:527
@ UNIT_FLAG_STUNNED
Definition Unit.h:643
@ UNIT_FLAG_NON_ATTACKABLE
Definition Unit.h:626
@ UNIT_FLAG_PACIFIED
Definition Unit.h:642
@ UNIT_FLAG_CONFUSED
Definition Unit.h:647
@ UNIT_FLAG_FLEEING
Definition Unit.h:648
@ UNIT_FLAG_SILENCED
Definition Unit.h:638
@ UNIT_FLAG_SKINNABLE
Definition Unit.h:651
uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition)
@ UNIT_FLAG2_ALLOW_CHEAT_SPELLS
Definition Unit.h:680
@ UNIT_FIELD_MOD_CASTING_SPEED
@ UNIT_FIELD_FLAGS2
@ UNIT_FIELD_CHANNEL_OBJECT
@ UNIT_FIELD_FLAGS
@ UNIT_FIELD_CHANNEL_SPELL
@ UNIT_FIELD_CREATED_BY_SPELL
@ PLAYER_FIELD_PLAYER_FLAGS
double rand_norm(void)
Definition Util.cpp:50
bool roll_chance_i(int chance)
Definition Util.h:89
T AddPct(T &base, U pct)
Definition Util.h:109
T CalculatePct(T base, U pct)
Definition Util.h:103
SpellInfo const * GetSpellInfo() const
bool IsPeriodic() const
Aura * GetBase() const
int32 GetDuration() const
Definition SpellAuras.h:119
AuraEffect * GetEffect(uint8 effIndex) const
Definition SpellAuras.h:168
static Aura * TryRefreshStackOrCreate(SpellInfo const *spellproto, uint32 tryEffMask, WorldObject *owner, Unit *caster, int32 *baseAmount=NULL, Item *castItem=NULL, uint64 casterGUID=0, bool *refresh=NULL)
void SetDuration(int32 duration, bool withMods=false)
SpellInfo const * GetSpellInfo() const
Definition SpellAuras.h:87
bool IsPassive() const
bool CanFlyIn() const
Return if we can use mount in battlefield.
void WriteGuidBytes(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:264
bool WriteBit(uint32 bit)
Definition ByteBuffer.h:164
void WriteGuidMask(const ObjectGuid &guid, Offsets... offsets)
Definition ByteBuffer.h:248
size_t bitwpos() const
Returns position of last written bit.
Definition ByteBuffer.h:492
void WriteString(std::string const &str)
Definition ByteBuffer.h:578
void appendPackGUID(uint64 guid)
Definition ByteBuffer.h:681
void append(T value)
Definition ByteBuffer.h:147
void PutBits(size_t pos, T value, uint32 bitCount)
Definition ByteBuffer.h:283
size_t wpos() const
Definition ByteBuffer.h:483
void WriteBits(T value, size_t bits)
Definition ByteBuffer.h:192
void WriteByteSeq(uint8 b)
Definition ByteBuffer.h:227
void FlushBits()
Definition ByteBuffer.h:154
void readPackGUID(uint64 &guid)
Definition ByteBuffer.h:541
uint64 GetOwnerGUID() const
Definition Corpse.h:54
virtual void SpellHit(Unit *, SpellInfo const *)
Definition CreatureAI.h:105
Loot loot
Definition Creature.h:544
CreatureTemplate const * GetCreatureTemplate() const
Definition Creature.h:524
CreatureAI * AI() const
Definition Creature.h:483
bool IsInRange(float x, float y, float z, float radius) const
GameobjectTypes GetGoType() const
Definition GameObject.h:719
Definition Guild.h:324
void threatAssist(Unit *victim, float baseThreat, SpellInfo const *threatSpell=NULL)
Definition Item.h:202
bool IsLocked() const
Definition Item.h:243
ItemTemplate const * GetTemplate() const
Definition Item.cpp:528
bool IsBroken() const
Definition Item.h:247
Player * GetOwner() const
Definition Item.cpp:533
bool IsFitToSpellRequirements(SpellInfo const *spellInfo) const
Definition Item.cpp:820
Definition Map.h:238
static WorldObject * GetWorldObject(WorldObject const &, uint64)
static Unit * GetUnit(WorldObject const &, uint64 guid)
static Corpse * GetCorpse(WorldObject const &u, uint64 guid)
static Player * FindPlayer(uint64)
static Unit * FindUnit(uint64)
Corpse * ToCorpse()
Definition Object.h:216
uint64 GetGUID() const
Definition Object.h:119
Player * ToPlayer()
Definition Object.h:204
TypeID GetTypeId() const
Definition Object.h:131
GameObject * ToGameObject()
Definition Object.h:213
uint32 GetEntry() const
Definition Object.h:125
Creature * ToCreature()
Definition Object.h:207
bool HasFlag(uint16 index, uint32 flag) const
Definition Object.cpp:1309
Unit * ToUnit()
Definition Object.h:210
Definition Pet.h:28
Player * GetOwner() const
Definition Pet.cpp:2117
bool HaveInDiet(ItemTemplate const *item) const
Definition Pet.cpp:1084
uint32 GetCurrentFoodBenefitLevel(uint32 itemlevel) const
Definition Pet.cpp:1102
void SendEquipError(InventoryResult msg, Item *pItem, Item *pItem2=NULL, uint32 itemid=0)
void SetLastPotionId(uint32 item_id)
Definition Player.h:2190
InstancePlayerBind * GetBoundInstance(uint32 mapid, DifficultyID difficulty)
Definition Player.cpp:13877
bool IsInSameRaidWith(Player const *p) const
Definition Player.cpp:3030
void SetLastUsedRune(RuneType type)
Definition Player.h:3079
void SetRuneCooldown(uint8 index, uint32 cooldown)
Definition Player.cpp:20536
bool HasItemFitToSpellRequirements(SpellInfo const *spellInfo, Item const *ignoreItem=NULL) const
Definition Player.cpp:19557
uint16 GetSkillValue(uint32 skill) const
Definition Player.cpp:6563
void CastItemCombatSpell(Unit *target, WeaponAttackType attType, uint32 procVictim, uint32 procEx)
Definition Player.cpp:8913
Item * GetItemByEntry(uint32 entry) const
bool HasItemCount(uint32 item, uint32 count=1, bool inBankAlso=false) const
uint8 GetRunesState() const
Definition Player.h:3053
void RestoreBaseRune(uint8 index)
Definition Player.cpp:20564
WorldSession * GetSession() const
Definition Player.h:2417
Item * GetItemByGuid(uint64 guid) const
bool CanNoReagentCast(SpellInfo const *spellInfo) const
Definition Player.cpp:19602
T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell *spell=NULL)
Definition Player.h:3623
uint32 GetRuneCooldown(uint8 index) const
Definition Player.h:3065
void AddSpellAndCategoryCooldowns(SpellInfo const *spellInfo, uint32 itemId, Spell *spell=NULL, bool infinityCooldown=false)
Definition Player.cpp:17511
bool Satisfy(AccessRequirement const *ar, uint32 target_map, bool report=false)
Definition Player.cpp:14123
TradeData * GetTradeData() const
Definition Player.h:1694
RuneType GetCurrentRune(uint8 index) const
Definition Player.h:3061
InventoryResult CanStoreNewItem(uint8 bag, uint8 slot, ItemPosCountVec &dest, uint32 item, uint32 count, uint32 *no_space_count=NULL) const
void DestroyItemCount(uint32 item, uint32 count, bool update, bool unequip_check=false)
uint32 GetRuneBaseCooldown(uint8 index) const
Definition Player.h:3069
Player * GetSelectedPlayer() const
Definition Player.cpp:18392
Item * GetWeaponForAttack(WeaponAttackType attackType, bool useable=false) const
void RecordSpellCastFailure(uint32 spellId, uint32 failure, uint32 customError, uint32 opcode)
SpellDestination const * GetSrc() const
Definition Spell.cpp:332
void SetItemTarget(Item *item)
Definition Spell.cpp:303
void RemoveObjectTarget()
Definition Spell.cpp:296
WorldObject * GetObjectTarget() const
Definition Spell.cpp:286
void OutDebug() const
Definition Spell.cpp:469
uint64 GetGOTargetGUID() const
Definition Spell.cpp:238
uint64 GetObjectTargetGUID() const
Definition Spell.cpp:291
uint64 GetCorpseTargetGUID() const
Definition Spell.cpp:268
void ModDst(Position const &pos)
Definition Spell.cpp:412
GameObject * GetGOTarget() const
Definition Spell.cpp:251
void SetTradeItemTarget(Player *caster)
Definition Spell.cpp:314
SpellDestination m_dst
Definition Spell.h:247
bool HasSrc() const
Definition Spell.h:216
Corpse * GetCorpseTarget() const
Definition Spell.cpp:279
uint64 m_objectTargetGUID
Definition Spell.h:242
void SetDst(float x, float y, float z, float orientation, uint32 mapId=MAPID_INVALID)
Definition Spell.cpp:388
uint64 m_itemTargetGUID
Definition Spell.h:243
void SetSrc(float x, float y, float z)
Definition Spell.cpp:342
SpellDestination const * GetDst() const
Definition Spell.cpp:378
void SetGOTarget(GameObject *target)
Definition Spell.cpp:258
std::string m_strTarget
Definition Spell.h:250
float m_speed
Definition Spell.h:249
void UpdateTradeSlotItem()
Definition Spell.cpp:323
SpellDestination m_src
Definition Spell.h:246
float m_elevation
Definition Spell.h:249
void SetUnitTarget(Unit *target)
Definition Spell.cpp:228
void Read(ByteBuffer &data, Unit *caster)
Definition Spell.cpp:117
uint32 m_targetMask
Definition Spell.h:235
bool HasDst() const
Definition Spell.h:217
WorldObject * m_objectTarget
Definition Spell.h:238
Unit * GetUnitTarget() const
Definition Spell.cpp:221
void Update(Unit *caster)
Definition Spell.cpp:430
uint64 GetUnitTargetGUID() const
Definition Spell.cpp:207
uint32 m_itemTargetEntry
Definition Spell.h:244
void ModSrc(Position const &pos)
Definition Spell.cpp:360
void RemoveDst()
Definition Spell.cpp:425
void RemoveSrc()
Definition Spell.cpp:373
void Write(ByteBuffer &data)
Definition Spell.cpp:170
Position const * GetSrcPos() const
Definition Spell.cpp:337
WorldLocation const * GetDstPos() const
Definition Spell.cpp:383
Item * m_itemTarget
Definition Spell.h:239
std::list< Condition * > * ImplicitTargetConditions
Definition SpellInfo.h:110
uint32 TriggerSpell
Definition SpellInfo.h:108
float CalcRadius(Unit *caster=NULL, Spell *=NULL) const
SpellImplicitTargetInfo TargetA
Definition SpellInfo.h:102
SpellImplicitTargetInfo TargetB
Definition SpellInfo.h:103
virtual ~SpellEvent()
Definition Spell.cpp:7366
Spell * m_Spell
Definition Spell.h:840
virtual bool IsDeletable() const
Definition Spell.cpp:7477
SpellEvent(Spell *spell)
Definition Spell.cpp:7361
virtual void Abort(uint64 e_time)
Definition Spell.cpp:7470
virtual bool Execute(uint64 e_time, uint32 p_time)
Definition Spell.cpp:7383
Definition Spell.h:289
void SelectImplicitDestDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType)
Definition Spell.cpp:1488
void UpdatePointers()
Definition Spell.cpp:7210
SpellInfo const * GetSpellInfo() const
Definition Spell.h:565
int8 m_comboPointGain
Definition Spell.h:536
void CallScriptAfterCastHandlers()
Definition Spell.cpp:7744
void HandleHolyPower(Player *caster)
Definition Spell.cpp:5482
GameObject * SearchSpellFocus()
Definition Spell.cpp:2039
GameObject * gameObjTarget
Definition Spell.h:628
void PrepareTriggersExecutedOnHit()
Definition Spell.cpp:7932
bool m_referencedFromCurrentSpell
Definition Spell.h:619
bool m_canReflect
Definition Spell.h:599
uint32 m_procVictim
Definition Spell.h:650
Unit * m_originalCaster
Definition Spell.h:587
void LoadScripts()
Definition Spell.cpp:7699
void cast(bool skipCheck=false)
Definition Spell.cpp:3266
void SendChannelStart(uint32 duration)
Definition Spell.cpp:5041
bool m_needComboPoints
Definition Spell.h:621
static void SendCastResult(Player *caster, SpellInfo const *spellInfo, uint8 cast_count, SpellCastResult result, SpellCustomErrors customError=SPELL_CUSTOM_ERROR_NONE, Opcodes opcode=SMSG_CAST_FAILED)
Definition Spell.cpp:3874
uint64 m_delayStart
Definition Spell.h:614
SpellCastTargets m_targets
Definition Spell.h:535
void SendPetCastResult(SpellCastResult result)
Definition Spell.cpp:3862
void SearchChainTargets(std::list< WorldObject * > &targets, uint32 chainTargets, WorldObject *target, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectType, ConditionList *condList, bool isChainHeal)
Definition Spell.cpp:1943
Unit * GetCaster() const
Definition Spell.h:563
void SelectEffectImplicitTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType, uint32 &processedEffectMask)
Definition Spell.cpp:819
void SelectExplicitTargets()
Definition Spell.cpp:701
void handle_immediate()
Definition Spell.cpp:3462
void SendSpellGo()
Definition Spell.cpp:4341
TriggerCastFlags _triggeredCastFlags
Definition Spell.h:752
bool IsAutoRepeat() const
Definition Spell.h:543
int32 damage
Definition Spell.h:630
void SetSpellValue(SpellValueMod mod, int32 value)
Definition Spell.cpp:7659
void prepareDataForTriggerSystem(AuraEffect const *triggeredByAura)
Definition Spell.cpp:2048
void ExecuteLogEffectSummonObject(uint8 effIndex, WorldObject *obj)
Definition Spell.cpp:4970
SpellCastResult CanOpenLock(uint32 effIndex, uint32 lockid, SkillType &skillid, int32 &reqSkillValue, int32 &skillValue)
Definition Spell.cpp:7597
SpellEffectHandleMode effectHandleMode
Definition Spell.h:631
void TakeReagents()
Definition Spell.cpp:5383
bool IsValidDeadOrAliveTarget(Unit const *target) const
Definition Spell.cpp:7482
Aura * m_spellAura
Definition Spell.h:633
uint32 GetSearcherTypeMask(SpellTargetObjectTypes objType, ConditionList *condList) const
Definition Spell.cpp:1853
bool IsNeedSendToClient() const
Definition Spell.cpp:7338
SpellResearchData const * m_researchData
Definition Spell.h:538
void CallScriptObjectAreaTargetSelectHandlers(std::list< WorldObject * > &targets, SpellEffIndex effIndex)
Definition Spell.cpp:7869
void SelectImplicitConeTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType, uint32 effMask)
Definition Spell.cpp:1061
SpellDestination m_destTargets[MAX_SPELL_EFFECTS]
Definition Spell.h:690
Unit *const m_caster
Definition Spell.h:581
void _handle_finish_phase()
Definition Spell.cpp:3628
void PrepareTargetProcessing()
Definition Spell.cpp:7684
void SetExecutedCurrently(bool yes)
Definition Spell.h:554
void SendSpellStart()
Definition Spell.cpp:4012
int32 m_powerType
Definition Spell.h:594
Spell(Unit *caster, SpellInfo const *info, TriggerCastFlags triggerFlags, uint64 originalCasterGUID=0, bool skipCheck=false)
Definition Spell.cpp:500
uint8 m_delayAtDamageCount
Definition Spell.h:603
void SendChannelUpdate(uint32 time)
Definition Spell.cpp:5023
uint64 m_delayMoment
Definition Spell.h:615
SpellCastResult CheckItems()
Definition Spell.cpp:6695
void prepare(SpellCastTargets const *targets, AuraEffect const *triggeredByAura=NULL)
Definition Spell.cpp:2939
std::list< GOTargetInfo > m_UniqueGOTargetInfo
Definition Spell.h:681
void SendLogExecute()
Definition Spell.cpp:4804
WeaponAttackType m_attackType
Definition Spell.h:593
void SendInterrupted(uint8 result)
Definition Spell.cpp:4988
uint64 m_originalCasterGUID
Definition Spell.h:585
bool m_immediateHandled
Definition Spell.h:616
uint32 m_spellState
Definition Spell.h:749
LogHelperMap m_effectExecuteData
Definition Spell.h:764
bool UpdateChanneledTargetList()
Definition Spell.cpp:2882
void CleanupTargetList()
Definition Spell.cpp:2128
void TriggerGlobalCooldown()
Definition Spell.cpp:7979
int32 m_timer
Definition Spell.h:750
int32 m_casttime
Definition Spell.h:598
void SearchTargets(SEARCHER &searcher, uint32 containerMask, Unit *referer, Position const *pos, float radius)
Definition Spell.cpp:1888
void ExecuteLogEffectOpenLock(uint8 effIndex, Object *obj)
Definition Spell.cpp:4952
Item * itemTarget
Definition Spell.h:627
void AddGOTarget(GameObject *target, uint32 effectMask)
Definition Spell.cpp:2244
void HandleThreatSpells()
Definition Spell.cpp:5431
void SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType, WorldObject *target, uint32 effMask)
Definition Spell.cpp:1588
uint8 m_cast_count
Definition Spell.h:533
int32 m_damage
Definition Spell.h:643
void ExecuteLogEffectTakeTargetPower(uint8 effIndex, Unit *target, uint32 powerType, uint32 powerTaken, float gainMultiplier)
Definition Spell.cpp:4902
void CancelGlobalCooldown()
Definition Spell.cpp:8013
int32 CalculateDamage(uint8 i, Unit const *target) const
Definition Spell.h:489
uint32 getState() const
Definition Spell.h:494
bool m_executedCurrently
Definition Spell.h:620
void PrepareScriptHitHandlers()
Definition Spell.cpp:7776
DiminishingLevels m_diminishLevel
Definition Spell.h:636
void CallScriptOnCastHandlers()
Definition Spell.cpp:7731
void AddDestTarget(SpellDestination const &dest, uint32 effIndex)
Definition Spell.cpp:2340
void SelectImplicitTargetDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType)
Definition Spell.cpp:1461
float m_damageMultipliers[3]
Definition Spell.h:623
bool HaveTargetsForEffect(uint8 effect) const
Definition Spell.cpp:7344
void HandleEffects(Unit *pUnitTarget, Item *pItemTarget, GameObject *pGOTarget, uint32 i, SpellEffectHandleMode mode)
Definition Spell.cpp:5517
void _handle_immediate_phase()
Definition Spell.cpp:3586
void SendSpellCooldown()
Definition Spell.cpp:3650
SpellCastResult CheckCasterAuras() const
Definition Spell.cpp:6398
void DoAllEffectOnLaunchTarget(TargetInfo &targetInfo, float *multiplier)
Definition Spell.cpp:7547
void CallScriptBeforeCastHandlers()
Definition Spell.cpp:7718
uint8 m_auraScaleMask
Definition Spell.h:760
int32 m_periodicPowerCost
Definition Spell.h:596
void SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType, uint32 effMask)
Definition Spell.cpp:1111
void HandleLaunchPhase()
Definition Spell.cpp:7491
SpellCustomErrors m_customError
Definition Spell.h:537
bool CallScriptEffectHandlers(SpellEffIndex effIndex, SpellEffectHandleMode mode)
Definition Spell.cpp:7782
void SelectImplicitChannelTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType)
Definition Spell.cpp:925
void SelectImplicitTargetObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType)
Definition Spell.cpp:1566
void CallScriptObjectTargetSelectHandlers(WorldObject *&target, SpellEffIndex effIndex)
Definition Spell.cpp:7883
bool m_skipCheck
Definition Spell.h:759
PathGenerator m_preGeneratedPath
Definition Spell.h:761
HitTriggerSpellList m_hitTriggerSpells
Definition Spell.h:740
int32 m_periodicPowerTimer
Definition Spell.h:595
int32 m_healing
Definition Spell.h:644
bool CheckEffectTarget(Unit const *target, uint32 eff) const
Definition Spell.cpp:7263
void SetDelayStart(uint64 m_time)
Definition Spell.h:556
uint32 m_glyphIndex
Definition Spell.h:534
SpellCastResult CheckPower()
Definition Spell.cpp:6659
SpellInfo const * m_triggeredByAuraSpell
Definition Spell.h:757
uint64 handle_delayed(uint64 t_offset)
Definition Spell.cpp:3517
void SearchAreaTargets(std::list< WorldObject * > &targets, float range, Position const *position, Unit *referer, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList *condList)
Definition Spell.cpp:1933
uint8 m_channelTargetEffectMask
Definition Spell.h:672
void SelectImplicitCasterObjectTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType)
Definition Spell.cpp:1521
CurrentSpellTypes GetCurrentContainer() const
Definition Spell.cpp:7251
std::list< TargetInfo > m_UniqueTargetInfo
Definition Spell.h:671
SpellMissInfo DoSpellHitOnUnit(Unit *unit, uint32 effectMask, bool scaleAura)
Definition Spell.cpp:2596
void AddUnitTarget(Unit *target, uint32 effectMask, bool checkIfValid=true, bool implicit=true)
Definition Spell.cpp:2136
Unit * unitTarget
Definition Spell.h:626
void Delayed()
Definition Spell.cpp:7124
SpellSchoolMask m_spellSchoolMask
Definition Spell.h:592
void cancel()
Definition Spell.cpp:3210
std::list< SpellScript * > m_loadedScripts
Definition Spell.h:727
void ExecuteLogEffectUnsummonObject(uint8 effIndex, WorldObject *obj)
Definition Spell.cpp:4976
void SelectImplicitTrajTargets()
Definition Spell.cpp:1634
void SelectSpellTargets()
Definition Spell.cpp:730
void ExecuteLogEffectInterruptCast(uint8 effIndex, Unit *victim, uint32 spellId)
Definition Spell.cpp:4914
void ExecuteLogEffectResurrect(uint8 effIndex, Unit *target)
Definition Spell.cpp:4982
~Spell()
Definition Spell.cpp:604
void TakePower()
Definition Spell.cpp:5213
SpellCastResult CheckPetCast(Unit *target)
Definition Spell.cpp:6365
bool IsNextMeleeSwingSpell() const
Definition Spell.cpp:7327
SpellCastResult CheckCast(bool strict)
Definition Spell.cpp:5539
void ReSetTimer()
Definition Spell.h:545
SpellCastResult CallScriptCheckCastHandlers()
Definition Spell.cpp:7757
std::list< ItemTargetInfo > m_UniqueItemInfo
Definition Spell.h:688
void SelectEffectTypeImplicitTargets(uint8 effIndex)
Definition Spell.cpp:1770
uint64 m_castItemGUID
Definition Spell.h:532
void ExecuteLogEffectCreateItem(uint8 effIndex, uint32 entry)
Definition Spell.cpp:4958
void InitExplicitTargets(SpellCastTargets const &targets)
Definition Spell.cpp:632
bool isDelayableNoMore()
Definition Spell.h:604
void CallScriptBeforeHitHandlers()
Definition Spell.cpp:7830
WorldLocation * destTarget
Definition Spell.h:629
Spell ** m_selfContainer
Definition Spell.h:589
bool IsTriggered() const
Definition Spell.h:547
uint8 m_applyMultiplierMask
Definition Spell.h:622
void DoTriggersOnSpellHit(Unit *unit, uint32 effMask)
Definition Spell.cpp:2790
void SetReferencedFromCurrent(bool yes)
Definition Spell.h:552
bool CanExecuteTriggersOnHit(uint32 effMask, SpellInfo const *triggeredByAura=NULL) const
Definition Spell.cpp:7920
void ExecuteLogEffectDestroyItem(uint8 effIndex, uint32 entry)
Definition Spell.cpp:4964
void CheckEffectExecuteData() const
Definition Spell.cpp:7694
void update(uint32 difftime)
Definition Spell.cpp:3671
void SelectImplicitNearbyTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType, uint32 effMask)
Definition Spell.cpp:973
bool CheckScriptEffectImplicitTargets(uint32 effIndex, uint32 effIndexToCheck)
Definition Spell.cpp:7897
DiminishingGroup m_diminishGroup
Definition Spell.h:637
uint32 m_procEx
Definition Spell.h:651
Item * m_CastItem
Definition Spell.h:531
void AddItemTarget(Item *item, uint32 effectMask)
Definition Spell.cpp:2311
UsedSpellMods m_appliedMods
Definition Spell.h:540
void TakeCastItem()
Definition Spell.cpp:5147
SpellValue *const m_spellValue
Definition Spell.h:583
int32 m_powerCost
Definition Spell.h:597
void SendResurrectRequest(Player *target)
Definition Spell.cpp:5108
void SelectImplicitCasterDestTargets(SpellEffIndex effIndex, SpellImplicitTargetInfo const &targetType)
Definition Spell.cpp:1378
bool IsAutoActionResetSpell() const
Definition Spell.cpp:7332
void ExecuteLogEffectDurabilityDamage(uint8 effIndex, Unit *victim, int32 itemId, int32 slot)
Definition Spell.cpp:4946
void DelayedChannel()
Definition Spell.cpp:7170
uint32 m_procAttacker
Definition Spell.h:649
GameObject * focusObject
Definition Spell.h:640
void ExecuteLogEffectExtraAttacks(uint8 effIndex, Unit *victim, uint32 attCount)
Definition Spell.cpp:4908
WorldObject * SearchNearbyTarget(float range, SpellTargetObjectTypes objectType, SpellTargetCheckTypes selectionType, ConditionList *condList=NULL)
Definition Spell.cpp:1921
void finish(bool ok=true)
Definition Spell.cpp:3762
SpellCastResult CheckRange(bool strict)
Definition Spell.cpp:6599
SpellInfo const *const m_spellInfo
Definition Spell.h:530
bool HasGlobalCooldown() const
Definition Spell.cpp:7968
uint8 m_runesState
Definition Spell.h:601
void FinishTargetProcessing()
Definition Spell.cpp:7689
void CallScriptOnHitHandlers()
Definition Spell.cpp:7843
bool m_autoRepeat
Definition Spell.h:600
SpellCastResult CheckRuneCost(uint32 runeCostID)
Definition Spell.cpp:5273
void TakeRunePower(bool didHit)
Definition Spell.cpp:5320
SpellCastResult CheckArenaAndRatedBattlegroundCastRules()
Definition Spell.cpp:6528
void CallScriptAfterHitHandlers()
Definition Spell.cpp:7856
void DoAllEffectOnTarget(TargetInfo *target)
Definition Spell.cpp:2345
bool CanAutoCast(Unit *target)
Definition Spell.cpp:6559
SpellTargetCheckTypes GetCheckType() const
SpellTargetReferenceTypes GetReferenceType() const
SpellTargetSelectionCategories GetSelectionCategory() const
SpellTargetObjectTypes GetObjectType() const
float CalcDirectionAngle() const
uint32 RequiresSpellFocus
Definition SpellInfo.h:183
SpellEffectInfo Effects[MAX_SPELL_EFFECTS]
Definition SpellInfo.h:255
uint32 SpellLevel
Definition SpellInfo.h:206
uint32 TotemCategory[2]
Definition SpellInfo.h:218
uint32 ReagentCount[MAX_SPELL_REAGENTS]
Definition SpellInfo.h:214
uint32 Id
Definition SpellInfo.h:160
uint32 GetDispelMask() const
int32 EquippedItemClass
Definition SpellInfo.h:215
SpellSchoolMask GetSchoolMask() const
uint32 AttributesEx
Definition SpellInfo.h:165
uint32 MaxAffectedTargets
Definition SpellInfo.h:225
int32 EquippedItemSubClassMask
Definition SpellInfo.h:216
uint32 GetAllEffectsMechanicMask() const
uint32 SpellIconID
Definition SpellInfo.h:220
uint32 Totem[2]
Definition SpellInfo.h:212
uint32 AttributesEx4
Definition SpellInfo.h:168
int32 Reagent[MAX_SPELL_REAGENTS]
Definition SpellInfo.h:213
uint32 GetSpell() const
Definition Player.h:1081
Definition Unit.h:1367
bool IsVehicle() const
Definition Unit.h:1523
uint32 m_lastSanctuaryTime
Definition Unit.h:2446
DiminishingLevels GetDiminishing(DiminishingGroup group)
Definition Unit.cpp:4837
void IncrDiminishing(DiminishingGroup group)
Definition Unit.cpp:4863
bool CanHaveThreatList() const
Definition Unit.cpp:4424
uint32 GetCombatTimer() const
Definition Unit.h:1904
void RemoveAura(AuraApplicationMap::iterator &i, AuraRemoveMode mode=AURA_REMOVE_BY_DEFAULT)
bool HasAuraEffect(uint32 spellId, uint8 effIndex, uint64 caster=0) const
void CastSpell(SpellCastTargets const &targets, SpellInfo const *spellInfo, CustomSpellValues const *value, TriggerCastFlags triggerFlags=TRIGGERED_NONE, Item *castItem=NULL, AuraEffect const *triggeredByAura=NULL, uint64 originalCaster=0)
void RemoveAurasWithInterruptFlags(uint32 flag, uint32 except=0)
void RemoveAurasDueToSpell(uint32 spellId, uint64 casterGUID=0, uint32 reqEffMask=0, AuraRemoveMode removeMode=AURA_REMOVE_BY_DEFAULT)
Player * GetSpellModOwner() const
Definition Unit.cpp:5818
uint64 GetCharmerOrOwnerGUID() const
Definition Unit.cpp:5806
std::multimap< uint32, AuraApplication * > AuraApplicationMap
Definition Unit.h:1376
void AddThreat(Unit *victim, float fThreat, SpellSchoolMask schoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *threatSpell=NULL)
Definition Unit.cpp:4463
bool isSpellCrit(Unit *victim, SpellInfo const *spellProto, SpellSchoolMask schoolMask, WeaponAttackType attackType=WeaponAttackType::BASE_ATTACK) const
Definition Unit.cpp:3111
Player * GetCharmerOrOwnerPlayerOrPlayerItself() const
Definition Unit.cpp:2355
uint32 SpellCriticalHealingBonus(SpellInfo const *spellProto, uint32 damage, Unit *victim)
Definition Unit.cpp:3353
Aura * GetAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
void DealDamageMods(Unit *victim, uint32 &damage, uint32 *absorb)
bool IsPvP() const
Definition Unit.h:1716
float ApplyDiminishingToDuration(DiminishingGroup group, int32 &duration, Unit *caster, DiminishingLevels Level, int32 limitduration)
uint8 getClass() const
Definition Unit.h:1543
uint64 GetTarget() const
Definition Unit.h:2830
bool IsAlive() const
Definition Unit.h:2032
bool IsStandState() const
Definition Unit.cpp:5896
void DealSpellDamage(SpellNonMeleeDamage *damageInfo, bool durabilityLoss)
int32 ModifyPower(Powers power, int32 val)
Definition Unit.cpp:4081
int32 HealBySpell(Unit *victim, SpellInfo const *spellInfo, uint32 addHealth, bool critical=false)
Definition Unit.cpp:2963
bool HasAura(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0) const
uint64 GetCharmerGUID() const
Definition Unit.h:2071
uint32 GetCreatureType() const
Definition Unit.cpp:4910
virtual bool IsImmunedToSpell(SpellInfo const *spellInfo) const
Definition Unit.cpp:3456
uint64 GetTransGUID() const override
Definition Unit.cpp:7217
AttackerSet const & getAttackers() const
Definition Unit.h:1463
bool IsMounted() const
Definition Unit.h:1742
HostileRefManager & getHostileRefManager()
Definition Unit.h:2466
void RemoveAurasByType(AuraType auraType, uint64 casterGUID=0, Aura *except=NULL, bool negative=true, bool positive=true)
AuraEffect * GetAuraEffect(uint32 spellId, uint8 effIndex, uint64 casterGUID=0) const
int32 GetPower(Powers power) const
Definition Unit.cpp:5237
void SendSpellNonMeleeDamageLog(SpellNonMeleeDamage *log)
Definition Unit.cpp:1766
bool IsImmunedToDamage(SpellSchoolMask meleeSchoolMask) const
Definition Unit.cpp:3415
bool IsAIEnabled
Definition Unit.h:2735
virtual bool IsImmunedToSpellEffect(SpellInfo const *spellInfo, uint32 index) const
Definition Unit.cpp:3520
AuraApplication * GetAuraApplication(uint32 spellId, uint64 casterGUID=0, uint64 itemCasterGUID=0, uint32 reqEffMask=0, AuraApplication *except=NULL) const
bool HasUnitState(const uint32 f) const
Definition Unit.h:1485
bool IsFriendlyTo(Unit const *unit) const
Definition Unit.cpp:2283
void CalculateSpellDamageTaken(SpellNonMeleeDamage *damageInfo, int32 damage, SpellInfo const *spellInfo, WeaponAttackType attackType=WeaponAttackType::BASE_ATTACK, bool crit=false)
bool IsControlledByPlayer() const
Definition Unit.h:2100
float GetTotalAuraMultiplierByMiscMask(AuraType auratype, uint32 misc_mask) const
uint8 getLevel() const
Definition Unit.h:1528
std::list< AuraEffect * > AuraEffectList
Definition Unit.h:1383
bool IsTotem() const
Definition Unit.h:1519
void SetStandState(uint8 state)
Definition Unit.cpp:5902
void ProcDamageAndSpell(Unit *victim, uint32 procAttacker, uint32 procVictim, uint32 procEx, uint32 amount, WeaponAttackType attType=WeaponAttackType::BASE_ATTACK, SpellInfo const *procSpell=NULL, SpellInfo const *procAura=NULL)
Definition UnitProc.cpp:53
bool IsInCombat() const
Definition Unit.h:1896
static IVMapManager * createOrGetVMapManager()
bool IsWithinDist3d(float x, float y, float z, float dist) const
Definition Object.cpp:1710
Map * GetMap() const
Definition Object.h:740
bool IsWithinLOSInMap(WorldObject const *obj) const
Definition Object.cpp:1656
float GetTransOffsetX() const
Definition Object.h:798
bool GetDistanceOrder(WorldObject const *obj1, WorldObject const *obj2, bool is3D=true) const
Definition Object.cpp:1752
float GetTransOffsetY() const
Definition Object.h:799
float GetTransOffsetZ() const
Definition Object.h:800
void GetFirstCollisionPosition(Position &pos, float dist, float angle)
Definition Object.cpp:3082
void GetContactPoint(WorldObject const *obj, float &x, float &y, float &z, float distance2d=CONTACT_DISTANCE) const
Definition Object.cpp:3094
float GetDistance(WorldObject const *obj) const
Definition Object.cpp:1666
float GetTransOffsetO() const
Definition Object.h:801
void GetNearPosition(Position &pos, float dist, float angle)
Definition Object.cpp:3076
bool IsWithinDist(WorldObject const *obj, float dist2compare, bool is3D=true) const
Definition Object.cpp:1730
float GetObjectSize() const
Definition Object.cpp:3100
virtual uint64 GetTransGUID() const
Definition Object.cpp:3571
void Initialize(Opcodes opcode, size_t newres=200)
Definition WorldPacket.h:31
LocaleConstant GetSessionDbLocaleIndex() const
uint32 GetRecruiterId() const
void SendPacket(WorldPacket const *packet, bool forced=false)
Send a packet to the client.
uint32 GetAccountId() const
Opcodes
List of Opcodes.
Definition Opcodes.h:21
@ SMSG_SPELL_CHANNEL_UPDATE
Definition Opcodes.h:978
@ SMSG_SPELL_EXECUTE_LOG
Definition Opcodes.h:982
@ SMSG_SPELL_CHANNEL_START
Definition Opcodes.h:977
@ SMSG_SPELL_FAILURE
Definition Opcodes.h:984
@ SMSG_SPELLINTERRUPTLOG
Definition Opcodes.h:973
@ SMSG_SPELL_DELAYED
Definition Opcodes.h:980
@ SMSG_SPELL_GO
Definition Opcodes.h:985
@ SMSG_SPELL_FAILED_OTHER
Definition Opcodes.h:983
@ SMSG_RESURRECT_REQUEST
Definition Opcodes.h:942
@ SMSG_PET_CAST_FAILED
Definition Opcodes.h:867
@ SMSG_SPELL_START
Definition Opcodes.h:989
#define sWorld
Definition World.h:910
@ RATE_POWER_RUNICPOWER_INCOME
Definition World.h:380
bool IsDisabledFor(DisableType type, uint32 entry, Unit const *unit, uint8 flags)
void RandomResizeList(std::list< T > &list, uint32 size)
Definition Containers.h:19
RuntimeMetrics & GetRuntimeMetrics()
@ SPELL_POWER_COST_UNSUPPORTED_POWER_TYPE
SpellPowerCostCalculationResult CalculateSpellPowerCosts(SpellPowerCostCalculationData const &data)
bool HasMechanic(uint32 mask, uint32 mechanic)
CellCoord ComputeCellCoord(float x, float y)
int32 SpellCharges
uint32 SpellTrigger
int32 SpellId
Definition Cell.h:37
void SetNoCreate()
Definition Cell.h:66
void Visit(CellCoord const &, TypeContainerVisitor< T, CONTAINER > &visitor, Map &, WorldObject const &, float) const
Definition CellImpl.h:109
SpellCastResult ErrorType
uint8 ConditionTarget
uint32 ErrorTextId
Condition * mLastFailedCondition
WorldObject * mConditionTargets[MAX_CONDITION_TARGETS]
SkillType GetRequiredLootSkill() const
Definition Creature.h:136
uint32 flags_extra
Definition Creature.h:129
float ratio
bool AllowMount
Definition Map.h:221
uint32 DisenchantID
_Spell Spells[MAX_ITEM_PROTO_SPELLS]
uint32 RequiredDisenchantSkill
uint32 ItemLimitCategory
uint32 Type[MAX_LOCK_CASE]
uint32 Index[MAX_LOCK_CASE]
uint32 Skill[MAX_LOCK_CASE]
bool isLooted() const
Definition LootMgr.h:332
bool IsInstance() const
bool IsRaid() const
float m_positionZ
Definition Object.h:289
float m_positionX
Definition Object.h:287
float GetPositionZ() const
Definition Object.h:330
float m_positionY
Definition Object.h:288
float GetOrientation() const
Definition Object.h:331
float GetRelativeAngle(Position const *pos) const
Definition Object.h:399
float GetPositionX() const
Definition Object.h:328
float GetPositionY() const
Definition Object.h:329
void RelocateOffset(Position const &offset)
Definition Object.cpp:1841
void Relocate(float x, float y)
Definition Object.h:302
WorldObjectSpellAreaTargetCheck(float range, Position const *position, Unit *caster, Unit *referer, SpellInfo const *spellInfo, SpellTargetCheckTypes selectionType, ConditionList *condList)
Definition Spell.cpp:8122
bool operator()(WorldObject *target)
Definition Spell.cpp:8126
bool operator()(WorldObject *target)
Definition Spell.cpp:8137
WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit *caster, SpellInfo const *spellInfo, SpellTargetCheckTypes selectionType, ConditionList *condList)
Definition Spell.cpp:8133
WorldObjectSpellNearbyTargetCheck(float range, Unit *caster, SpellInfo const *spellInfo, SpellTargetCheckTypes selectionType, ConditionList *condList)
Definition Spell.cpp:8107
bool operator()(WorldObject *target)
Definition Spell.cpp:8111
WorldObjectSpellTargetCheck(Unit *caster, Unit *referer, SpellInfo const *spellInfo, SpellTargetCheckTypes selectionType, ConditionList *condList)
Definition Spell.cpp:8032
ConditionSourceInfo * _condSrcInfo
Definition Spell.h:786
bool operator()(WorldObject *target)
Definition Spell.cpp:8048
SpellTargetCheckTypes _targetSelectionType
Definition Spell.h:785
bool operator()(WorldObject *target)
Definition Spell.cpp:8160
WorldObjectSpellTrajTargetCheck(float range, Position const *position, Unit *caster, SpellInfo const *spellInfo)
Definition Spell.cpp:8157
uint64 targetGUID
Definition Spell.h:676
SpellInfo const * triggeredSpell
Definition Spell.h:731
SpellInfo const * triggeredByAura
Definition Spell.h:732
uint64 timeDelay
Definition Spell.h:661
SpellMissInfo missCondition
Definition Spell.h:662
uint64 targetGUID
Definition Spell.h:660
SpellMissInfo reflectResult
Definition Spell.h:663
uint8 effectMask
Definition Spell.h:664
WorldLocation _position
Definition Spell.h:80
uint64 _transportGUID
Definition Spell.h:81
WorldLocation _transportOffset
Definition Spell.h:82
uint32 type[MAX_ITEM_ENCHANTMENT_EFFECTS]
uint32 slot
std::list< SpellLogExtraAttacksHelper > ExtraAttacks
Definition Spell.h:103
std::list< ObjectGuid > Targets
Definition Spell.h:101
std::list< uint32 > PetFeed
Definition Spell.h:104
std::list< SpellLogEnergizeHelper > Energizes
Definition Spell.h:102
std::list< uint32 > CreatedItems
Definition Spell.h:105
float ManaCostPercentageFloat
uint32 ShapeShiftSpellID
float ChannelCostPercentageFloat
uint32 spellId
uint32 powerType
uint32 manaPerSecond
uint32 manaCost
bool NoRuneCost() const
bool NoRunicPowerGain() const
uint32 RuneCost[4]
uint32 runePowerGain
Definition SpellMgr.h:346
float RadiusMod
Definition Spell.h:258
SpellValue(SpellInfo const *proto)
Definition Spell.cpp:491
int32 EffectBasePoints[MAX_SPELL_EFFECTS]
Definition Spell.h:256
uint32 MaxAffectedTargets
Definition Spell.h:257
uint8 AuraStackAmount
Definition Spell.h:259
uint32 Category