Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
example_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/*
7 * An example of a spell script file
8 * to bind a script to spell you have to add entry for it in `spell_script_names`
9 * where `spell_id` is id of the spell to bind
10 * and `ScriptName` is the name of a script assigned on registration
11 */
12
13#include "ScriptMgr.h"
14#include "SpellAuras.h"
15#include "SpellAuraEffects.h"
16#include "SpellScript.h"
17#include "Player.h"
18
20{
22};
23
25{
26 public:
27 spell_ex_5581() : SpellScriptLoader("spell_ex_5581") { }
28
30 {
31 // initialize script, this macro does compile time check for type of the function - prevents possible issues
32 // if you have assigned wrong type of function to a hook you'll receive type conversion error during build
33 // this line is required, otherwise you'll get XXXHandlerFunction - identifier not found errors
35
36 std::string localVariable;
38
39 // function called on server startup
40 // checks if script has data required for it to work
41 bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
42 {
43 // check if spellid 70522 exists in dbc, we will trigger it later
44 if (!sSpellMgr->GetSpellInfo(SPELL_TRIGGERED))
45 return false;
46 return true;
47 }
48
49 // function called just after script is added to spell
50 // we initialize local variables if needed
52 {
53 localVariable = "we're using local variable";
54 localVariable2 = new char();
55 return true;
56 // return false - script will be immediately removed from the spell
57 // for example - we don't want this script to be executed on a creature
58 // if (GetCaster()->GetTypeID() != TYPEID_PLAYER)
59 // return false;
60 }
61
62 // function called just before script delete
63 // we free allocated memory
65 {
66 delete localVariable2;
67 }
68
70 {
71 // this hook is executed before anything about casting the spell is done
72 // after this hook is executed all the machinery starts
73 SF_LOG_INFO("misc", "Caster just finished preparing the spell (cast bar has expired)");
74 }
75
77 {
78 // cast is validated and spell targets are selected at this moment
79 // this is a last place when the spell can be safely interrupted
80 SF_LOG_INFO("misc", "Spell is about to do take reagents, power, launch missile, do visuals and instant spell effects");
81 }
82
84 {
85 SF_LOG_INFO("misc", "All immediate Actions for the spell are finished now");
86 // this is a safe for triggering additional effects for a spell without interfering
87 // with visuals or with other effects of the spell
88 //GetCaster()->CastSpell(target, SPELL_TRIGGERED, true);
89 }
90
92 {
93 // in this hook you can add additional requirements for spell caster (and throw a client error if reqs're not passed)
94 // in this case we're disallowing to select non-player as a target of the spell
95 //if (!GetExplTargetUnit() || GetExplTargetUnit()->ToPlayer())
96 //return SPELL_FAILED_BAD_TARGETS;
97 return SPELL_CAST_OK;
98 }
99
100
102 {
103 SF_LOG_INFO("misc", "Spell %u with SPELL_EFFECT_DUMMY is just launched!", GetSpellInfo()->Id);
104 }
105
107 {
108 uint64 targetGUID = 0;
109 if (Unit* unitTarget = GetHitUnit())
110 targetGUID = unitTarget->GetGUID();
111 // we're handling SPELL_EFFECT_DUMMY in effIndex 0 here
112 SF_LOG_INFO("misc", "Spell %u with SPELL_EFFECT_DUMMY is just launched at it's target: " UI64FMTD "!", GetSpellInfo()->Id, targetGUID);
113 }
114
115 void HandleDummyHit(SpellEffIndex /*effIndex*/)
116 {
117 SF_LOG_INFO("misc", "Spell %u with SPELL_EFFECT_DUMMY has hit!", GetSpellInfo()->Id);
118 }
119
121 {
122 SF_LOG_INFO("misc", "SPELL_EFFECT_DUMMY is hits it's target!");
123 // make caster cast a spell on a unit target of effect
124 if (Unit* target = GetHitUnit())
125 GetCaster()->CastSpell(target, SPELL_TRIGGERED, true);
126 }
127
129 {
130 SF_LOG_INFO("misc", "Spell is about to hit target!");
131 }
132
134 {
135 SF_LOG_INFO("misc", "Spell just hit target!");
136 }
137
139 {
140 SF_LOG_INFO("misc", "Spell just finished hitting target!");
141 }
142
143 void FilterTargets(std::list<Unit*>& /*targetList*/)
144 {
145 // usually you want this call for Area Target spells
146 SF_LOG_INFO("misc", "Spell is about to add targets from targetList to final targets!");
147 }
148
149 // register functions used in spell script - names of these functions do not matter
151 {
152 // we're registering our functions here
157 // function HandleDummy will be called when spell is launched, independant from targets selected for spell, just before default effect 0 launch handler
159 // function HandleDummy will be called when spell is launched at target, just before default effect 0 launch at target handler
161 // function HandleDummy will be called when spell hits it's destination, independant from targets selected for spell, just before default effect 0 hit handler
163 // function HandleDummy will be called when unit is hit by spell, just before default effect 0 hit target handler
165 // this will prompt an error on startup because effect 0 of spell 49375 is set to SPELL_EFFECT_DUMMY, not SPELL_EFFECT_APPLY_AURA
166 //OnEffectHitTarget += SpellEffectFn(spell_gen_49375SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_APPLY_AURA);
167 // this will make HandleDummy function to be called on first != 0 effect of spell 49375
168 //OnEffectHitTarget += SpellEffectFn(spell_gen_49375SpellScript::HandleDummy, EFFECT_FIRST_FOUND, SPELL_EFFECT_ANY);
169 // this will make HandleDummy function to be called on all != 0 effect of spell 49375
170 //OnEffectHitTarget += SpellEffectFn(spell_gen_49375SpellScript::HandleDummy, EFFECT_ALL, SPELL_EFFECT_ANY);
171 // bind handler to BeforeHit event of the spell
173 // bind handler to OnHit event of the spell
175 // bind handler to AfterHit event of the spell
177 // bind handler to OnUnitTargetSelect event of the spell
178 //OnUnitTargetSelect += SpellUnitTargetFn(spell_ex_5581SpellScript::FilterTargets, EFFECT_0, TARGET_UNIT_CASTER);
179 }
180 };
181
182 // function which creates SpellScript
184 {
185 return new spell_ex_5581SpellScript();
186 }
187};
188
190{
191 public:
192 spell_ex_66244() : SpellScriptLoader("spell_ex_66244") { }
193
195 {
197 // function called on server startup
198 // checks if script has data required for it to work
199 bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
200 {
201 // check if spellid exists in dbc, we will trigger it later
202 if (!sSpellMgr->GetSpellInfo(SPELL_TRIGGERED))
203 return false;
204 return true;
205 }
206
207 // function called in aura constructor
208 // we initialize local variables if needed
210 {
211 // do not load script if aura is casted by player or caster not avalible
212 if (Unit* caster = GetCaster())
213 if (caster->GetTypeId() == TYPEID_PLAYER)
214 return true;
215 return false;
216 }
217
218
219 void HandleOnEffectApply(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
220 {
221 SF_LOG_INFO("misc", "Aura Effect is about to be applied on target!");
222 // this hook allows you to prevent execution of AuraEffect handler, or to replace it with your own handler
223 //PreventDefaultAction();
224 }
225 void HandleOnEffectRemove(AuraEffect const* /*aurEff*/, AuraEffectHandleModes /*mode*/)
226 {
227 SF_LOG_INFO("misc", "Aura Effect is about to be removed from target!");
228 // this hook allows you to prevent execution of AuraEffect handler, or to replace it with your own handler
229 //PreventDefaultAction();
230 }
231
233 {
234 SF_LOG_INFO("misc", "Aura Effect has just been applied on target!");
235 Unit* target = GetTarget();
236 // cast spell on target on aura apply
237 target->CastSpell(target, SPELL_TRIGGERED, true);
238 }
239
241 {
242 SF_LOG_INFO("misc", "Aura Effect has just been just removed from target!");
243 Unit* target = GetTarget();
244 Unit* caster = GetCaster();
245 // caster may be not avalible (logged out for example)
246 if (!caster)
247 return;
248 // cast spell on caster on aura remove
249 target->CastSpell(caster, SPELL_TRIGGERED, true);
250 }
251
252 void HandleEffectPeriodic(AuraEffect const* /*aurEff*/)
253 {
254 SF_LOG_INFO("misc", "Perioidic Aura Effect is does a tick on target!");
255 Unit* target = GetTarget();
256 // aura targets damage self on tick
257 target->DealDamage(target, 100);
258 }
259
261 {
262 SF_LOG_INFO("misc", "Perioidic Aura Effect is now updated!");
263 // we're doubling aura amount every tick
264 aurEff->ChangeAmount(aurEff->GetAmount() * 2);
265 }
266
267 void HandleEffectCalcAmount(AuraEffect const* /*aurEff*/, int32& amount, bool& canBeRecalculated)
268 {
269 SF_LOG_INFO("misc", "Amount of Aura Effect is being calculated now!");
270 // we're setting amount to 100
271 amount = 100;
272 // amount will be never recalculated due to applying passive aura
273 canBeRecalculated = false;
274 }
275
276 void HandleEffectCalcPeriodic(AuraEffect const* /*aurEff*/, bool& isPeriodic, int32& amplitude)
277 {
278 SF_LOG_INFO("misc", "Periodic data of Aura Effect is being calculated now!");
279 // we're setting aura to be periodic and tick every 10 seconds
280 isPeriodic = true;
281 amplitude = 2 * IN_MILLISECONDS;
282 }
283
284 void HandleEffectCalcSpellMod(AuraEffect const* /*aurEff*/, SpellModifier*& spellMod)
285 {
286 SF_LOG_INFO("misc", "SpellMod data of Aura Effect is being calculated now!");
287 // we don't want spellmod for example
288 if (spellMod)
289 {
290 delete spellMod;
291 spellMod = NULL;
292 }
293 /*
294 // alternative: we want spellmod for spell which doesn't have it
295 if (!spellMod)
296 {
297 spellMod = new SpellModifier(GetAura());
298 spellMod->op = SPELLMOD_DOT;
299 spellMod->type = SPELLMOD_PCT;
300 spellMod->spellId = GetId();
301 spellMod->mask[1] = 0x00002000;
302 }
303 */
304 }
305
306 // function registering
308 {
311 // AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK - makes handler to be called when aura is reapplied on target
319 /*OnApply += AuraEffectApplyFn();
320 OnRemove += AuraEffectRemoveFn();
321 DoCheckAreaTarget += AuraCheckAreaTargetFn();*/
322 }
323 /*
324 void OnApply()
325 {
326 }
327
328 void OnRemove()
329 {
330 }
331
332 bool DoCheckAreaTarget(Unit* proposedTarget)
333 {
334 }*/
335 };
336
337 // function which creates AuraScript
339 {
340 return new spell_ex_66244AuraScript();
341 }
342};
343
344// example usage of OnEffectManaShield and AfterEffectManaShield hooks
345// see spell_ex_absorb_aura, these hooks work the same as OnEffectAbsorb and AfterEffectAbsorb
346
347// example usage of OnEffectAbsorb and AfterEffectAbsorb hooks
349{
350 public:
351 spell_ex_absorb_aura() : SpellScriptLoader("spell_ex_absorb_aura") { }
352
354 {
356
357 void HandleOnEffectAbsorb(AuraEffect* /*aurEff*/, DamageInfo & dmgInfo, uint32 & absorbAmount)
358 {
359 SF_LOG_INFO("misc", "Our aura is now absorbing damage done to us!");
360 // absorb whole damage done to us
361 absorbAmount = dmgInfo.GetDamage();
362 }
363
364 void HandleAfterEffectAbsorb(AuraEffect* /*aurEff*/, DamageInfo & /*dmgInfo*/, uint32 & absorbAmount)
365 {
366 SF_LOG_INFO("misc", "Our aura has absorbed %u damage!", absorbAmount);
367 }
368
369 // function registering
375 };
376
377 // function which creates AuraScript
379 {
381 }
382};
383
385{
386 public:
387 spell_ex_463() : SpellScriptLoader("spell_ex_463") { }
388
390 {
392
393 bool CheckAreaTarget(Unit* target)
394 {
395 SF_LOG_INFO("misc", "Area aura checks if unit is a valid target for it!");
396 // in our script we allow only players to be affected
397 return target->GetTypeId() == TYPEID_PLAYER;
398 }
403 };
404
405 // function which creates AuraScript
407 {
408 return new spell_ex_463AuraScript();
409 }
410};
411
412// this function has to be added to function set in ScriptLoader.cpp
420
421/* empty script for copypasting
422class spell_ex : public SpellScriptLoader
423{
424 public:
425 spell_ex() : SpellScriptLoader("spell_ex") { }
426
427 class spell_ex_SpellScript : public SpellScript
428 {
429 PrepareSpellScript(spell_ex_SpellScript);
430
431 //bool Validate(SpellInfo const* spellEntry){return true;} OVERRIDE
432 //bool Load(){return true;}
433 //void Unload(){ }
434
435 //void Function(SpellEffIndex effIndex) //OnEffect += SpellEffectFn(spell_ex_SpellScript::Function, EFFECT_ANY, SPELL_EFFECT_ANY);
436 //void Function() //OnHit += SpellEffectFn(spell_ex_SpellScript::Function);
437 void Register() OVERRIDE
438 {
439 }
440 };
441
442 SpellScript* GetSpellScript() const OVERRIDE
443 {
444 return new spell_ex_SpellScript();
445 }
446};
447*/
448
449/* empty script for copypasting
450class spell_ex : public SpellScriptLoader
451{
452 public:
453 spell_ex() : SpellScriptLoader("spell_ex") { }
454
455 class spell_ex_AuraScript : public AuraScript
456 {
457 PrepareAuraScript(spell_ex)
458 //bool Validate(SpellInfo const* spellEntry){return true;} OVERRIDE
459 //bool Load(){return true;}
460 //void Unload(){ }
461
462 //void spell_ex_SpellScript::Function(AuraEffect const* aurEff, AuraEffectHandleModes mode) //OnEffectApply += AuraEffectApplyFn(spell_ex_SpellScript::Function, EFFECT_ANY, SPELL_AURA_ANY, AURA_EFFECT_HANDLE_REAL);
463 //void spell_ex_SpellScript::Function(AuraEffect const* aurEff, AuraEffectHandleModes mode) //OnEffectRemove += AuraEffectRemoveFn(spell_ex_SpellScript::Function, EFFECT_ANY, SPELL_AURA_ANY, AURA_EFFECT_HANDLE_REAL);
464 //void spell_ex_SpellScript::Function(AuraEffect const* aurEff) //OnEffectPeriodic += AuraEffectPeriodicFn(spell_ex_SpellScript::Function, EFFECT_ANY, SPELL_AURA_ANY);
465 //void spell_ex_SpellScript::Function(AuraEffect* aurEff) //OnEffectUpdatePeriodic += AuraEffectUpdatePeriodicFn(spell_ex_SpellScript::Function, EFFECT_ANY, SPELL_AURA_ANY);
466 //void spell_ex_SpellScript::Function(AuraEffect const* aurEff, int32& amount, bool& canBeRecalculated) //DoEffectCalcAmount += AuraEffectCalcAmountFn(spell_ex_SpellScript::Function, EFFECT_ANY, SPELL_AURA_ANY);
467 //void spell_ex_SpellScript::Function(AuraEffect const* aurEff, bool& isPeriodic, int32& amplitude) //OnEffectCalcPeriodic += AuraEffectCalcPeriodicFn(spell_ex_SpellScript::Function, EFFECT_ANY, SPELL_AURA_ANY);
468 //void spell_ex_SpellScript::Function(AuraEffect const* aurEff, SpellModifier*& spellMod) //OnEffectCalcSpellMod += AuraEffectCalcSpellModFn(spell_ex_SpellScript::Function, EFFECT_ANY, SPELL_AURA_ANY);
469 void Register() OVERRIDE
470 {
471 }
472 };
473
474 AuraScript* GetAuraScript() const OVERRIDE
475 {
476 return new spell_ex_AuraScript();
477 }
478};
479*/
@ IN_MILLISECONDS
Definition Common.h:125
std::int32_t int32
Definition Define.h:73
#define UI64FMTD
Definition Define.h:64
std::uint32_t uint32
Definition Define.h:77
#define OVERRIDE
Definition Define.h:60
std::uint64_t uint64
Definition Define.h:76
static constexpr TypeID TYPEID_PLAYER
#define SF_LOG_INFO(filterType__,...)
Definition Log.h:137
SpellEffIndex
@ EFFECT_0
@ SPELL_EFFECT_DUMMY
SpellCastResult
@ SPELL_AURA_DUMMY
AuraEffectHandleModes
@ AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK
@ AURA_EFFECT_HANDLE_REAL
#define sSpellMgr
Definition SpellMgr.h:744
#define SpellCheckCastFn(F)
#define SpellEffectFn(F, I, N)
#define AuraEffectCalcAmountFn(F, I, N)
#define AuraEffectPeriodicFn(F, I, N)
#define AuraEffectUpdatePeriodicFn(F, I, N)
#define SpellCastFn(F)
#define AuraEffectAbsorbFn(F, I)
#define AuraEffectCalcPeriodicFn(F, I, N)
#define AuraEffectApplyFn(F, I, N, M)
#define SpellHitFn(F)
#define AuraEffectCalcSpellModFn(F, I, N)
#define AuraCheckAreaTargetFn(F)
#define AuraEffectRemoveFn(F, I, N, M)
void ChangeAmount(int32 newAmount, bool mark=true, bool onStackOrReapply=false)
int32 GetAmount() const
HookList< EffectCalcPeriodicHandler > DoEffectCalcPeriodic
HookList< EffectApplyHandler > AfterEffectRemove
HookList< EffectPeriodicHandler > OnEffectPeriodic
HookList< EffectApplyHandler > AfterEffectApply
HookList< EffectAbsorbHandler > AfterEffectAbsorb
HookList< EffectCalcAmountHandler > DoEffectCalcAmount
Unit * GetCaster() const
HookList< EffectUpdatePeriodicHandler > OnEffectUpdatePeriodic
HookList< EffectCalcSpellModHandler > DoEffectCalcSpellMod
HookList< EffectAbsorbHandler > OnEffectAbsorb
HookList< CheckAreaTargetHandler > DoCheckAreaTarget
Unit * GetTarget() const
HookList< EffectApplyHandler > OnEffectRemove
HookList< EffectApplyHandler > OnEffectApply
uint32 GetDamage() const
Definition Unit.h:923
TypeID GetTypeId() const
Definition Object.h:131
HookList< CastHandler > AfterCast
HookList< CheckCastHandler > OnCheckCast
HookList< HitHandler > AfterHit
SpellInfo const * GetSpellInfo()
HookList< HitHandler > OnHit
HookList< EffectHandler > OnEffectHit
HookList< EffectHandler > OnEffectHitTarget
HookList< CastHandler > OnCast
Unit * GetHitUnit()
HookList< CastHandler > BeforeCast
HookList< EffectHandler > OnEffectLaunchTarget
HookList< EffectHandler > OnEffectLaunch
Unit * GetCaster()
HookList< HitHandler > BeforeHit
SpellScriptLoader(const char *name)
Definition Unit.h:1367
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)
uint32 DealDamage(Unit *victim, uint32 damage, CleanDamage const *cleanDamage=NULL, DamageEffectType damagetype=DIRECT_DAMAGE, SpellSchoolMask damageSchoolMask=SPELL_SCHOOL_MASK_NORMAL, SpellInfo const *spellProto=NULL, bool durabilityLoss=true)
PrepareAuraScript(spell_ex_463AuraScript)
AuraScript * GetAuraScript() const OVERRIDE
void FilterTargets(std::list< Unit * > &)
bool Validate(SpellInfo const *) OVERRIDE
PrepareSpellScript(spell_ex_5581SpellScript)
SpellScript * GetSpellScript() const OVERRIDE
void HandleEffectPeriodicUpdate(AuraEffect *aurEff)
void HandleEffectCalcPeriodic(AuraEffect const *, bool &isPeriodic, int32 &amplitude)
void HandleEffectPeriodic(AuraEffect const *)
bool Validate(SpellInfo const *) OVERRIDE
PrepareAuraScript(spell_ex_66244AuraScript)
void HandleOnEffectRemove(AuraEffect const *, AuraEffectHandleModes)
void HandleOnEffectApply(AuraEffect const *, AuraEffectHandleModes)
void HandleAfterEffectApply(AuraEffect const *, AuraEffectHandleModes)
void HandleAfterEffectRemove(AuraEffect const *, AuraEffectHandleModes)
void HandleEffectCalcAmount(AuraEffect const *, int32 &amount, bool &canBeRecalculated)
void HandleEffectCalcSpellMod(AuraEffect const *, SpellModifier *&spellMod)
AuraScript * GetAuraScript() const OVERRIDE
PrepareAuraScript(spell_ex_absorb_auraAuraScript)
void HandleOnEffectAbsorb(AuraEffect *, DamageInfo &dmgInfo, uint32 &absorbAmount)
void HandleAfterEffectAbsorb(AuraEffect *, DamageInfo &, uint32 &absorbAmount)
AuraScript * GetAuraScript() const OVERRIDE
void AddSC_example_spell_scripts()
@ SPELL_TRIGGERED