TrinityCore
Loading...
Searching...
No Matches
SpellScript.h
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef TRINITY_SPELL_SCRIPT_H
19#define TRINITY_SPELL_SCRIPT_H
20
21#include "ObjectGuid.h"
22#include "SharedDefines.h"
23#include "SpellAuraDefines.h"
24#include "Util.h"
25#include <stack>
26
27#ifdef TRINITY_API_USE_DYNAMIC_LINKING
28#include <memory>
29#endif
30
31class Aura;
32class AuraApplication;
33class AuraEffect;
34class Creature;
35class Corpse;
36class DamageInfo;
37class DispelInfo;
38class DynamicObject;
39class GameObject;
40class HealInfo;
41class Item;
42class ModuleReference;
43class Player;
44class ProcEventInfo;
45class Spell;
46class SpellEffectInfo;
47class SpellInfo;
48class SpellScript;
49class Unit;
50class WorldLocation;
51class WorldObject;
52struct SpellDestination;
53struct SpellModifier;
54struct SpellValue;
55enum Difficulty : int16;
56enum class ItemContext : uint8;
57
58using SpellEffectValue = double;
59
60#define SPELL_EFFECT_ANY ((uint16)-1)
61#define SPELL_AURA_ANY ((uint16)-1)
62
70#define SPELL_SCRIPT_STATE_END (SPELL_SCRIPT_STATE_UNLOADING + 1)
71
72// helper class from which SpellScript and AuraScript derive, use these classes instead
74{
75// internal use classes & functions
76// DO NOT OVERRIDE THESE IN SCRIPTS
77public:
78 SpellScriptBase() noexcept;
80
81 SpellScriptBase(SpellScriptBase const& right) = delete;
83 SpellScriptBase& operator=(SpellScriptBase const& right) = delete;
85
86 void _Register();
87 void _Unload();
88 void _Init(std::string const& scriptname, uint32 spellId);
89 std::string_view GetScriptName() const;
90
91protected:
92 virtual bool _Validate(SpellInfo const* entry);
93
94 // compile barrier to avoid instantiating operator+= in every script file
95 template <typename T>
96 class HookList : public ::HookList<T>
97 {
98 public:
99 HookList& operator+=(T&& t) noexcept;
100 };
101
103 {
104 public:
105 explicit EffectHook(uint8 effIndex);
106 EffectHook(EffectHook const& right) = delete;
107 EffectHook(EffectHook&& right) noexcept;
108 EffectHook& operator=(EffectHook const& right) = delete;
109 EffectHook& operator=(EffectHook&& right) noexcept;
110 virtual ~EffectHook();
111
112 uint32 GetAffectedEffectsMask(SpellInfo const* spellInfo) const;
113 bool IsEffectAffected(SpellInfo const* spellInfo, uint8 effIndex) const;
114 virtual bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const = 0;
115 std::string EffIndexToString() const;
116
117 protected:
119 };
120
121 template<typename>
123 {
124 using type = void;
125 };
126
127 template<typename Return, typename Class, typename... Args>
128 struct GetScriptClass<Return(Class::*)(Args...)>
129 {
130 using type = Class;
131 };
132
133 template<typename Return, typename Class, typename... Args>
134 struct GetScriptClass<Return(Class::*)(Args...) const>
135 {
136 using type = Class;
137 };
138
139 template<typename Return, typename Class, typename... Args>
140 struct GetScriptClass<Return(*)(Class&, Args...)>
141 {
142 using type = std::remove_const_t<Class>;
143 };
144
145 template<typename ScriptFunc>
147
148 template <typename Ret, typename BaseClass, typename... Args>
150 {
152 {
153 Ret(BaseClass::* Member)(Args...);
154 Ret(* Static)(BaseClass&, Args...);
155 };
156
157 static constexpr std::size_t Size = sizeof(SizeAndAlignment);
158 static constexpr std::size_t Alignment = alignof(SizeAndAlignment);
159
160 struct alignas(Alignment) StorageType : std::array<std::byte, Size> { };
161
162 template <typename ScriptFunc>
163 struct Impl
164 {
166
167 static Ret Invoke(BaseClass& script, Args... args, StorageType callImpl)
168 {
169 return std::invoke(reinterpret_cast<Impl const*>(callImpl.data())->Func, static_cast<ScriptClass&>(script), args...);
170 }
171
172 ScriptFunc Func;
173 };
174
176 Ret(* Thunk)(BaseClass&, Args..., StorageType);
177 };
178
179 std::string_view m_scriptName;
182
183private:
184
185#ifdef TRINITY_API_USE_DYNAMIC_LINKING
186
187 // Strong reference to keep the binary code loaded
188 std::shared_ptr<ModuleReference> m_moduleReference;
189
190#endif // #ifndef TRINITY_API_USE_DYNAMIC_LINKING
191
192public:
193 //
194 // SpellScript/AuraScript interface base
195 // these functions are safe to override, see notes below for usage instructions
196 //
197 // Function in which handler functions are registered, must be implemented in script
198 virtual void Register() = 0;
199 // Function called on server startup, if returns false script won't be used in core
200 // use for: dbc/template data presence/correctness checks
201 virtual bool Validate([[maybe_unused]] SpellInfo const* spellInfo) { return true; }
202 // Function called when script is created, if returns false script will be unloaded afterwards
203 // use for: initializing local script variables (DO NOT USE CONSTRUCTOR FOR THIS PURPOSE!)
204 virtual bool Load() { return true; }
205 // Function called when script is destroyed
206 // use for: deallocating memory allocated by script
207 virtual void Unload() { }
208 // Helpers
209 static bool ValidateSpellInfo(std::initializer_list<uint32> spellIds)
210 {
211 return ValidateSpellInfoImpl(spellIds.begin(), spellIds.end());
212 }
213
214 template <class T>
215 static bool ValidateSpellInfo(T const& spellIds)
216 {
217 return ValidateSpellInfoImpl(std::cbegin(spellIds), std::cend(spellIds));
218 }
219
220 static bool ValidateSpellEffect(std::initializer_list<std::pair<uint32, SpellEffIndex>> effects)
221 {
222 return ValidateSpellEffectsImpl(effects.begin(), effects.end());
223 }
224
225 template <class T>
226 static bool ValidateSpellEffect(T const& spellEffects)
227 {
228 return ValidateSpellEffectsImpl(std::cbegin(spellEffects), std::cend(spellEffects));
229 }
230
231private:
232 template<typename Iterator>
233 static bool ValidateSpellInfoImpl(Iterator begin, Iterator end)
234 {
235 bool allValid = true;
236 while (begin != end)
237 {
238 if (!ValidateSpellInfoImpl(*begin))
239 allValid = false;
240
241 ++begin;
242 }
243 return allValid;
244 }
245
246 template<typename Iterator>
247 static bool ValidateSpellEffectsImpl(Iterator begin, Iterator end)
248 {
249 bool allValid = true;
250 while (begin != end)
251 {
252 if (!ValidateSpellEffectImpl(begin->first, begin->second))
253 allValid = false;
254
255 ++begin;
256 }
257 return allValid;
258 }
259
260 static bool ValidateSpellInfoImpl(uint32 spellId);
261 static bool ValidateSpellEffectImpl(uint32 spellId, SpellEffIndex effectIndex);
262};
263
264// SpellScript interface - enum used for runtime checks of script function calls
291
292#define HOOK_SPELL_HIT_START SPELL_SCRIPT_HOOK_EFFECT_HIT
293#define HOOK_SPELL_HIT_END SPELL_SCRIPT_HOOK_AFTER_HIT + 1
294
296{
297 // internal use classes & functions
298 // DO NOT OVERRIDE THESE IN SCRIPTS
299 template <typename Ret, typename... Args>
301
302public:
303 class CastHandler final
304 {
305 public:
307
308 template<typename ScriptFunc>
309 explicit CastHandler(ScriptFunc handler)
310 {
311 using ScriptClass = GetScriptClass_t<ScriptFunc>;
312
313 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
314 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
315
316 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&>,
317 R""(CastHandler signature must be "void HandleCast()")"");
318
319 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
321 }
322
323 void Call(SpellScript* spellScript) const
324 {
325 return _invoker.Thunk(*spellScript, _invoker.ImplStorage);
326 }
327 private:
329 };
330
332 {
333 public:
335
336 template<typename ScriptFunc>
337 explicit CheckCastHandler(ScriptFunc handler)
338 {
339 using ScriptClass = GetScriptClass_t<ScriptFunc>;
340
341 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
342 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
343
344 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
345 static_assert(std::is_invocable_r_v<SpellCastResult, ScriptFunc, ScriptClass&>,
346 R""(CheckCastHandler signature must be "SpellCastResult CheckCast()")"");
347 else
348 static_assert(std::is_invocable_r_v<SpellCastResult, ScriptFunc, SpellScript&>,
349 R""(CheckCastHandler signature must be "static SpellCastResult CheckCast(your_script_class& script, SpellScript&)")"");
350
351 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
353 }
354
355 SpellCastResult Call(SpellScript* spellScript) const
356 {
357 return _invoker.Thunk(*spellScript, _invoker.ImplStorage);
358 }
359 private:
361 };
362
364 {
365 public:
366 EffectBase(uint8 effIndex, uint16 effName);
367 EffectBase(EffectBase const& right) = delete;
368 EffectBase(EffectBase&& right) noexcept;
369 EffectBase& operator=(EffectBase const& right) = delete;
370 EffectBase& operator=(EffectBase&& right) noexcept;
372 std::string ToString() const;
373 bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const override;
374 private:
376 };
377
378 class EffectHandler final : public EffectBase
379 {
380 public:
382
383 template<typename ScriptFunc>
384 explicit EffectHandler(ScriptFunc handler, uint8 effIndex, uint16 effName)
385 : EffectBase(effIndex, effName)
386 {
387 using ScriptClass = GetScriptClass_t<ScriptFunc>;
388
389 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
390 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
391
392 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, SpellEffIndex>,
393 R""(EffectHandler signature must be "void HandleEffect(SpellEffIndex effIndex)")"");
394
395 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
397 }
398
399 void Call(SpellScript* spellScript, SpellEffIndex effIndex) const
400 {
401 return _invoker.Thunk(*spellScript, effIndex, _invoker.ImplStorage);
402 }
403 private:
405 };
406
408 {
409 public:
411
412 template<typename ScriptFunc>
413 explicit BeforeHitHandler(ScriptFunc handler)
414 {
415 using ScriptClass = GetScriptClass_t<ScriptFunc>;
416
417 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
418 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
419
420 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, SpellMissInfo>,
421 R""(BeforeHitHandler signature must be "void HandleBeforeHit(SpellMissInfo missInfo)")"");
422
423 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
425 }
426
427 void Call(SpellScript* spellScript, SpellMissInfo missInfo) const
428 {
429 return _invoker.Thunk(*spellScript, missInfo, _invoker.ImplStorage);
430 }
431 private:
433 };
434
435 class HitHandler final
436 {
437 public:
439
440 template<typename ScriptFunc>
441 explicit HitHandler(ScriptFunc handler)
442 {
443 using ScriptClass = GetScriptClass_t<ScriptFunc>;
444
445 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
446 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
447
448 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&>,
449 R""(HitHandler signature must be "void HandleHit()")"");
450
451 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
453 }
454
455 void Call(SpellScript* spellScript) const
456 {
457 return _invoker.Thunk(*spellScript, _invoker.ImplStorage);
458 }
459 private:
461 };
462
464 {
465 public:
467
468 template<typename ScriptFunc>
469 explicit OnCalcCritChanceHandler(ScriptFunc handler)
470 {
471 using ScriptClass = GetScriptClass_t<ScriptFunc>;
472
473 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
474 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
475
476 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
477 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, Unit const*, float&>,
478 R""(OnCalcCritChanceHandler signature must be "void CalcCritChance(Unit const* victim, float& critChance)")"");
479 else
480 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, Unit const*, float&>,
481 R""(OnCalcCritChanceHandler signature must be "static void CalcCritChance(your_script_class& script, Unit const* victim, float& critChance)")"");
482
483 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
485 }
486
487 void Call(SpellScript* spellScript, Unit const* victim, float& critChance) const
488 {
489 return _invoker.Thunk(*spellScript, victim, critChance, _invoker.ImplStorage);
490 }
491 private:
493 };
494
496 {
497 public:
498 TargetHook(uint8 effectIndex, uint16 targetType, bool area, bool dest);
499 TargetHook(TargetHook const& right) = delete;
500 TargetHook(TargetHook&& right) noexcept;
501 TargetHook& operator=(TargetHook const& right) = delete;
502 TargetHook& operator=(TargetHook&& right) noexcept;
503 virtual ~TargetHook();
504 bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const override;
505 std::string ToString() const;
506 uint16 GetTarget() const { return _targetType; }
507 protected:
509 bool _area;
510 bool _dest;
511 };
512
514 {
515 public:
517
518 template<typename ScriptFunc>
519 explicit ObjectAreaTargetSelectHandler(ScriptFunc handler, uint8 effIndex, uint16 targetType)
520 : TargetHook(effIndex, targetType, true, false)
521 {
522 using ScriptClass = GetScriptClass_t<ScriptFunc>;
523
524 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
525 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
526
527 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
528 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, std::list<WorldObject*>&>,
529 R""(ObjectAreaTargetSelectHandler signature must be "void SetTargets(std::list<WorldObject*>& targets)")"");
530 else
531 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, std::list<WorldObject*>&>,
532 R""(ObjectAreaTargetSelectHandler signature must be "static void SetTargets(your_script_class& script, std::list<WorldObject*>& targets)")"");
533
534 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
536 }
537
538 void Call(SpellScript* spellScript, std::list<WorldObject*>& targets) const
539 {
540 return _invoker.Thunk(*spellScript, targets, _invoker.ImplStorage);
541 }
542
544 {
545 return _invoker.ImplStorage == other._invoker.ImplStorage;
546 }
547 private:
549 };
550
552 {
553 public:
555
556 template<typename ScriptFunc>
557 explicit ObjectTargetSelectHandler(ScriptFunc handler, uint8 effIndex, uint16 targetType)
558 : TargetHook(effIndex, targetType, false, false)
559 {
560 using ScriptClass = GetScriptClass_t<ScriptFunc>;
561
562 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
563 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
564
565 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
566 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, WorldObject*&>,
567 R""(ObjectTargetSelectHandler signature must be "void SetTarget(WorldObject*& target)")"");
568 else
569 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, WorldObject*&>,
570 R""(ObjectTargetSelectHandler signature must be "static void SetTarget(your_script_class& script, WorldObject*& target)")"");
571
572 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
574 }
575
576 void Call(SpellScript* spellScript, WorldObject*& target) const
577 {
578 return _invoker.Thunk(*spellScript, target, _invoker.ImplStorage);
579 }
580
582 {
583 return _invoker.ImplStorage == other._invoker.ImplStorage;
584 }
585 private:
587 };
588
590 {
591 public:
593
594 template<typename ScriptFunc>
595 explicit DestinationTargetSelectHandler(ScriptFunc handler, uint8 effIndex, uint16 targetType)
596 : TargetHook(effIndex, targetType, false, true)
597 {
598 using ScriptClass = GetScriptClass_t<ScriptFunc>;
599
600 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
601 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
602
603 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
604 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, SpellDestination&>,
605 R""(DestinationTargetSelectHandler signature must be "void SetTarget(SpellDestination& target)")"");
606 else
607 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, SpellDestination&>,
608 R""(DestinationTargetSelectHandler signature must be "static void SetTarget(your_script_class& script, SpellDestination& target)")"");
609
610 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
612 }
613
614 void Call(SpellScript* spellScript, SpellDestination& target) const
615 {
616 return _invoker.Thunk(*spellScript, target, _invoker.ImplStorage);
617 }
618 private:
620 };
621
623 {
624 public:
626
627 template<typename ScriptFunc>
628 explicit DamageAndHealingCalcHandler(ScriptFunc handler)
629 {
630 using ScriptClass = GetScriptClass_t<ScriptFunc>;
631
632 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
633 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
634
635 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
636 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, SpellEffectInfo const&, Unit*, int32&, int32&, float&>,
637 R""(DamageAndHealingCalcHandler signature must be "void CalcDamage(SpellEffectInfo const& spellEffectInfo, Unit* victim, int32& damageOrHealing, int32& flatMod, float& pctMod)")"");
638 else
639 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, SpellEffectInfo const&, Unit*, int32&, int32&, float&>,
640 R""(DamageAndHealingCalcHandler signature must be "static void CalcDamage(your_script_class& script, SpellEffectInfo const& spellEffectInfo, Unit* victim, int32& damageOrHealing, int32& flatMod, float& pctMod)")"");
641
642 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
644 }
645
646 void Call(SpellScript* spellScript, SpellEffectInfo const& spellEffectInfo, Unit* victim, int32& damageOrHealing, int32& flatMod, float& pctMod) const
647 {
648 return _invoker.Thunk(*spellScript, spellEffectInfo, victim, damageOrHealing, flatMod, pctMod, _invoker.ImplStorage);
649 }
650 private:
652 };
653
655 {
656 public:
658
659 template<typename ScriptFunc>
660 explicit OnCalculateResistAbsorbHandler(ScriptFunc handler)
661 {
662 using ScriptClass = GetScriptClass_t<ScriptFunc>;
663
664 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
665 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
666
667 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
668 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, DamageInfo const&, uint32&, int32&>,
669 R""(OnCalculateResistAbsorbHandler signature must be "void CalcAbsorbResist(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount)")"");
670 else
671 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, DamageInfo const&, uint32&, int32&>,
672 R""(OnCalculateResistAbsorbHandler signature must be "static void CalcAbsorbResist(your_script_class& script, DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount)")"");
673
674 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
676 }
677
678 void Call(SpellScript* spellScript, DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount) const
679 {
680 return _invoker.Thunk(*spellScript, damageInfo, resistAmount, absorbAmount, _invoker.ImplStorage);
681 }
682 private:
684 };
685
687 {
688 public:
690
691 template<typename ScriptFunc>
692 explicit EmpowerStageCompletedHandler(ScriptFunc handler)
693 {
694 using ScriptClass = GetScriptClass_t<ScriptFunc>;
695
696 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
697 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
698
699 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, int32>,
700 R""(EmpowerStageCompleted/EmpowerCompleted signature must be "void HandleEmpowerStageCompleted(int32 completedStagesCount)")"");
701
702 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
704 }
705
706 void Call(SpellScript* spellScript, int32 completedStagesCount) const
707 {
708 return _invoker.Thunk(*spellScript, completedStagesCount, _invoker.ImplStorage);
709 }
710 private:
712 };
713
714 // left for custom compatibility only, DO NOT USE
715 #define PrepareSpellScript(CLASSNAME)
716
717 SpellScript() noexcept;
719 bool _Validate(SpellInfo const* entry) override;
720 bool _Load(Spell* spell);
721 void _InitHit();
722 bool _IsEffectPrevented(SpellEffIndex effIndex) const { return (m_hitPreventEffectMask & (1 << effIndex)) != 0; }
723 bool _IsDefaultEffectPrevented(SpellEffIndex effIndex) const { return (m_hitPreventDefaultEffectMask & (1 << effIndex)) != 0; }
724 void _PrepareScriptCall(SpellScriptHookType hookType);
725 void _FinishScriptCall();
726 bool IsInCheckCastHook() const;
727 bool IsAfterTargetSelectionPhase() const;
728 bool IsInTargetHook() const;
729 bool IsInModifiableHook() const;
730 bool IsInHitPhase() const;
731 bool IsInEffectHook() const;
732private:
736public:
737 //
738 // SpellScript interface
739 //
740 // example: void OnPrecast() override { }
741 virtual void OnPrecast() { }
742 //
743 // hooks to which you can attach your functions
744 //
745 // example: BeforeCast += SpellCastFn(class::function);
747 // example: OnCast += SpellCastFn(class::function);
749 // example: AfterCast += SpellCastFn(class::function);
751 #define SpellCastFn(F) CastHandler(&F)
752
753 // example: OnCheckCast += SpellCheckCastFn();
754 // where function is SpellCastResult function()
756 #define SpellCheckCastFn(F) CheckCastHandler(&F)
757
758 // example: int32 CalcCastTime(int32 castTime) override { return 1500; }
759 virtual int32 CalcCastTime(int32 castTime) { return castTime; }
760
761 // example: OnEffect**** += SpellEffectFn(class::function, EffectIndexSpecifier, EffectNameSpecifier);
762 // where function is void function(SpellEffIndex effIndex)
768 #define SpellEffectFn(F, I, N) EffectHandler(&F, I, N)
769
770 // example: BeforeHit += BeforeSpellHitFn(class::function);
771 // where function is void function(SpellMissInfo missInfo)
773 #define BeforeSpellHitFn(F) BeforeHitHandler(&F)
774
775 // example: OnHit += SpellHitFn(class::function);
777 // example: AfterHit += SpellHitFn(class::function);
779 // where function is: void function()
780 #define SpellHitFn(F) HitHandler(&F)
781
782 // example: OnCalcCritChance += SpellOnCalcCritChanceFn(class::function);
783 // where function is: void function(Unit* victim, float& critChance)
785 #define SpellOnCalcCritChanceFn(F) OnCalcCritChanceHandler(&F)
786
787 // example: OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier);
788 // where function is void function(std::list<WorldObject*>& targets)
790 #define SpellObjectAreaTargetSelectFn(F, I, N) ObjectAreaTargetSelectHandler(&F, I, N)
791
792 // example: OnObjectTargetSelect += SpellObjectTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier);
793 // where function is void function(WorldObject*& target)
795 #define SpellObjectTargetSelectFn(F, I, N) ObjectTargetSelectHandler(&F, I, N)
796
797 // example: OnDestinationTargetSelect += SpellDestinationTargetSelectFn(class::function, EffectIndexSpecifier, TargetsNameSpecifier);
798 // where function is void function(SpellDestination& target)
800 #define SpellDestinationTargetSelectFn(F, I, N) DestinationTargetSelectHandler(&F, I, N)
801
802 // example: CalcDamage += SpellCalcDamageFn(class::function);
803 // where function is void function(SpellEffectInfo const& effectInfo, Unit* victim, int32& damage, int32& flatMod, float& pctMod)
805 #define SpellCalcDamageFn(F) DamageAndHealingCalcHandler(&F)
806
807 // example: CalcHealing += SpellCalcHealingFn(class::function);
808 // where function is void function(SpellEffectInfo const& effectInfo, Unit* victim, int32& healing, int32& flatMod, float& pctMod)
810 #define SpellCalcHealingFn(F) DamageAndHealingCalcHandler(&F)
811
812 // example: OnCalculateResistAbsorb += SpellOnResistAbsorbCalculateFn(class::function);
813 // where function is void function(DamageInfo const& damageInfo, uint32& resistAmount, int32& absorbAmount)
815 #define SpellOnResistAbsorbCalculateFn(F) OnCalculateResistAbsorbHandler(&F)
816
817 // example: OnEmpowerStageCompleted += SpellOnEmpowerStageCompletedFn(class::function);
818 // where function is void function(int32 completedStages)
820 #define SpellOnEmpowerStageCompletedFn(F) EmpowerStageCompletedHandler(&F)
821
822 // example: OnEmpowerCompleted += SpellOnEmpowerCompletedFn(class::function);
823 // where function is void function(int32 completedStages)
825 #define SpellOnEmpowerCompletedFn(F) EmpowerStageCompletedHandler(&F)
826
827 // hooks are executed in following order, at specified event of spell:
828 // 1. OnPrecast - executed during spell preparation (before cast bar starts)
829 // 2. BeforeCast - executed when spell preparation is finished (when cast bar becomes full) before cast is handled
830 // 3. OnCheckCast - allows to override result of CheckCast function
831 // 4a. OnObjectAreaTargetSelect - executed just before adding selected targets to final target list (for area targets)
832 // 4b. OnObjectTargetSelect - executed just before adding selected target to final target list (for single unit targets)
833 // 4c. OnDestinationTargetSelect - executed just before adding selected target to final target list (for destination targets)
834 // 5. OnCast - executed just before spell is launched (creates missile) or executed
835 // 6. AfterCast - executed after spell missile is launched and immediate spell actions are done
836 // 7. OnEffectLaunch - executed just before specified effect handler call - when spell missile is launched
837 // 8. OnCalcCritChance - executed just after specified effect handler call - when spell missile is launched - called for each target from spell target map
838 // 9. OnEffectLaunchTarget - executed just before specified effect handler call - when spell missile is launched - called for each target from spell target map
839 // 10a. CalcDamage - executed during specified effect handler call - when spell missile is launched - called for each target from spell target map
840 // 10b. CalcHealing - executed during specified effect handler call - when spell missile is launched - called for each target from spell target map
841 // 11. OnCalculateResistAbsorb - executed when damage resist/absorbs is calculated - before spell hit target
842 // 12. OnEffectHit - executed just before specified effect handler call - when spell missile hits dest
843 // 13. BeforeHit - executed just before spell hits a target - called for each target from spell target map
844 // 14. OnEffectHitTarget - executed just before specified effect handler call - called for each target from spell target map
845 // 15. OnHit - executed just before spell deals damage and procs auras - when spell hits target - called for each target from spell target map
846 // 16. AfterHit - executed just after spell finishes all it's jobs for target - called for each target from spell target map
847 // 17. OnEmpowerStageCompleted - executed when empowered spell completes each stage
848 // 18. OnEmpowerCompleted - executed when empowered spell is released
849
850 // this hook is only executed after a successful dispel of any aura
851 // OnEffectSuccessfulDispel - executed just after effect successfully dispelled aura(s)
852
853 //
854 // methods allowing interaction with Spell object
855 //
856 // methods useable during all spell handling phases
857 Unit* GetCaster() const;
858 GameObject* GetGObjCaster() const;
859 Unit* GetOriginalCaster() const;
860 SpellInfo const* GetSpellInfo() const;
861 SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const;
862 SpellValue const* GetSpellValue() const;
863
864 // methods useable after spell is prepared
865 // accessors to the explicit targets of the spell
866 // explicit target - target selected by caster (player, game client, or script - DoCast(explicitTarget, ...), required for spell to be cast
867 // examples:
868 // -shadowstep - explicit target is the unit you want to go behind of
869 // -chain heal - explicit target is the unit to be healed first
870 // -holy nova/arcane explosion - explicit target = NULL because target you are selecting doesn't affect how spell targets are selected
871 // you can determine if spell requires explicit targets by dbc columns:
872 // - Targets - mask of explicit target types
873 // - ImplicitTargetXX set to TARGET_XXX_TARGET_YYY, _TARGET_ here means that explicit target is used by the effect, so spell needs one too
874
875 // returns: WorldLocation which was selected as a spell destination or NULL
876 WorldLocation const* GetExplTargetDest() const;
877
878 void SetExplTargetDest(WorldLocation const& loc);
879
880 // returns: WorldObject which was selected as an explicit spell target or NULL if there's no target
881 WorldObject* GetExplTargetWorldObject() const;
882
883 // returns: Unit which was selected as an explicit spell target or NULL if there's no target
884 Unit* GetExplTargetUnit() const;
885
886 // returns: GameObject which was selected as an explicit spell target or NULL if there's no target
887 GameObject* GetExplTargetGObj() const;
888
889 // returns: Item which was selected as an explicit spell target or NULL if there's no target
890 Item* GetExplTargetItem() const;
891
892 // methods usable only after spell targets have been fully selected
893 int64 GetUnitTargetCountForEffect(SpellEffIndex effect) const;
894 int32 GetUnitTargetIndexForEffect(ObjectGuid const& target, SpellEffIndex effect) const;
895 int64 GetGameObjectTargetCountForEffect(SpellEffIndex effect) const;
896 int64 GetItemTargetCountForEffect(SpellEffIndex effect) const;
897 int64 GetCorpseTargetCountForEffect(SpellEffIndex effect) const;
898
899 // methods useable only during spell hit on target, or during spell launch on target:
900 // returns: target of current effect if it was Unit otherwise NULL
901 Unit* GetHitUnit() const;
902 // returns: target of current effect if it was Creature otherwise NULL
903 Creature* GetHitCreature() const;
904 // returns: target of current effect if it was Player otherwise NULL
905 Player* GetHitPlayer() const;
906 // returns: target of current effect if it was Item otherwise NULL
907 Item* GetHitItem() const;
908 // returns: target of current effect if it was GameObject otherwise NULL
909 GameObject* GetHitGObj() const;
910 // returns: target of current effect if it was Corpse otherwise nullptr
911 Corpse* GetHitCorpse() const;
912 // returns: destination of current effect
913 WorldLocation* GetHitDest() const;
914 // setter/getter for for damage done by spell to target of spell hit
915 // returns damage calculated before hit, and real dmg done after hit
916 int32 GetHitDamage() const;
917 void SetHitDamage(int32 damage);
918 void PreventHitDamage() { SetHitDamage(0); }
919 // setter/getter for for heal done by spell to target of spell hit
920 // returns healing calculated before hit, and real dmg done after hit
921 int32 GetHitHeal() const;
922 void SetHitHeal(int32 heal);
923 void PreventHitHeal() { SetHitHeal(0); }
924 // returns: true if spell critically hits current HitUnit
925 bool IsHitCrit() const;
926 Spell* GetSpell() const { return m_spell; }
927 // returns current spell hit target aura
928 Aura* GetHitAura(bool dynObjAura = false, bool withRemoved = false) const;
929 // prevents applying aura on current spell hit target
930 void PreventHitAura();
931
932 // prevents effect execution on current spell hit target
933 // including other effect/hit scripts
934 // will not work on aura/damage/heal
935 // will not work if effects were already handled
936 void PreventHitEffect(SpellEffIndex effIndex);
937
938 // prevents default effect execution on current spell hit target
939 // will not work on aura/damage/heal effects
940 // will not work if effects were already handled
941 void PreventHitDefaultEffect(SpellEffIndex effIndex);
942
943 // method available only in EffectHandler method
944 SpellEffectInfo const& GetEffectInfo() const;
945 int32 GetEffectValueAsInt() const;
946 SpellEffectValue GetEffectValue() const;
947 void SetEffectValue(SpellEffectValue value);
948 float GetEffectVariance() const;
949 void SetEffectVariance(float variance);
950
951 // returns: cast item if present.
952 Item* GetCastItem() const;
953
954 // Creates item. Calls Spell::DoCreateItem method.
955 void CreateItem(uint32 itemId, ItemContext context);
956
957 // Returns SpellInfo from the spell that triggered the current one
958 SpellInfo const* GetTriggeringSpell() const;
959
960 // finishes spellcast prematurely with selected error message
961 void FinishCast(SpellCastResult result, int32* param1 = nullptr, int32* param2 = nullptr);
962
963 void SetCustomCastResultMessage(SpellCustomErrors result);
964
965 // returns desired cast difficulty for triggered spells
966 Difficulty GetCastDifficulty() const;
967};
968
969// AuraScript interface - enum used for runtime checks of script function calls
1004/*
1005#define HOOK_AURA_EFFECT_START HOOK_AURA_EFFECT_APPLY
1006#define HOOK_AURA_EFFECT_END HOOK_AURA_EFFECT_CALC_SPELLMOD + 1
1007#define HOOK_AURA_EFFECT_COUNT HOOK_AURA_EFFECT_END - HOOK_AURA_EFFECT_START
1008*/
1010{
1011 // internal use classes & functions
1012 // DO NOT OVERRIDE THESE IN SCRIPTS
1013 template <typename Ret, typename... Args>
1015
1016public:
1018 {
1019 public:
1021
1022 template<typename ScriptFunc>
1023 explicit CheckAreaTargetHandler(ScriptFunc handler)
1024 {
1025 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1026
1027 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1028 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1029
1030 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1031 static_assert(std::is_invocable_r_v<bool, ScriptFunc, ScriptClass&, Unit*>,
1032 R""(CheckAreaTargetHandler signature must be "bool CheckTarget(Unit* target)")"");
1033 else
1034 static_assert(std::is_invocable_r_v<bool, ScriptFunc, ScriptClass&, Unit*>,
1035 R""(CheckAreaTargetHandler signature must be "static bool CheckTarget(your_script_class& script, Unit* target)")"");
1036
1037 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1039 }
1040
1041 bool Call(AuraScript* auraScript, Unit* target) const
1042 {
1043 return _invoker.Thunk(*auraScript, target, _invoker.ImplStorage);
1044 }
1045 private:
1047 };
1048
1050 {
1051 public:
1053
1054 template<typename ScriptFunc>
1055 explicit AuraDispelHandler(ScriptFunc handler)
1056 {
1057 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1058
1059 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1060 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1061
1062 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1063 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, DispelInfo*>,
1064 R""(AuraDispelHandler signature must be "void HandleDispel(DispelInfo* dispelInfo)")"");
1065 else
1066 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, DispelInfo*>,
1067 R""(AuraDispelHandler signature must be "static void HandleDispel(your_script_class& script, DispelInfo* dispelInfo)")"");
1068
1069 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1071 }
1072
1073 void Call(AuraScript* auraScript, DispelInfo* dispelInfo) const
1074 {
1075 return _invoker.Thunk(*auraScript, dispelInfo, _invoker.ImplStorage);
1076 }
1077 private:
1079 };
1080
1082 {
1083 public:
1085
1086 template<typename ScriptFunc>
1087 explicit AuraHeartbeatHandler(ScriptFunc handler)
1088 {
1089 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1090
1091 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1092 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1093
1094 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1095 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass>,
1096 R""(AuraHeartbeatHandler signature must be "void HandleHeartbeat()")"");
1097 else
1098 static_assert(std::is_invocable_r_v<void, ScriptFunc>,
1099 R""(AuraHeartbeatHandler signature must be "static void HandleHeartbeat(your_script_class& script)")"");
1100
1101 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1103 }
1104
1105 void Call(AuraScript* auraScript) const
1106 {
1107 return _invoker.Thunk(*auraScript, _invoker.ImplStorage);
1108 }
1109 private:
1111 };
1112
1114 {
1115 public:
1116 EffectBase(uint8 effIndex, uint16 auraType);
1117 EffectBase(EffectBase const& right) = delete;
1118 EffectBase(EffectBase&& right) noexcept;
1119 EffectBase& operator=(EffectBase const& right) = delete;
1120 EffectBase& operator=(EffectBase&& right) noexcept;
1121 virtual ~EffectBase();
1122 std::string ToString() const;
1123 bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) const override;
1124 private:
1126 };
1127
1129 {
1130 public:
1132
1133 template<typename ScriptFunc>
1134 explicit EffectPeriodicHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1135 : EffectBase(effIndex, auraType)
1136 {
1137 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1138
1139 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1140 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1141
1142 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1143 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*>,
1144 R""(EffectPeriodicHandler signature must be "void HandlePeriodic(AuraEffect const* aurEff)")"");
1145 else
1146 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*>,
1147 R""(EffectPeriodicHandler signature must be "static void HandlePeriodic(your_script_class& script, AuraEffect const* aurEff)")"");
1148
1149 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1151 }
1152
1153 void Call(AuraScript* auraScript, AuraEffect const* aurEff) const
1154 {
1155 return _invoker.Thunk(*auraScript, aurEff, _invoker.ImplStorage);
1156 }
1157 private:
1159 };
1160
1162 {
1163 public:
1165
1166 template<typename ScriptFunc>
1167 explicit EffectUpdatePeriodicHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1168 : EffectBase(effIndex, auraType)
1169 {
1170 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1171
1172 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1173 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1174
1175 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1176 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect*>,
1177 R""(EffectUpdatePeriodicHandler signature must be "void HandleUpdatePeriodic(AuraEffect* aurEff)")"");
1178 else
1179 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect*>,
1180 R""(EffectUpdatePeriodicHandler signature must be "static void HandleUpdatePeriodic(your_script_class& script, AuraEffect* aurEff)")"");
1181
1182 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1184 }
1185
1186 void Call(AuraScript* auraScript, AuraEffect* aurEff) const
1187 {
1188 return _invoker.Thunk(*auraScript, aurEff, _invoker.ImplStorage);
1189 }
1190 private:
1192 };
1193
1195 {
1196 public:
1198
1199 template<typename ScriptFunc>
1200 explicit EffectCalcAmountHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1201 : EffectBase(effIndex, auraType)
1202 {
1203 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1204
1205 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1206 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1207
1208 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1209 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, SpellEffectValue&, bool&>,
1210 R""(EffectCalcAmountHandler signature must be "void CalcAmount(AuraEffect const* aurEff, SpellEffectValue& amount, bool& canBeRecalculated)")"");
1211 else
1212 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, SpellEffectValue&, bool&>,
1213 R""(EffectCalcAmountHandler signature must be "static void CalcAmount(your_script_class& script, AuraEffect const* aurEff, SpellEffectValue& amount, bool& canBeRecalculated)")"");
1214
1215 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1217 }
1218
1219 void Call(AuraScript* auraScript, AuraEffect const* aurEff, SpellEffectValue& amount, bool& canBeRecalculated) const
1220 {
1221 return _invoker.Thunk(*auraScript, aurEff, amount, canBeRecalculated, _invoker.ImplStorage);
1222 }
1223 private:
1225 };
1226
1228 {
1229 public:
1231
1232 template<typename ScriptFunc>
1233 explicit EffectCalcPeriodicHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1234 : EffectBase(effIndex, auraType)
1235 {
1236 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1237
1238 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1239 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1240
1241 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1242 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, bool&, int32&>,
1243 R""(EffectCalcPeriodicHandler signature must be "void CalcPeriodic(AuraEffect const* aurEff, bool& isPeriodic, int32& periodicTimer)")"");
1244 else
1245 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, bool&, int32&>,
1246 R""(EffectCalcPeriodicHandler signature must be "static void CalcPeriodic(your_script_class& script, AuraEffect const* aurEff, bool& isPeriodic, int32& periodicTimer)")"");
1247
1248 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1250 }
1251
1252 void Call(AuraScript* auraScript, AuraEffect const* aurEff, bool& isPeriodic, int32& periodicTimer) const
1253 {
1254 return _invoker.Thunk(*auraScript, aurEff, isPeriodic, periodicTimer, _invoker.ImplStorage);
1255 }
1256 private:
1258 };
1259
1261 {
1262 public:
1264
1265 template<typename ScriptFunc>
1266 explicit EffectCalcSpellModHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1267 : EffectBase(effIndex, auraType)
1268 {
1269 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1270
1271 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1272 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1273
1274 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1275 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, SpellModifier*&>,
1276 R""(EffectCalcSpellModHandler signature must be "void CalcSpellMod(AuraEffect const* aurEff, SpellModifier*& spellMod)")"");
1277 else
1278 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, SpellModifier*&>,
1279 R""(EffectCalcSpellModHandler signature must be "static void CalcSpellMod(your_script_class& script, AuraEffect const* aurEff, SpellModifier*& spellMod)")"");
1280
1281 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1283 }
1284
1285 void Call(AuraScript* auraScript, AuraEffect const* aurEff, SpellModifier*& spellMod) const
1286 {
1287 return _invoker.Thunk(*auraScript, aurEff, spellMod, _invoker.ImplStorage);
1288 }
1289 private:
1291 };
1292
1294 {
1295 public:
1297
1298 template<typename ScriptFunc>
1299 explicit EffectCalcCritChanceHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1300 : EffectBase(effIndex, auraType)
1301 {
1302 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1303
1304 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1305 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1306
1307 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1308 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, Unit const*, float&>,
1309 R""(EffectCalcCritChanceHandler signature must be "void CalcCritChance(AuraEffect const* aurEff, Unit const* victim, float& critChance)")"");
1310 else
1311 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, Unit const*, float&>,
1312 R""(EffectCalcCritChanceHandler signature must be "static void CalcCritChance(your_script_class& script, AuraEffect const* aurEff, Unit const* victim, float& critChance)")"");
1313
1314 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1316 }
1317
1318 void Call(AuraScript* auraScript, AuraEffect const* aurEff, Unit const* victim, float& critChance) const
1319 {
1320 return _invoker.Thunk(*auraScript, aurEff, victim, critChance, _invoker.ImplStorage);
1321 }
1322 private:
1324 };
1325
1327 {
1328 public:
1330
1331 template<typename ScriptFunc>
1332 explicit EffectCalcDamageAndHealingHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1333 : EffectBase(effIndex, auraType)
1334 {
1335 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1336
1337 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1338 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1339
1340 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1341 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, Unit*, int32&, int32&, float&>,
1342 R""(EffectCalcDamageAndHealingHandler signature must be "void CalcDamageAndHealing(AuraEffect const* aurEff, Unit* victim, int32& damageOrHealing, int32& flatMod, float& pctMod)")"");
1343 else
1344 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, Unit*, int32&, int32&, float&>,
1345 R""(EffectCalcDamageAndHealingHandler signature must be "static void CalcDamageAndHealing(your_script_class& script, AuraEffect const* aurEff, Unit* victim, int32& damageOrHealing, int32& flatMod, float& pctMod)")"");
1346
1347 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1349 }
1350
1351 void Call(AuraScript* auraScript, AuraEffect const* aurEff, Unit* victim, int32& damageOrHealing, int32& flatMod, float& pctMod) const
1352 {
1353 return _invoker.Thunk(*auraScript, aurEff, victim, damageOrHealing, flatMod, pctMod, _invoker.ImplStorage);
1354 }
1355 private:
1357 };
1358
1359 class EffectApplyHandler final : public EffectBase
1360 {
1361 public:
1363
1364 template<typename ScriptFunc>
1365 explicit EffectApplyHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType, AuraEffectHandleModes mode)
1366 : EffectBase(effIndex, auraType), _mode(mode)
1367 {
1368 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1369
1370 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1371 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1372
1373 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1374 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, AuraEffectHandleModes>,
1375 R""(EffectApplyHandler signature must be "void HandleApplyOrRemove(AuraEffect const* aurEff, AuraEffectHandleModes mode)")"");
1376 else
1377 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect const*, AuraEffectHandleModes>,
1378 R""(EffectApplyHandler signature must be "static void HandleApplyOrRemove(your_script_class& script, AuraEffect const* aurEff, AuraEffectHandleModes mode)")"");
1379
1380 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1382 }
1383
1384 void Call(AuraScript* auraScript, AuraEffect const* aurEff, AuraEffectHandleModes mode) const
1385 {
1386 if (!(_mode & mode))
1387 return;
1388
1389 return _invoker.Thunk(*auraScript, aurEff, mode, _invoker.ImplStorage);
1390 }
1391 private:
1394 };
1395
1396 class EffectAbsorbHandler final : public EffectBase
1397 {
1398 public:
1400
1401 template<typename ScriptFunc>
1402 explicit EffectAbsorbHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1403 : EffectBase(effIndex, auraType)
1404 {
1405 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1406
1407 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1408 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1409
1410 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1411 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect*, DamageInfo&, uint32&>,
1412 R""(EffectAbsorbHandler signature must be "void HandleAbsorb(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount)")"");
1413 else
1414 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect*, DamageInfo&, uint32&>,
1415 R""(EffectAbsorbHandler signature must be "static void HandleAbsorb(your_script_class& script, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount)")"");
1416
1417 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1419 }
1420
1421 void Call(AuraScript* auraScript, AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount) const
1422 {
1423 return _invoker.Thunk(*auraScript, aurEff, dmgInfo, absorbAmount, _invoker.ImplStorage);
1424 }
1425 private:
1427 };
1428
1430 {
1431 public:
1433
1434 template<typename ScriptFunc>
1435 explicit EffectAbsorbHealHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1436 : EffectBase(effIndex, auraType)
1437 {
1438 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1439
1440 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1441 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1442
1443 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1444 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect*, HealInfo&, uint32&>,
1445 R""(EffectAbsorbHealHandler signature must be "void HandleAbsorb(AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount)")"");
1446 else
1447 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect*, HealInfo&, uint32&>,
1448 R""(EffectAbsorbHealHandler signature must be "static void HandleAbsorb(your_script_class& script, AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount)")"");
1449
1450 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1452 }
1453
1454 void Call(AuraScript* auraScript, AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount) const
1455 {
1456 return _invoker.Thunk(*auraScript, aurEff, healInfo, absorbAmount, _invoker.ImplStorage);
1457 }
1458 private:
1460 };
1461
1463 {
1464 public:
1466
1467 template<typename ScriptFunc>
1468 explicit CheckProcHandler(ScriptFunc handler)
1469 {
1470 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1471
1472 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1473 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1474
1475 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1476 static_assert(std::is_invocable_r_v<bool, ScriptFunc, ScriptClass&, ProcEventInfo&>,
1477 R""(CheckProcHandler signature must be "bool CheckProc(ProcEventInfo& eventInfo)")"");
1478 else
1479 static_assert(std::is_invocable_r_v<bool, ScriptFunc, ScriptClass&, ProcEventInfo&>,
1480 R""(CheckProcHandler signature must be "static bool CheckProc(your_script_class& script, ProcEventInfo& eventInfo)")"");
1481
1482 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1484 }
1485
1486 bool Call(AuraScript* auraScript, ProcEventInfo& eventInfo) const
1487 {
1488 return _invoker.Thunk(*auraScript, eventInfo, _invoker.ImplStorage);
1489 }
1490 private:
1492 };
1493
1495 {
1496 public:
1498
1499 template<typename ScriptFunc>
1500 explicit CheckEffectProcHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1501 : EffectBase(effIndex, auraType)
1502 {
1503 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1504
1505 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1506 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1507
1508 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1509 static_assert(std::is_invocable_r_v<bool, ScriptFunc, ScriptClass&, AuraEffect const*, ProcEventInfo&>,
1510 R""(CheckEffectProcHandler signature must be "bool CheckProc(AuraEffect const* aurEff, ProcEventInfo& eventInfo)")"");
1511 else
1512 static_assert(std::is_invocable_r_v<bool, ScriptFunc, ScriptClass&, AuraEffect const*, ProcEventInfo&>,
1513 R""(CheckEffectProcHandler signature must be "static bool CheckProc(your_script_class& script, AuraEffect const* aurEff, ProcEventInfo& eventInfo)")"");
1514
1515 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1517 }
1518
1519 bool Call(AuraScript* auraScript, AuraEffect const* aurEff, ProcEventInfo& eventInfo) const
1520 {
1521 return _invoker.Thunk(*auraScript, aurEff, eventInfo, _invoker.ImplStorage);
1522 }
1523 private:
1525 };
1526
1528 {
1529 public:
1531
1532 template<typename ScriptFunc>
1533 explicit AuraProcHandler(ScriptFunc handler)
1534 {
1535 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1536
1537 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1538 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1539
1540 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1541 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, ProcEventInfo&>,
1542 R""(AuraProcHandler signature must be "void HandleProc(ProcEventInfo& eventInfo)")"");
1543 else
1544 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, ProcEventInfo&>,
1545 R""(AuraProcHandler signature must be "static void HandleProc(your_script_class& script, ProcEventInfo& eventInfo)")"");
1546
1547 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1549 }
1550
1551 void Call(AuraScript* auraScript, ProcEventInfo& eventInfo) const
1552 {
1553 return _invoker.Thunk(*auraScript, eventInfo, _invoker.ImplStorage);
1554 }
1555 private:
1557 };
1558
1559 class EffectProcHandler final : public EffectBase
1560 {
1561 public:
1563
1564 template<typename ScriptFunc>
1565 explicit EffectProcHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
1566 : EffectBase(effIndex, auraType)
1567 {
1568 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1569
1570 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1571 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1572
1573 if constexpr (std::is_member_function_pointer_v<ScriptFunc>)
1574 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect*, ProcEventInfo&>,
1575 R""(EffectProcHandler signature must be "void HandleProc(AuraEffect* aurEff, ProcEventInfo& eventInfo)")"");
1576 else
1577 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass&, AuraEffect*, ProcEventInfo&>,
1578 R""(EffectProcHandler signature must be "static void HandleProc(your_script_class& script, AuraEffect* aurEff, ProcEventInfo& eventInfo)")"");
1579
1580 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1582 }
1583
1584 void Call(AuraScript* auraScript, AuraEffect* aurEff, ProcEventInfo& eventInfo) const
1585 {
1586 return _invoker.Thunk(*auraScript, aurEff, eventInfo, _invoker.ImplStorage);
1587 }
1588 private:
1590 };
1591
1593 {
1594 public:
1596
1597 template<typename ScriptFunc>
1598 explicit EnterLeaveCombatHandler(ScriptFunc handler)
1599 {
1600 using ScriptClass = GetScriptClass_t<ScriptFunc>;
1601
1602 static_assert(ScriptFuncInvoker::Size >= sizeof(ScriptFunc));
1603 static_assert(ScriptFuncInvoker::Alignment >= alignof(ScriptFunc));
1604
1605 static_assert(std::is_invocable_r_v<void, ScriptFunc, ScriptClass, bool>,
1606 R""(EnterLeaveCombatHandler signature must be "void HandleEnterLeaveCombat(bool isNowInCombat)")"");
1607
1608 new (_invoker.ImplStorage.data()) ScriptFuncInvoker::Impl<ScriptFunc>{ .Func = handler };
1610 }
1611
1612 void Call(AuraScript* auraScript, bool isNowInCombat) const
1613 {
1614 return _invoker.Thunk(*auraScript, isNowInCombat, _invoker.ImplStorage);
1615 }
1616 private:
1618 };
1619
1620 // left for custom compatibility only, DO NOT USE
1621 #define PrepareAuraScript(CLASSNAME)
1622
1623public:
1624 AuraScript() noexcept;
1626 bool _Validate(SpellInfo const* entry) override;
1627 bool _Load(Aura* aura);
1628 void _PrepareScriptCall(AuraScriptHookType hookType, AuraApplication const* aurApp = nullptr);
1629 void _FinishScriptCall();
1630 bool _IsDefaultActionPrevented() const;
1631private:
1632 Aura* m_aura;
1633 AuraApplication const* m_auraApplication;
1634 bool m_defaultActionPrevented;
1635
1637 {
1638 public:
1642 ScriptStateStore(uint8 currentScriptState, AuraApplication const* auraApplication, bool defaultActionPrevented)
1643 : _auraApplication(auraApplication), _currentScriptState(currentScriptState), _defaultActionPrevented(defaultActionPrevented)
1644 { }
1645 };
1646 typedef std::stack<ScriptStateStore> ScriptStateStack;
1648
1649public:
1650 //
1651 // AuraScript interface
1652 // hooks to which you can attach your functions
1653 //
1654 // executed when area aura checks if it can be applied on target
1655 // example: OnEffectApply += AuraEffectApplyFn(class::function);
1656 // where function is: bool function(Unit* target);
1658 #define AuraCheckAreaTargetFn(F) CheckAreaTargetHandler(&F)
1659
1660 // executed when aura is dispelled by a unit
1661 // example: OnDispel += AuraDispelFn(class::function);
1662 // where function is: void function(DispelInfo* dispelInfo);
1664 // executed after aura is dispelled by a unit
1665 // example: AfterDispel += AuraDispelFn(class::function);
1666 // where function is: void function(DispelInfo* dispelInfo);
1668 #define AuraDispelFn(F) AuraDispelHandler(&F)
1669
1670 // executed on every heartbeat of a unit
1671 // example: OnHeartbeat += AuraHeartbeatFn(class::function);
1672 // where function is: void function();
1674 #define AuraHeartbeatFn(F) AuraHeartbeatHandler(&F)
1675
1676 // executed when aura effect is applied with specified mode to target
1677 // should be used when when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe
1678 // example: OnEffectApply += AuraEffectApplyFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes);
1679 // where function is: void function(AuraEffect const* aurEff, AuraEffectHandleModes mode);
1681 // executed after aura effect is applied with specified mode to target
1682 // example: AfterEffectApply += AuraEffectApplyFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes);
1683 // where function is: void function(AuraEffect const* aurEff, AuraEffectHandleModes mode);
1685 #define AuraEffectApplyFn(F, I, N, M) EffectApplyHandler(&F, I, N, M)
1686
1687 // executed after aura effect is removed with specified mode from target
1688 // should be used when effect handler preventing/replacing is needed, do not use this hook for triggering spellcasts/removing auras etc - may be unsafe
1689 // example: OnEffectRemove += AuraEffectRemoveFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes);
1690 // where function is: void function(AuraEffect const* aurEff, AuraEffectHandleModes mode);
1692 // executed when aura effect is removed with specified mode from target
1693 // example: AfterEffectRemove += AuraEffectRemoveFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier, AuraEffectHandleModes);
1694 // where function is: void function(AuraEffect const* aurEff, AuraEffectHandleModes mode);
1696 #define AuraEffectRemoveFn(F, I, N, M) EffectApplyHandler(&F, I, N, M)
1697
1698 // executed when periodic aura effect ticks on target
1699 // example: OnEffectPeriodic += AuraEffectPeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1700 // where function is: void function(AuraEffect const* aurEff);
1702 #define AuraEffectPeriodicFn(F, I, N) EffectPeriodicHandler(&F, I, N)
1703
1704 // executed when periodic aura effect is updated
1705 // example: OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1706 // where function is: void function(AuraEffect* aurEff);
1708 #define AuraEffectUpdatePeriodicFn(F, I, N) EffectUpdatePeriodicHandler(&F, I, N)
1709
1710 // executed when aura effect calculates amount
1711 // example: DoEffectCalcAmount += AuraEffectCalcAmounFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1712 // where function is: void function(AuraEffect* aurEff, int32& amount, bool& canBeRecalculated);
1714 #define AuraEffectCalcAmountFn(F, I, N) EffectCalcAmountHandler(&F, I, N)
1715
1716 // executed when aura effect calculates periodic data
1717 // example: DoEffectCalcPeriodic += AuraEffectCalcPeriodicFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1718 // where function is: void function(AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude);
1720 #define AuraEffectCalcPeriodicFn(F, I, N) EffectCalcPeriodicHandler(&F, I, N)
1721
1722 // executed when aura effect calculates spellmod
1723 // example: DoEffectCalcSpellMod += AuraEffectCalcSpellModFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1724 // where function is: void function(AuraEffect const* aurEff, SpellModifier*& spellMod);
1726 #define AuraEffectCalcSpellModFn(F, I, N) EffectCalcSpellModHandler(&F, I, N)
1727
1728 // executed when aura effect calculates crit chance for dots and hots
1729 // example: DoEffectCalcCritChance += AuraEffectCalcCritChanceFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1730 // where function is: void function(AuraEffect const* aurEff, Unit* victim, float& critChance);
1732 #define AuraEffectCalcCritChanceFn(F, I, N) EffectCalcCritChanceHandler(&F, I, N)
1733
1734 // executed when aura effect calculates damage or healing for dots and hots or initial absorb aura amount calculation
1735 // example: DoEffectCalcDamageAndHealing += AuraEffectCalcDamageFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1736 // example: DoEffectCalcDamageAndHealing += AuraEffectCalcHealingFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1737 // where function is: void function(AuraEffect const* aurEff, Unit* victim, int32& damageOrHealing, int32& flatMod, float& pctMod);
1739 #define AuraEffectCalcDamageFn(F, I, N) EffectCalcDamageAndHealingHandler(&F, I, N)
1740 #define AuraEffectCalcHealingFn(F, I, N) EffectCalcDamageAndHealingHandler(&F, I, N)
1741 #define AuraEffectCalcAbsorbFn(F, I) EffectCalcDamageAndHealingHandler(&F, I, SPELL_AURA_SCHOOL_ABSORB)
1742
1743 // executed when absorb aura effect is going to reduce damage
1744 // example: OnEffectAbsorb += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier);
1745 // where function is: void function(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
1747 #define AuraEffectAbsorbFn(F, I) EffectAbsorbHandler(&F, I, SPELL_AURA_SCHOOL_ABSORB)
1748 #define AuraEffectAbsorbOverkillFn(F, I) EffectAbsorbHandler(&F, I, SPELL_AURA_SCHOOL_ABSORB_OVERKILL)
1749
1750 // executed after absorb aura effect reduced damage to target - absorbAmount is real amount absorbed by aura
1751 // example: AfterEffectAbsorb += AuraEffectAbsorbFn(class::function, EffectIndexSpecifier);
1752 // where function is: void function(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
1754
1755 // executed when absorb aura effect is going to reduce damage
1756 // example: OnEffectAbsorbHeal += AuraEffectAbsorbHealFn(class::function, EffectIndexSpecifier);
1757 // where function is: void function(AuraEffect const* aurEff, HealInfo& healInfo, uint32& absorbAmount);
1759 #define AuraEffectAbsorbHealFn(F, I) EffectAbsorbHealHandler(&F, I, SPELL_AURA_SCHOOL_HEAL_ABSORB)
1760
1761 // executed after absorb aura effect reduced heal to target - absorbAmount is real amount absorbed by aura
1762 // example: AfterEffectAbsorbHeal += AuraEffectAbsorbHealFn(class::function, EffectIndexSpecifier);
1763 // where function is: void function(AuraEffect* aurEff, HealInfo& healInfo, uint32& absorbAmount);
1765
1766 // executed when mana shield aura effect is going to reduce damage
1767 // example: OnEffectManaShield += AuraEffectManaShieldFn(class::function, EffectIndexSpecifier);
1768 // where function is: void function (AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
1770 #define AuraEffectManaShieldFn(F, I) EffectAbsorbHandler(&F, I, SPELL_AURA_MANA_SHIELD)
1771
1772 // executed after mana shield aura effect reduced damage to target - absorbAmount is real amount absorbed by aura
1773 // example: AfterEffectManaShield += AuraEffectManaShieldFn(class::function, EffectIndexSpecifier);
1774 // where function is: void function(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& absorbAmount);
1776
1777 // executed when the caster of some spell with split dmg aura gets damaged through it
1778 // example: OnEffectSplit += AuraEffectSplitFn(class::function, EffectIndexSpecifier);
1779 // where function is: void function(AuraEffect* aurEff, DamageInfo& dmgInfo, uint32& splitAmount);
1781 #define AuraEffectSplitFn(F, I) EffectAbsorbHandler(&F, I, SPELL_AURA_SPLIT_DAMAGE_PCT)
1782
1783 // executed when aura checks if it can proc
1784 // example: DoCheckProc += AuraCheckProcFn(class::function);
1785 // where function is: bool function(ProcEventInfo& eventInfo);
1787 #define AuraCheckProcFn(F) CheckProcHandler(&F)
1788
1789 // executed when aura effect checks if it can proc the aura
1790 // example: DoCheckEffectProc += AuraCheckEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1791 // where function is bool function(AuraEffect const* aurEff, ProcEventInfo& eventInfo);
1793 #define AuraCheckEffectProcFn(F, I, N) CheckEffectProcHandler(&F, I, N)
1794
1795 // executed before aura procs (possibility to prevent charge drop/cooldown)
1796 // example: DoPrepareProc += AuraProcFn(class::function);
1797 // where function is: void function(ProcEventInfo& eventInfo);
1799 // executed when aura procs
1800 // example: OnProc += AuraProcFn(class::function);
1801 // where function is: void function(ProcEventInfo& eventInfo);
1803 // executed after aura proced
1804 // example: AfterProc += AuraProcFn(class::function);
1805 // where function is: void function(ProcEventInfo& eventInfo);
1807 #define AuraProcFn(F) AuraProcHandler(&F)
1808
1809 // executed when aura effect procs
1810 // example: OnEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1811 // where function is: void function(AuraEffect* aurEff, ProcEventInfo& procInfo);
1813 // executed after aura effect proced
1814 // example: AfterEffectProc += AuraEffectProcFn(class::function, EffectIndexSpecifier, EffectAuraNameSpecifier);
1815 // where function is: void function(AuraEffect* aurEff, ProcEventInfo& procInfo);
1817 #define AuraEffectProcFn(F, I, N) EffectProcHandler(&F, I, N)
1818
1819 // executed when target enters or leaves combat
1820 // example: OnEnterLeaveCombat += AuraEnterLeaveCombatFn(class::function)
1821 // where function is: void function (bool isNowInCombat);
1823 #define AuraEnterLeaveCombatFn(F) EnterLeaveCombatHandler(&F)
1824
1825 // AuraScript interface - hook/effect execution manipulators
1826
1827 // prevents default action of a hook from being executed (works only while called in a hook which default action can be prevented)
1828 void PreventDefaultAction();
1829
1830 // AuraScript interface - functions which are redirecting to Aura class
1831
1832 // returns proto of the spell
1833 SpellInfo const* GetSpellInfo() const;
1834 SpellEffectInfo const& GetEffectInfo(SpellEffIndex effIndex) const;
1835 // returns spellid of the spell
1836 uint32 GetId() const;
1837
1838 // returns guid of object which cast the aura (m_originalCaster of the Spell class)
1839 ObjectGuid GetCasterGUID() const;
1840 // returns unit which cast the aura or NULL if not avalible (caster logged out for example)
1841 Unit* GetCaster() const;
1842 // returns gameobject which cast the aura or NULL if not available
1843 GameObject* GetGObjCaster() const;
1844 // returns object on which aura was cast, target for non-area auras, area aura source for area auras
1845 WorldObject* GetOwner() const;
1846 // returns owner if it's unit or unit derived object, NULL otherwise (only for persistent area auras NULL is returned)
1847 Unit* GetUnitOwner() const;
1848 // returns owner if it's dynobj, NULL otherwise
1849 DynamicObject* GetDynobjOwner() const;
1850
1851 // removes aura with remove mode (see AuraRemoveMode enum)
1852 void Remove(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
1853 // returns aura object of script
1854 Aura* GetAura() const;
1855
1856 // returns type of the aura, may be dynobj owned aura or unit owned aura
1857 AuraObjectType GetType() const;
1858
1859 // aura duration manipulation - when duration goes to 0 aura is removed
1860 int32 GetDuration() const;
1861 void SetDuration(int32 duration, bool withMods = false);
1862 // sets duration to maxduration
1863 void RefreshDuration();
1864 time_t GetApplyTime() const;
1865 int32 GetMaxDuration() const;
1866 void SetMaxDuration(int32 duration);
1867 int32 CalcMaxDuration() const;
1868 // expired - duration just went to 0
1869 bool IsExpired() const;
1870 // permament - has infinite duration
1871 bool IsPermanent() const;
1872
1873 // charges manipulation - 0 - not charged aura
1874 uint8 GetCharges() const;
1875 void SetCharges(uint8 charges);
1876 uint8 CalcMaxCharges() const;
1877 bool ModCharges(int8 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
1878 // returns true if last charge dropped
1879 bool DropCharge(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
1880
1881 // stack amount manipulation
1882 uint8 GetStackAmount() const;
1883 void SetStackAmount(uint8 num);
1884 bool ModStackAmount(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT);
1885
1886 // passive - "working in background", not saved, not removed by immunities, not seen by player
1887 bool IsPassive() const;
1888 // death persistent - not removed on death
1889 bool IsDeathPersistent() const;
1890
1891 // check if aura has effect of given effindex
1892 bool HasEffect(uint8 effIndex) const;
1893 // returns aura effect of given effect index or NULL
1894 AuraEffect* GetEffect(uint8 effIndex) const;
1895
1896 // check if aura has effect of given aura type
1897 bool HasEffectType(AuraType type) const;
1898
1899 // AuraScript interface - functions which are redirecting to AuraApplication class
1900 // Do not call these in hooks in which AuraApplication is not avalible, otherwise result will differ from expected (the functions will return NULL)
1901
1902 // returns currently processed target of an aura
1903 // Return value does not need to be NULL-checked, the only situation this will (always)
1904 // return NULL is when the call happens in an unsupported hook, in other cases, it is always valid
1905 Unit* GetTarget() const;
1906 // returns AuraApplication object of currently processed target
1907 AuraApplication const* GetTargetApplication() const;
1908
1909 // returns desired cast difficulty for triggered spells
1910 Difficulty GetCastDifficulty() const;
1911};
1912
1913//
1914// definitions:
1915//
1916// EffectIndexSpecifier - specifies conditions for effects
1917// EFFECT_0 - first effect matches
1918// EFFECT_1 - second effect matches
1919// EFFECT_2 - third effect matches
1920// EFFECT_FIRST_FOUND - first effect matching other conditions matches
1921// EFFECT_ALL - all effects of spell match
1922//
1923// EffectNameSpecifier - specifies conditions for spell effect names
1924// SPELL_EFFECT_ANY - any effect but not 0 matches condition
1925// SPELL_EFFECT_XXX - one of values of enum SpellEffects - effect with equal name matches
1926//
1927
1928#endif // TRINITY_SPELL_SCRIPT_H
ItemContext
Definition DBCEnums.h:1315
Difficulty
Definition DBCEnums.h:932
#define TC_GAME_API
Definition Define.h:129
uint8_t uint8
Definition Define.h:156
int64_t int64
Definition Define.h:149
int16_t int16
Definition Define.h:151
int8_t int8
Definition Define.h:152
int32_t int32
Definition Define.h:150
uint16_t uint16
Definition Define.h:155
uint32_t uint32
Definition Define.h:154
SpellEffIndex
SpellMissInfo
SpellCustomErrors
SpellCastResult
AuraEffectHandleModes
AuraRemoveMode
@ AURA_REMOVE_BY_DEFAULT
AuraObjectType
double SpellEffectValue
This is a double instead of float to be able to store full range of int32.
AuraScriptHookType
@ AURA_SCRIPT_HOOK_EFFECT_CALC_PERIODIC
@ AURA_SCRIPT_HOOK_CHECK_EFFECT_PROC
@ AURA_SCRIPT_HOOK_EFFECT_CALC_DAMAGE_AND_HEALING
@ AURA_SCRIPT_HOOK_EFFECT_CALC_AMOUNT
@ AURA_SCRIPT_HOOK_EFFECT_REMOVE
@ AURA_SCRIPT_HOOK_EFFECT_CALC_CRIT_CHANCE
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_MANASHIELD
@ AURA_SCRIPT_HOOK_PREPARE_PROC
@ AURA_SCRIPT_HOOK_ON_HEARTBEAT
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_APPLY
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_REMOVE
@ AURA_SCRIPT_HOOK_AFTER_PROC
@ AURA_SCRIPT_HOOK_CHECK_AREA_TARGET
@ AURA_SCRIPT_HOOK_EFFECT_MANASHIELD
@ AURA_SCRIPT_HOOK_PROC
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_ABSORB
@ AURA_SCRIPT_HOOK_DISPEL
@ AURA_SCRIPT_HOOK_EFFECT_APPLY
@ AURA_SCRIPT_HOOK_EFFECT_PERIODIC
@ AURA_SCRIPT_HOOK_EFFECT_AFTER_PROC
@ AURA_SCRIPT_HOOK_EFFECT_ABSORB
@ AURA_SCRIPT_HOOK_EFFECT_PROC
@ AURA_SCRIPT_HOOK_EFFECT_SPLIT
@ AURA_SCRIPT_HOOK_EFFECT_CALC_SPELLMOD
@ AURA_SCRIPT_HOOK_AFTER_DISPEL
@ AURA_SCRIPT_HOOK_CHECK_PROC
@ AURA_SCRIPT_HOOK_ENTER_LEAVE_COMBAT
@ AURA_SCRIPT_HOOK_EFFECT_UPDATE_PERIODIC
SpellScriptState
Definition SpellScript.h:64
@ SPELL_SCRIPT_STATE_NONE
Definition SpellScript.h:65
@ SPELL_SCRIPT_STATE_LOADING
Definition SpellScript.h:67
@ SPELL_SCRIPT_STATE_UNLOADING
Definition SpellScript.h:68
@ SPELL_SCRIPT_STATE_REGISTRATION
Definition SpellScript.h:66
double SpellEffectValue
Definition SpellScript.h:58
#define SPELL_SCRIPT_STATE_END
Definition SpellScript.h:70
SpellScriptHookType
@ SPELL_SCRIPT_HOOK_AFTER_CAST
@ SPELL_SCRIPT_HOOK_EFFECT_HIT
@ SPELL_SCRIPT_HOOK_AFTER_HIT
@ SPELL_SCRIPT_HOOK_EFFECT_SUCCESSFUL_DISPEL
@ SPELL_SCRIPT_HOOK_CALC_HEALING
@ SPELL_SCRIPT_HOOK_EFFECT_LAUNCH
@ SPELL_SCRIPT_HOOK_OBJECT_AREA_TARGET_SELECT
@ SPELL_SCRIPT_HOOK_BEFORE_HIT
@ SPELL_SCRIPT_HOOK_CALC_DAMAGE
@ SPELL_SCRIPT_HOOK_CHECK_CAST
@ SPELL_SCRIPT_HOOK_EFFECT_LAUNCH_TARGET
@ SPELL_SCRIPT_HOOK_CALC_CAST_TIME
@ SPELL_SCRIPT_HOOK_EMPOWER_STAGE_COMPLETED
@ SPELL_SCRIPT_HOOK_EMPOWER_COMPLETED
@ SPELL_SCRIPT_HOOK_HIT
@ SPELL_SCRIPT_HOOK_BEFORE_CAST
@ SPELL_SCRIPT_HOOK_ON_RESIST_ABSORB_CALCULATION
@ SPELL_SCRIPT_HOOK_DESTINATION_TARGET_SELECT
@ SPELL_SCRIPT_HOOK_OBJECT_TARGET_SELECT
@ SPELL_SCRIPT_HOOK_EFFECT_HIT_TARGET
@ SPELL_SCRIPT_HOOK_CALC_CRIT_CHANCE
@ SPELL_SCRIPT_HOOK_ON_CAST
@ SPELL_SCRIPT_HOOK_ON_PRECAST
AuraDispelHandler(ScriptFunc handler)
void Call(AuraScript *auraScript, DispelInfo *dispelInfo) const
void Call(AuraScript *auraScript) const
AuraHeartbeatHandler(ScriptFunc handler)
AuraProcHandler(ScriptFunc handler)
void Call(AuraScript *auraScript, ProcEventInfo &eventInfo) const
ScriptFuncInvoker _invoker
bool Call(AuraScript *auraScript, Unit *target) const
CheckAreaTargetHandler(ScriptFunc handler)
CheckEffectProcHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
bool Call(AuraScript *auraScript, AuraEffect const *aurEff, ProcEventInfo &eventInfo) const
bool Call(AuraScript *auraScript, ProcEventInfo &eventInfo) const
CheckProcHandler(ScriptFunc handler)
void Call(AuraScript *auraScript, AuraEffect *aurEff, DamageInfo &dmgInfo, uint32 &absorbAmount) const
EffectAbsorbHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
EffectAbsorbHealHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
void Call(AuraScript *auraScript, AuraEffect *aurEff, HealInfo &healInfo, uint32 &absorbAmount) const
void Call(AuraScript *auraScript, AuraEffect const *aurEff, AuraEffectHandleModes mode) const
EffectApplyHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType, AuraEffectHandleModes mode)
AuraEffectHandleModes _mode
EffectBase & operator=(EffectBase const &right)=delete
EffectBase & operator=(EffectBase &&right) noexcept
EffectBase(EffectBase &&right) noexcept
EffectBase(EffectBase const &right)=delete
void Call(AuraScript *auraScript, AuraEffect const *aurEff, SpellEffectValue &amount, bool &canBeRecalculated) const
EffectCalcAmountHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
void Call(AuraScript *auraScript, AuraEffect const *aurEff, Unit const *victim, float &critChance) const
EffectCalcCritChanceHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
EffectCalcDamageAndHealingHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
void Call(AuraScript *auraScript, AuraEffect const *aurEff, Unit *victim, int32 &damageOrHealing, int32 &flatMod, float &pctMod) const
EffectCalcPeriodicHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
void Call(AuraScript *auraScript, AuraEffect const *aurEff, bool &isPeriodic, int32 &periodicTimer) const
EffectCalcSpellModHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
void Call(AuraScript *auraScript, AuraEffect const *aurEff, SpellModifier *&spellMod) const
void Call(AuraScript *auraScript, AuraEffect const *aurEff) const
EffectPeriodicHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
EffectProcHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
void Call(AuraScript *auraScript, AuraEffect *aurEff, ProcEventInfo &eventInfo) const
void Call(AuraScript *auraScript, AuraEffect *aurEff) const
EffectUpdatePeriodicHandler(ScriptFunc handler, uint8 effIndex, uint16 auraType)
void Call(AuraScript *auraScript, bool isNowInCombat) const
EnterLeaveCombatHandler(ScriptFunc handler)
ScriptStateStore(uint8 currentScriptState, AuraApplication const *auraApplication, bool defaultActionPrevented)
AuraApplication const * _auraApplication
HookList< EffectAbsorbHandler > OnEffectManaShield
HookList< EffectCalcDamageAndHealingHandler > DoEffectCalcDamageAndHealing
HookList< EffectAbsorbHealHandler > OnEffectAbsorbHeal
HookList< EffectCalcPeriodicHandler > DoEffectCalcPeriodic
HookList< AuraHeartbeatHandler > OnHeartbeat
HookList< EffectApplyHandler > AfterEffectRemove
HookList< CheckEffectProcHandler > DoCheckEffectProc
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
HookList< EffectProcHandler > AfterEffectProc
HookList< EffectAbsorbHandler > AfterEffectAbsorb
HookList< EffectCalcAmountHandler > DoEffectCalcAmount
HookList< EffectUpdatePeriodicHandler > OnEffectUpdatePeriodic
HookList< EffectCalcSpellModHandler > DoEffectCalcSpellMod
HookList< EnterLeaveCombatHandler > OnEnterLeaveCombat
HookList< EffectAbsorbHandler > OnEffectAbsorb
std::stack< ScriptStateStore > ScriptStateStack
HookList< EffectCalcCritChanceHandler > DoEffectCalcCritChance
HookList< EffectAbsorbHandler > AfterEffectManaShield
HookList< CheckAreaTargetHandler > DoCheckAreaTarget
HookList< EffectAbsorbHealHandler > AfterEffectAbsorbHeal
HookList< AuraProcHandler > AfterProc
HookList< AuraDispelHandler > OnDispel
HookList< CheckProcHandler > DoCheckProc
HookList< EffectApplyHandler > OnEffectRemove
HookList< AuraDispelHandler > AfterDispel
ScriptStateStack m_scriptStates
HookList< EffectProcHandler > OnEffectProc
HookList< AuraProcHandler > DoPrepareProc
HookList< AuraProcHandler > OnProc
HookList< EffectApplyHandler > OnEffectApply
HookList< EffectAbsorbHandler > OnEffectSplit
Definition Item.h:179
EffectHook & operator=(EffectHook &&right) noexcept
EffectHook(EffectHook const &right)=delete
EffectHook(EffectHook &&right) noexcept
virtual bool CheckEffect(SpellInfo const *spellInfo, uint8 effIndex) const =0
EffectHook & operator=(EffectHook const &right)=delete
SpellScriptBase(SpellScriptBase const &right)=delete
uint32 m_scriptSpellId
uint8 m_currentScriptState
virtual void Register()=0
virtual bool Validate(SpellInfo const *spellInfo)
std::string_view m_scriptName
static bool ValidateSpellEffect(T const &spellEffects)
static bool ValidateSpellInfo(std::initializer_list< uint32 > spellIds)
static bool ValidateSpellEffect(std::initializer_list< std::pair< uint32, SpellEffIndex > > effects)
static bool ValidateSpellInfo(T const &spellIds)
static bool ValidateSpellEffectsImpl(Iterator begin, Iterator end)
static bool ValidateSpellInfoImpl(Iterator begin, Iterator end)
typename GetScriptClass< ScriptFunc >::type GetScriptClass_t
virtual bool Load()
SpellScriptBase & operator=(SpellScriptBase &&right)=delete
SpellScriptBase(SpellScriptBase &&right)=delete
virtual ~SpellScriptBase()
virtual void Unload()
SpellScriptBase & operator=(SpellScriptBase const &right)=delete
void Call(SpellScript *spellScript, SpellMissInfo missInfo) const
BeforeHitHandler(ScriptFunc handler)
CastHandler(ScriptFunc handler)
ScriptFuncInvoker _invoker
void Call(SpellScript *spellScript) const
SpellCastResult Call(SpellScript *spellScript) const
CheckCastHandler(ScriptFunc handler)
void Call(SpellScript *spellScript, SpellEffectInfo const &spellEffectInfo, Unit *victim, int32 &damageOrHealing, int32 &flatMod, float &pctMod) const
DamageAndHealingCalcHandler(ScriptFunc handler)
DestinationTargetSelectHandler(ScriptFunc handler, uint8 effIndex, uint16 targetType)
void Call(SpellScript *spellScript, SpellDestination &target) const
EffectBase(EffectBase const &right)=delete
EffectBase(EffectBase &&right) noexcept
EffectBase & operator=(EffectBase const &right)=delete
EffectBase & operator=(EffectBase &&right) noexcept
EffectHandler(ScriptFunc handler, uint8 effIndex, uint16 effName)
void Call(SpellScript *spellScript, SpellEffIndex effIndex) const
ScriptFuncInvoker _invoker
EmpowerStageCompletedHandler(ScriptFunc handler)
void Call(SpellScript *spellScript, int32 completedStagesCount) const
void Call(SpellScript *spellScript) const
ScriptFuncInvoker _invoker
HitHandler(ScriptFunc handler)
void Call(SpellScript *spellScript, std::list< WorldObject * > &targets) const
bool HasSameTargetFunctionAs(ObjectAreaTargetSelectHandler const &other) const
ObjectAreaTargetSelectHandler(ScriptFunc handler, uint8 effIndex, uint16 targetType)
bool HasSameTargetFunctionAs(ObjectTargetSelectHandler const &other) const
ObjectTargetSelectHandler(ScriptFunc handler, uint8 effIndex, uint16 targetType)
void Call(SpellScript *spellScript, WorldObject *&target) const
void Call(SpellScript *spellScript, Unit const *victim, float &critChance) const
OnCalcCritChanceHandler(ScriptFunc handler)
void Call(SpellScript *spellScript, DamageInfo const &damageInfo, uint32 &resistAmount, int32 &absorbAmount) const
TargetHook(TargetHook &&right) noexcept
uint16 GetTarget() const
TargetHook & operator=(TargetHook &&right) noexcept
TargetHook(TargetHook const &right)=delete
TargetHook & operator=(TargetHook const &right)=delete
bool _IsDefaultEffectPrevented(SpellEffIndex effIndex) const
HookList< DamageAndHealingCalcHandler > CalcDamage
HookList< CastHandler > AfterCast
HookList< CheckCastHandler > OnCheckCast
HookList< EmpowerStageCompletedHandler > OnEmpowerStageCompleted
HookList< HitHandler > AfterHit
HookList< DestinationTargetSelectHandler > OnDestinationTargetSelect
uint32 m_hitPreventDefaultEffectMask
HookList< HitHandler > OnHit
void PreventHitDamage()
uint32 m_hitPreventEffectMask
HookList< EffectHandler > OnEffectHit
HookList< EffectHandler > OnEffectHitTarget
void PreventHitHeal()
HookList< ObjectTargetSelectHandler > OnObjectTargetSelect
HookList< CastHandler > OnCast
HookList< OnCalculateResistAbsorbHandler > OnCalculateResistAbsorb
HookList< CastHandler > BeforeCast
virtual int32 CalcCastTime(int32 castTime)
Spell * m_spell
Spell * GetSpell() const
HookList< EffectHandler > OnEffectLaunchTarget
HookList< BeforeHitHandler > BeforeHit
virtual void OnPrecast()
HookList< EffectHandler > OnEffectSuccessfulDispel
HookList< OnCalcCritChanceHandler > OnCalcCritChance
HookList< EmpowerStageCompletedHandler > OnEmpowerCompleted
HookList< EffectHandler > OnEffectLaunch
HookList< DamageAndHealingCalcHandler > CalcHealing
HookList< ObjectAreaTargetSelectHandler > OnObjectAreaTargetSelect
Definition Spell.h:277
Definition Unit.h:635
static Ret Invoke(BaseClass &script, Args... args, StorageType callImpl)
GetScriptClass_t< ScriptFunc > ScriptClass