- Reaction score
- 91
http://www.dota-allstars.com/hero/2809/index.html <--- The Hero.
http://www.dota-allstars.com/wiki/Invoker <--- Check this for full information about him.
If you haven't played DotA then just download the testmap at the bottom of this post and see the spells. The screenshots will not show you much, after all the spellpack can be fully seen in-game.
GUI/JASS/vJASS? vJASS.
MUI? Yes.
Lagless? Not so much since it's a huge spellpack. But I've included an optional script that can preload all these resources.
Requires?
- Jass NewGen Pack
- PUI
- GroupUtils
- TimerUtils
- Line Segments
After you have read the two links that give full information on this DotA Hero, you will notice that there are a lot of object editor data that needs to be used and every spell needs to be triggered.
Read me:
//========================================================
InvokerConfig: (this is the configuration library that contains all resources such as raw codes, order strings, etc.)
InvokerPreload (optional library that preloads all of the Invoker's resources)
Invokelist (optional library that displays a text [usually the list of the Invoker's spells] to a specific player)
Screenshot: http://i42.tinypic.com/2wrovhl.jpg
Spheres: (handles all bonuses from Quas/Wex/Exort and displays correctly the spheres above the Invoker)
Screenshot: http://i39.tinypic.com/5wz3mw.jpg
Invoke: (the Invoker's ultimate - Invokes a spell based on a combination between Quas/Wex/Exort)
Cold Snap: (created by having 3 quas orbs and using Invoke)
Screenshot: http://i42.tinypic.com/2d77imp.jpg
EMP: (see the wiki link about the spell)
Screenshot 1: http://i40.tinypic.com/wre73t.jpg
Screenshot 2: http://i44.tinypic.com/2q07qdk.jpg
Sun Strike: (see the wiki link)
Screenshot: http://i39.tinypic.com/14aydk7.jpg
(Continues bellow...)
http://www.dota-allstars.com/wiki/Invoker <--- Check this for full information about him.
If you haven't played DotA then just download the testmap at the bottom of this post and see the spells. The screenshots will not show you much, after all the spellpack can be fully seen in-game.
GUI/JASS/vJASS? vJASS.
MUI? Yes.
Lagless? Not so much since it's a huge spellpack. But I've included an optional script that can preload all these resources.
Requires?
- Jass NewGen Pack
- PUI
- GroupUtils
- TimerUtils
- Line Segments
After you have read the two links that give full information on this DotA Hero, you will notice that there are a lot of object editor data that needs to be used and every spell needs to be triggered.
Read me:
Code:
Spellpack created by Tyrande_ma3x. Credits are not necessary but would be appreciated.
Please do not claim this to be your own.
HOW TO IMPORT:
- First, at the top of each trigger in this folder (The Invoker) there is a green comment that shows the requirements for it.
You must have all those in your map, otherwise it would give you errors. The full resources required can be found in the folder
"Systems". Copy everything from there (if you do not have it) to your map and return back to this folder.
- The main library that is needed for all spells to function normally (AND IS THE MAIN CONFIGURATION) is the trigger InvokerConfig.
If you take a closer look you will see lots of constant integers that represent raw codes of abilities/units/buffs. There are also strings
that contain the order string of a specific ability. To understand easier the naming of the constants I've sorted them with a prefix in front of them:
AID (ability id) - this is a raw code of an ability.
UID (ability id) - this is a raw code of a unit.
OID (order id) - this is an order string.
BID (buff id) - this is a raw code of a buff.
You will also see a few functions at the bottom which might also need configuring depending on your needs. Read the comments and change if you'd like.
It will be quite easy for you to configure the raw codes because I've made the variables exactly as in the object editor. For example:
Ice Wall - UID_ICE_WALL = unit raw code of the Ice Wall unit in Object Editor.
Chaos Meteor Falling - UID_CHAOS_METEOR_FALLING = unit raw code of the Chaos Meteor Falling unit in Object Editor. etc.
Ok, you know how to edit the main configuration script. The next step is quite simple:
Copy EVERYTHING in Object Editor/Units under categorization Custom Units (you may skip the Invoker if you don't want him)!
That's a total of 16 (15) units.
Copy EVERYTHING in Object Editor/Abilities under categorization Custom Abilities/UNDEAD! The Human part is for the testmap.
You can now copy this whole folder (The Invoker) but there are two triggers you can skip:
- InvokerPreload - this is a script that will preload all those Invoker's resources at map initialization.
- Invokelist - a script that gives you a command that will display a message for the triggering player. Usually this message would be the list of the Invoker's spells.
After you have copied the whole folder, go through every trigger and check the configuration menu. EDIT WHAT NEEDS EDITING!
This is a lot of work to do and it cannot be done really fast. Enjoy your Invoker!
//========================================================
InvokerConfig: (this is the configuration library that contains all resources such as raw codes, order strings, etc.)
JASS:
library InvokerConfig initializer Init
// Requires nothing.
//===============================================================================
// C O N F I G U R E E V E R Y T H I N G H E R E I F N E C E S S A R Y
//===============================================================================
globals
// Raw code of your Hero that is going to have all of the Invoker's spells.
constant integer UID_INVOKER = 039;H000039;
// Raw code of your generic dummy unit.
constant integer UID_DUMMY = 039;e000039;
// The EMP unit that is created at the target point of an EMP cast.
constant integer UID_EMP = 039;e001039;
// The EMP Blast unit that is created when the ball explodes, drains mana and deals damage.
// It uses an unit because this way it can get scaled to a much bigger size.
constant integer UID_EMP_BLAST = 039;e002039;
// Raw code of the Chaos Meteor unit (the unit that is supposed to "roll").
constant integer UID_CHAOS_METEOR = 039;e003039;
// Raw code of the Chaos Meteor Falling unit (the meteor that falls from the sky).
constant integer UID_CHAOS_METEOR_FALLING = 039;e004039;
// Raw code of the Tornado unit.
constant integer UID_TORNADO = 039;e005039;
// Raw code of the Deafening Blast unit.
constant integer UID_DEAFENING_BLAST = 039;e006039;
// Raw code of the Ice Wall unit.
constant integer UID_ICE_WALL = 039;e007039;
//===============================================================================
// Order string of casting the ability Cold Snap Ministun.
constant string OID_COLD_SNAP_MINISTUN = "thunderbolt"
// Order string of casting the ability Tornado Cyclone.
constant string OID_TORNADO_CYCLONE = "cyclone"
// Order string for casting the ability Deafening Blast Silence.
constant string OID_DEAFENING_BLAST_SILENCE = "soulburn"
// Order string for casting the ability Ghost Walk Self Slow.
constant string OID_GHOST_WALK_SELF_SLOW = "slow"
//===============================================================================
// These are the raw codes of the abilities that give the sphere effect.
// Reference them as Quas Sphere First/Second/Third and fill in their raw code accordingly.
// Raw code of the spell Quas Sphere First
constant integer AID_QUAS_FIRST = 039;A008039;
// Raw code of Quas Sphere Second... etc.
constant integer AID_QUAS_SECOND = 039;A009039;
constant integer AID_QUAS_THIRD = 039;A00A039;
// Reference these as Wex Sphere First/Second/Third and fill in their raw codes accordingly.
constant integer AID_WEX_FIRST = 039;A005039;
constant integer AID_WEX_SECOND = 039;A006039;
constant integer AID_WEX_THIRD = 039;A007039;
// Reference these as Exort Sphere First/Second/Third and fill their raw codes accordingly.
constant integer AID_EXORT_FIRST = 039;A002039;
constant integer AID_EXORT_SECOND = 039;A003039;
constant integer AID_EXORT_THIRD = 039;A004039;
// Raw code of the Hero ability Quas.
constant integer AID_QUAS = 039;A00D039;
// Raw code of the Hero ability Wex.
constant integer AID_WEX = 039;A00C039;
// Raw code of the Hero ability Exort.
constant integer AID_EXORT = 039;A00B039;
// Raw code of the Hero ability Invoke.
constant integer AID_INVOKE = 039;A00E039;
//===============================================================================
// Buff raw code of the ability Ghost Walk.
constant integer BID_GHOST_WALK = 039;B004039;
// Buff raw code of the ability Ghost Walk Self Slow.
constant integer BID_GHOST_WALK_SELF_SLOW = 039;B003039;
//===============================================================================
// Raw codes of the abilities that gives movement/attack speed bonuses when Wex is in use.
constant integer AID_WEX_MOVEMENT_SPEED_BONUS = 039;A00I039;
constant integer AID_WEX_ATTACK_SPEED_BONUS = 039;A00J039;
// Raw code of the spellbook that contains the movement speed bonus by Wex.
constant integer AID_WEX_SPELLBOOK = 039;A00K039;
// Raw code of the ability that gives damage bonuses when Exort is in use.
constant integer AID_EXORT_BONUS = 039;A00F039;
// Raw code of the Cold Snap ability.
constant integer AID_COLD_SNAP = 039;A00G039;
// Raw code of the dummy ability that is used to ministun and deal damage (Cold Snap Ministun).
constant integer AID_COLD_SNAP_MINISTUN = 039;A00H039;
// Raw code of the EMP ability.
constant integer AID_EMP = 039;A00L039;
// Raw code of the Sun Strike ability.
constant integer AID_SUN_STRIKE = 039;A00N039;
// Raw code of the Chaos Meteor ability.
constant integer AID_CHAOS_METEOR = 039;A00M039;
// Raw code of the Alacrity ability.
constant integer AID_ALACRITY = 039;A00O039;
// Raw code of the ability that gives damage (Alacrity Damage Bonus).
constant integer AID_ALACRITY_DAMAGE_BONUS = 039;A00P039;
// Raw code of the ability that gives attack speed (Alacrity Speed Bonus).
constant integer AID_ALACRITY_SPEED_BONUS = 039;A00Q039;
// Raw code of the ability Tornado.
constant integer AID_TORNADO = 039;A00R039;
// Raw code of the ability Tornado Cyclone that cyclones affected units.
constant integer AID_TORNADO_CYCLONE = 039;A00S039;
// Raw code of the ability Deafening Blast.
constant integer AID_DEAFENING_BLAST = 039;A00W039;
// Raw code of the ability Deafening Blast Disable Attack that is supposed to disable a unit's attack.
// Based on Cargo Hold (Orc Burrow).
constant integer AID_DEAFENING_BLAST_DISABLE_ATTACK = 039;A00T039;
// Raw code of the ability Deafening Blast Silence.
constant integer AID_DEAFENING_BLAST_SILENCE = 039;A00V039;
// Raw code of the Ice Wall ability.
constant integer AID_ICE_WALL = 039;A00X039;
// Raw code of the Ice Wall Slow Aura ability.
constant integer AID_ICE_WALL_SLOW_AURA = 039;A00Y039;
// Raw code of the Ghost Walk ability.
constant integer AID_GHOST_WALK = 039;A00Z039;
// Raw code of the Ghost Walk Aura ability.
constant integer AID_GHOST_WALK_AURA = 039;A010039;
// Raw code of the ability Ghost Walk Self Slow.
constant integer AID_GHOST_WALK_SELF_SLOW = 039;A011039;
// Raw code of the ability Forge Spirit.
constant integer AID_FORGE_SPIRIT = 039;A012039;
// Raw code of the ability Forge Spirit Armor Melt.
constant integer AID_FORGE_SPIRIT_ARMOR_MELT = 039;A013039;
// Raw code of the ability Forge Spirit Armor Bonus.
constant integer AID_FORGE_SPIRIT_ARMOR_BONUS = 039;A014039;
// Raw code of the ability Forge Spirit Mana Bonus.
constant integer AID_FORGE_SPIRIT_MANA_BONUS = 039;A015039;
endglobals
//===============================================================================
// Since real numbers cannot be used in life regeneration spells, Quas' regeneration
// has to be triggered for special cases like these.
public constant function QUAS_REGENERATION takes integer level returns real
return 0.75 * level
// Each level gives 0.75 regeneration PER ONE INSTANCE.
// If you have 3 instances you would get 2.25 hp/sec.
// And 15.75 for 3 instances and maximum level.
endfunction
// Choose a limitation to which levels to make it invoke only 1 spell.
// If you, for example, returned 3 it will allow 2 invokes only at level 4 and above.
public constant function LIMIT takes integer level returns integer
return 1
endfunction
globals
// DO NOT TOUCH OR CHANGE THIS INTEGER ARRAY!
integer array SPIRIT
endglobals
// Edit this by adding or changing raw codes and array indexes.
// REMEMBER TO ALWAYS START FROM SPIRIT[1] AND INCREASE BY ONE WITHOUT SKIPPING AN INDEX!
// For example: SPIRIT[1], SPIRIT[3], SPIRIT[4] <---- WRONG.
// The index represents what spirit will be spawned at that level.
// For example: Spirit[3] - A spirit with raw code 'n002' will be spawned.
private function SetForgeSpiritData takes nothing returns nothing
// Level 1.
set SPIRIT[1] = 039;n000039;
// Level 2.
set SPIRIT[2] = 039;n001039;
// Level 3.
set SPIRIT[3] = 039;n002039;
// etc.
set SPIRIT[4] = 039;n003039;
set SPIRIT[5] = 039;n004039;
set SPIRIT[6] = 039;n005039;
set SPIRIT[7] = 039;n006039;
endfunction
//===============================================================================
// E N D O F C O N F I G U R A T I O N M E N U
//===============================================================================
private function Init takes nothing returns nothing
local integer a = 0
// Make the spellbook hidden so the bonuses' icons can't be seen.
loop
exitwhen a > 11
call SetPlayerAbilityAvailable(Player(a), AID_WEX_SPELLBOOK, false)
set a = a + 1
endloop
call SetForgeSpiritData()
endfunction
endlibrary
InvokerPreload (optional library that preloads all of the Invoker's resources)
JASS:
library InvokerPreload initializer Init requires InvokerConfig, AbilityPreload
// Look above what it requires.
//===============================================================================
// THIS IS AN OPTIONAL LIBRARY THAT WILL PRELOAD ALL OF THE INVOKER'S RESOURCES
// AT MAP INITIALIZATION. IF YOU WANT YOU CAN COPY IT IN YOUR MAP HAVING IN MIND
// THAT IT WOULD CAUSE A SPIKE JUST AT THE START DUE TO THE BIG AMOUNTS OF DATA.
// IT IS OPTIONAL BECAUSE YOU MAY WANT TO PRELOAD YOUR STUFF IN A DIFFERENT WAY.
//===============================================================================
private function Init takes nothing returns nothing
local integer a = 0
call AbilityPreload(AID_QUAS_FIRST)
call AbilityPreload(AID_QUAS_SECOND)
call AbilityPreload(AID_QUAS_THIRD)
call AbilityPreload(AID_WEX_FIRST)
call AbilityPreload(AID_WEX_SECOND)
call AbilityPreload(AID_WEX_THIRD)
call AbilityPreload(AID_EXORT_FIRST)
call AbilityPreload(AID_EXORT_SECOND)
call AbilityPreload(AID_EXORT_THIRD)
call AbilityPreload(AID_QUAS)
call AbilityPreload(AID_WEX)
call AbilityPreload(AID_EXORT)
call AbilityPreload(AID_INVOKE)
call AbilityPreload(AID_WEX_ATTACK_SPEED_BONUS)
// Uknown why but preloading these at Map Initialization crashes with fatal error.
//call AbilityPreload(AID_WEX_SPELLBOOK) <--- Causes Fatal Error.
//call AbilityPreload(AID_WEX_MOVEMENT_SPEED_BONUS) <--- Causes Fatal Error.
call AbilityPreload(AID_EXORT_BONUS)
call AbilityPreload(AID_COLD_SNAP)
call AbilityPreload(AID_COLD_SNAP_MINISTUN)
call AbilityPreload(AID_EMP)
call AbilityPreload(AID_SUN_STRIKE)
call AbilityPreload(AID_CHAOS_METEOR)
call AbilityPreload(AID_TORNADO)
call AbilityPreload(AID_TORNADO_CYCLONE)
call AbilityPreload(AID_DEAFENING_BLAST)
call AbilityPreload(AID_DEAFENING_BLAST_DISABLE_ATTACK)
call AbilityPreload(AID_ICE_WALL)
call AbilityPreload(AID_ICE_WALL_SLOW_AURA)
call AbilityPreload(AID_GHOST_WALK)
call AbilityPreload(AID_GHOST_WALK_AURA)
call AbilityPreload(AID_FORGE_SPIRIT)
call AbilityPreload(AID_FORGE_SPIRIT_ARMOR_MELT)
call AbilityPreload(AID_FORGE_SPIRIT_ARMOR_BONUS)
call AbilityPreload(AID_FORGE_SPIRIT_MANA_BONUS)
call UnitApplyTimedLife(CreateUnit(Player(13), UID_INVOKER, 9999999., 999999., 0.), 039;BTLF039;, 2.)
call UnitApplyTimedLife(CreateUnit(Player(13), UID_DUMMY, 9999999., 999999., 0.), 039;BTLF039;, 2.)
call UnitApplyTimedLife(CreateUnit(Player(13), UID_EMP, 9999999., 999999., 0.), 039;BTLF039;, 2.)
call UnitApplyTimedLife(CreateUnit(Player(13), UID_EMP_BLAST, 9999999., 999999., 0.), 039;BTLF039;, 2.)
call UnitApplyTimedLife(CreateUnit(Player(13), UID_CHAOS_METEOR, 9999999., 999999., 0.), 039;BTLF039;, 2.)
call UnitApplyTimedLife(CreateUnit(Player(13), UID_CHAOS_METEOR_FALLING, 9999999., 999999., 0.), 039;BTLF039;, 2.)
call UnitApplyTimedLife(CreateUnit(Player(13), UID_TORNADO, 9999999., 999999., 0.), 039;BTLF039;, 2.)
call UnitApplyTimedLife(CreateUnit(Player(13), UID_ICE_WALL, 9999999., 999999., 0.), 039;BTLF039;, 2.)
loop
exitwhen SPIRIT[a] == null
call UnitApplyTimedLife(CreateUnit(Player(13), SPIRIT[a], 9999999., 999999., 0.), 039;BTLF039;, 2.)
set a = a + 1
endloop
endfunction
endlibrary
Invokelist (optional library that displays a text [usually the list of the Invoker's spells] to a specific player)
Screenshot: http://i42.tinypic.com/2wrovhl.jpg
JASS:
scope Invokelist initializer Init
// Requires nothing.
//===============================================================================
// C O N F I G U R A T I O N M E N U
//===============================================================================
globals
// Should a message appear at Map Initialization reminding what is the command?
private constant boolean REMINDER = true
// If yes, then this message will be displayed:
private constant string REMINDER_MESSAGE = "Type |cffffcc00-invokelist|r to see what spells you can invoke."
// Should previous text messages be cleared so only the list be visible for the player?
// True or false.
private constant boolean CLEAR_MESSAGES = true
// Duration of the list that is going to be displayed for the player (in seconds).
private constant real LIST_DURATION = 30.
// Don't touch this string array!!!
private string array SPELL
endglobals
// You can add your list here by filling the value SPELL[x] (x is a number) from 0 to
// as much as you like. Then all these will be displayed after the user types -invokelist.
// Remember to always start at 0 and NEVER have a missing index inbetween
// (for example SPELL[0], SPELL[1], SPELL[3] <--- that is WRONG and will not display the whole list).
private function Set takes nothing returns nothing
// All those FF03535 etc. symbols are colour codes.
set SPELL[0] = "Sun Strike [|CFFFF0303EEE|r] - [|cffffcc00T|r]"
set SPELL[1] = "Chaos Meteor [|CFFFF0303EE|r|cff93ffc9W|r] - [|cffffcc00D|r]"
set SPELL[2] = "Forge Spirit [|CFFFF0303EE|r|CFF0042FFQ|r] - [|cffffcc00F|r]"
set SPELL[3] = "Cold Snap [|CFF0042FFQQQ|r] - [|cffffcc00Y|r]"
set SPELL[4] = "Ghost Walk [|CFF0042FFQQ|r|cff93ffc9W|r] - [|cffffcc00V|r]"
set SPELL[5] = "Ice Wall [|CFF0042FFQQ|r|cff93ffc9E|r] - [|cffffcc00G|r]"
set SPELL[6] = "Alacrity [|cff93ffc9WW|r|CFFFF0303E|r] - [|cffffcc00Z|r]"
set SPELL[7] = "Tornado [|cff93ffc9WW|r|CFF0042FFQ|r] - [|cffffcc00X|r]"
set SPELL[8] = "EMP [|cff93ffc9WWW|r] - [|cffffcc00C|r]"
set SPELL[9] = "Deafening Blast [|CFF0042FFQ|r|cff93ffc9W|r|CFFFF0303E|r] - [|cffffcc00B|r]"
endfunction
//===============================================================================
// E N D O F C O N F I G U R A T I O N M E N U
//===============================================================================
private function Actions takes nothing returns nothing
local integer a = 0
if CLEAR_MESSAGES then
if GetLocalPlayer() == GetTriggerPlayer() then
call ClearTextMessages()
endif
endif
loop
exitwhen SPELL[a] == null
call DisplayTimedTextToPlayer(GetTriggerPlayer(), 0., 0., LIST_DURATION, SPELL[a])
set a = a + 1
endloop
endfunction
private function Init takes nothing returns nothing
local trigger trig = CreateTrigger()
local integer a = 0
loop
exitwhen a > 11
call TriggerRegisterPlayerChatEvent(trig, Player(a), "-invokelist", true)
set a = a + 1
endloop
call TriggerAddAction(trig, function Actions)
if REMINDER then
call BJDebugMsg(REMINDER_MESSAGE)
endif
call Set()
endfunction
endscope
Spheres: (handles all bonuses from Quas/Wex/Exort and displays correctly the spheres above the Invoker)
Screenshot: http://i39.tinypic.com/5wz3mw.jpg
JASS:
scope Spheres initializer Init
// Requires PUI and InvokerConfig.
//===============================================================================
// * This script handles all orb combination and changes and keeps track of them.
// * It also takes care of the bonuses given by Quas/Wex/Exort and of invoked spells.
//===============================================================================
//========================
// No configuration here.=
//========================
globals
// Group for enumerating.
private group gr = CreateGroup()
// Unit used for FirstOfGroup().
private unit fir = null
endglobals
// Even if this isn't private, it shouldn't be touched.
// Do not edit it unless you know what you are doing!
struct Spheres
//! runtextmacro PUI()
integer quas = 0
integer wex = 0
integer exort = 0
integer count = 0
integer invokes = 0
integer invoke1 = 0
integer invoke2 = 0
endstruct
private function Conditions takes nothing returns boolean
// One of the three spells should be casted.
return GetSpellAbilityId() == AID_QUAS or GetSpellAbilityId() == AID_WEX or GetSpellAbilityId() == AID_EXORT
endfunction
// The bonuses given by the orbs should be updated when a new level of Exort/Wex is learned.
// There is no need for Quas since it's triggered.
private function FixBonuses takes nothing returns boolean
local unit cast = GetTriggerUnit()
local Spheres d = Spheres[cast]
if GetLearnedSkill() == AID_EXORT and GetUnitAbilityLevel(cast, AID_EXORT_BONUS) > 0 then
call SetUnitAbilityLevel(cast, AID_EXORT_BONUS, GetUnitAbilityLevel(cast, AID_EXORT) * d.exort)
elseif GetLearnedSkill() == AID_WEX and GetUnitAbilityLevel(cast, AID_WEX_MOVEMENT_SPEED_BONUS) > 0 then
call SetUnitAbilityLevel(cast, AID_WEX_MOVEMENT_SPEED_BONUS, GetUnitAbilityLevel(cast, AID_WEX) * d.wex)
call SetUnitAbilityLevel(cast, AID_WEX_ATTACK_SPEED_BONUS, GetUnitAbilityLevel(cast, AID_WEX) * d.wex)
endif
set cast = null
return false
endfunction
private function GetInvoker takes nothing returns boolean
return GetUnitTypeId(GetFilterUnit()) == UID_INVOKER and GetUnitAbilityLevel(GetFilterUnit(), AID_QUAS) > 0 and GetWidgetLife(GetFilterUnit()) > 0.405 and IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) == false
// Double check.
endfunction
private function Callback takes nothing returns nothing
local real heal
local Spheres d
// Get the Invokers on the map (there can be more than one of them).
call GroupEnumUnitsInRange(gr, 0., 0., 999999., Condition(function GetInvoker))
loop
set fir = FirstOfGroup(gr)
exitwhen fir == null
set d = Spheres[fir]
// Is the struct created and attached?
if d != 0 then
// Is a Quas orb activated?
if d.quas > 0 then
set heal = InvokerConfig_QUAS_REGENERATION(GetUnitAbilityLevel(fir, AID_QUAS)) * d.quas
call SetWidgetLife(fir, GetWidgetLife(fir) + heal)
endif
endif
call GroupRemoveUnit(gr, fir)
endloop
endfunction
private function Actions takes nothing returns nothing
local unit cast = GetTriggerUnit()
local Spheres d = Spheres[cast]
// Was the struct already created? If no, create it and "attach" with PUI.
if d == 0 then
set d = Spheres.create()
set Spheres[cast] = d
endif
// Used for counting the spheres... If it gets over 3 then return it back
// to 1 so the cycle can begin once again and orbs can get replaced.
if d.count < 3 then
set d.count = d.count + 1
else
set d.count = 1
endif
// Was Quas casted?
if GetSpellAbilityId() == AID_QUAS then
// Maybe the first orb must be replaced?
if d.count == 1 then
// Remove all attached orb effects.
call UnitRemoveAbility(cast, AID_QUAS_FIRST)
call UnitRemoveAbility(cast, AID_WEX_FIRST)
call UnitRemoveAbility(cast, AID_EXORT_FIRST)
// And add the one that is really needed.
call UnitAddAbility(cast, AID_QUAS_FIRST)
// Or maybe the second sphere needs to be replaced>
elseif d.count == 2 then
// Remove again.
call UnitRemoveAbility(cast, AID_QUAS_SECOND)
call UnitRemoveAbility(cast, AID_WEX_SECOND)
call UnitRemoveAbility(cast, AID_EXORT_SECOND)
// Add the necessary one.
call UnitAddAbility(cast, AID_QUAS_SECOND)
// Nothing left, it must be the 3rd orb.
elseif d.count == 3 then
// Remove.
call UnitRemoveAbility(cast, AID_QUAS_THIRD)
call UnitRemoveAbility(cast, AID_WEX_THIRD)
call UnitRemoveAbility(cast, AID_EXORT_THIRD)
// Add.
call UnitAddAbility(cast, AID_QUAS_THIRD)
endif
// Was Wex casted instead?
elseif GetSpellAbilityId() == AID_WEX then
// Same cycle as in Exort.
if d.count == 1 then
// Remove.
call UnitRemoveAbility(cast, AID_QUAS_FIRST)
call UnitRemoveAbility(cast, AID_WEX_FIRST)
call UnitRemoveAbility(cast, AID_EXORT_FIRST)
// Add.
call UnitAddAbility(cast, AID_WEX_FIRST)
// Is it second sphere?
elseif d.count == 2 then
// Remove.
call UnitRemoveAbility(cast, AID_QUAS_SECOND)
call UnitRemoveAbility(cast, AID_WEX_SECOND)
call UnitRemoveAbility(cast, AID_EXORT_SECOND)
// Add.
call UnitAddAbility(cast, AID_WEX_SECOND)
elseif d.count == 3 then
call UnitRemoveAbility(cast, AID_QUAS_THIRD)
call UnitRemoveAbility(cast, AID_WEX_THIRD)
call UnitRemoveAbility(cast, AID_EXORT_THIRD)
call UnitAddAbility(cast, AID_WEX_THIRD)
endif
// Exort was casted if it wasn't the other two:
else
if d.count == 1 then
call UnitRemoveAbility(cast, AID_QUAS_FIRST)
call UnitRemoveAbility(cast, AID_WEX_FIRST)
call UnitRemoveAbility(cast, AID_EXORT_FIRST)
// Add first exort orb effect.
call UnitAddAbility(cast, AID_EXORT_FIRST)
elseif d.count == 2 then
call UnitRemoveAbility(cast, AID_QUAS_SECOND)
call UnitRemoveAbility(cast, AID_WEX_SECOND)
call UnitRemoveAbility(cast, AID_EXORT_SECOND)
// Add second exort orb effect.
call UnitAddAbility(cast, AID_EXORT_SECOND)
elseif d.count == 3 then
call UnitRemoveAbility(cast, AID_QUAS_THIRD)
call UnitRemoveAbility(cast, AID_WEX_THIRD)
call UnitRemoveAbility(cast, AID_EXORT_THIRD)
// Add third exort orb effect.
call UnitAddAbility(cast, AID_EXORT_THIRD)
endif
endif
// Set the counting for the orbs to 0.
set d.wex = 0
set d.exort = 0
set d.quas = 0
// And start checking one by one the number of activated instances.
if GetUnitAbilityLevel(cast, AID_WEX_FIRST) > 0 then
set d.wex = d.wex + 1
endif
if GetUnitAbilityLevel(cast, AID_WEX_SECOND) > 0 then
set d.wex = d.wex + 1
endif
if GetUnitAbilityLevel(cast, AID_WEX_THIRD) > 0 then
set d.wex = d.wex + 1
endif
if GetUnitAbilityLevel(cast, AID_EXORT_FIRST) > 0 then
set d.exort = d.exort + 1
endif
if GetUnitAbilityLevel(cast, AID_EXORT_SECOND) > 0 then
set d.exort = d.exort + 1
endif
if GetUnitAbilityLevel(cast, AID_EXORT_THIRD) > 0 then
set d.exort = d.exort + 1
endif
if GetUnitAbilityLevel(cast, AID_QUAS_FIRST) > 0 then
set d.quas = d.quas + 1
endif
if GetUnitAbilityLevel(cast, AID_QUAS_SECOND) > 0 then
set d.quas = d.quas + 1
endif
if GetUnitAbilityLevel(cast, AID_QUAS_THIRD) > 0 then
set d.quas = d.quas + 1
endif
// First remove the abilities that give bonuses.
call UnitRemoveAbility(cast, AID_WEX_SPELLBOOK)
call UnitRemoveAbility(cast, AID_WEX_ATTACK_SPEED_BONUS)
call UnitRemoveAbility(cast, AID_EXORT_BONUS)
// And re-add them if it's necessary.
if d.wex > 0 then
call UnitAddAbility(cast, AID_WEX_SPELLBOOK)
call UnitAddAbility(cast, AID_WEX_ATTACK_SPEED_BONUS)
endif
if d.exort > 0 then
call UnitAddAbility(cast, AID_EXORT_BONUS)
endif
// Modify their level depending on the main abilities' level and the number of activated orbs.
call SetUnitAbilityLevel(cast, AID_WEX_MOVEMENT_SPEED_BONUS, GetUnitAbilityLevel(cast, AID_WEX) * d.wex)
call SetUnitAbilityLevel(cast, AID_WEX_ATTACK_SPEED_BONUS, GetUnitAbilityLevel(cast, AID_WEX) * d.wex)
call SetUnitAbilityLevel(cast, AID_EXORT_BONUS, GetUnitAbilityLevel(cast, AID_EXORT) * d.exort)
set cast = null
endfunction
private function Init takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trig, Condition(function Conditions))
call TriggerAddAction(trig, function Actions)
set trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_HERO_SKILL)
call TriggerAddCondition(trig, Condition(function FixBonuses))
call TimerStart(CreateTimer(), 1., true, function Callback)
endfunction
endscope
Invoke: (the Invoker's ultimate - Invokes a spell based on a combination between Quas/Wex/Exort)
JASS:
scope Invoke initializer Init
// Requires PUI, Spheres, InvokerConfig.
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == AID_INVOKE
endfunction
private function Actions takes nothing returns nothing
local unit cast = GetTriggerUnit()
local integer temp
local integer lvl = GetUnitAbilityLevel(cast, AID_INVOKE)
local Spheres d = Spheres[cast]
// Some checks to prevent more than 2 invokes (and a limit check, ofc).
if d.invokes < 2 and lvl > InvokerConfig_LIMIT(lvl) then
set d.invokes = d.invokes + 1
else
set d.invokes = 1
endif
// Next are some checks to see what combinations were made:
// 3 times Exort - Sun Strike.
if d.exort == 3 then
set temp = AID_SUN_STRIKE
// 3 times Wex - EMP.
elseif d.wex == 3 then
set temp = AID_EMP
// 3 times Quas - Cold Snap.
elseif d.quas == 3 then
set temp = AID_COLD_SNAP
// 2 times Exort and 1 time Wex - Chaos Meteor.
elseif d.exort == 2 and d.wex == 1 then
set temp = AID_CHAOS_METEOR
// 2 times Wex and 1 time Exort - Alacrity.
elseif d.wex == 2 and d.exort == 1 then
set temp = AID_ALACRITY
// 2 times Wex and 1 time Quas - Tornado.
elseif d.wex == 2 and d.quas == 1 then
set temp = AID_TORNADO
// 1 time Quas, 1 time Wex and 1 time Exort - Deafening Blast.
elseif d.quas == 1 and d.wex == 1 and d.exort == 1 then
set temp = AID_DEAFENING_BLAST
// 2 times Quas, 1 time Exort - Ice Wall.
elseif d.quas == 2 and d.exort == 1 then
set temp = AID_ICE_WALL
// 2 times Quas, 1 time Wex - Ghost Walk.
elseif d.quas == 2 and d.wex == 1 then
set temp = AID_GHOST_WALK
// 2 times Exort, 1 time Quas - Forge Spirit.
elseif d.exort == 2 and d.quas == 1 then
set temp = AID_FORGE_SPIRIT
endif
// Other checks to see which ability needs to be replaced.
// Of course, it shouldn't be the previous invoked one because that would
// make you have one invoked spell forever. A cycle is needed.
// And a check must be done to see if the spell that is going to be replaced
// is the same (if it just replaced then cooldown could be reseted and thus abused).
if d.invokes == 1 and temp != d.invoke1 then
call UnitRemoveAbility(cast, d.invoke1)
set d.invoke1 = temp
call UnitAddAbility(cast, d.invoke1)
elseif d.invokes == 2 and temp != d.invoke2 then
call UnitRemoveAbility(cast, d.invoke2)
set d.invoke2 = temp
call UnitAddAbility(cast, d.invoke2)
endif
set cast = null
endfunction
private function Init takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trig, Condition(function Conditions))
call TriggerAddAction(trig, function Actions)
endfunction
endscope
Cold Snap: (created by having 3 quas orbs and using Invoke)
Screenshot: http://i42.tinypic.com/2d77imp.jpg
JASS:
scope ColdSnap initializer Init
// Requires PUI, TimerUtils, LightLeaklessDamageDetect, InvokerConfig.
//===============================================================================
// C O N F I G U R A T I O N M E N U
//===============================================================================
globals
// Special effect attached to the target while Cold Snap is active.
private constant string SFX_ONE = "Abilities\\Weapons\\SpiritOfVengeanceMissile\\SpiritOfVengeanceMissile.mdl"
// Attachment point of the special effect (SFX_ONE).
private constant string AP_ONE = "overhead"
endglobals
// Duration of the ability.
private constant function DURATION takes integer level returns real
return 2.5 + (level * 0.5)
endfunction
// Interval in which affected enemies cannot get ministunned.
private constant function MINISTUN_INTERVAL takes integer level returns real
return 0.8 - (0.028 * level)
endfunction
//===============================================================================
// E N D O F C O N F I G U R A T I O N M E N U
//===============================================================================
// PUI properties for checking whether a unit was hit and prevent endless
// ministuns and passing the level of Quas.
//! runtextmacro PUI_PROPERTY("private", "boolean", "AFFECTED", "false")
//! runtextmacro PUI_PROPERTY("private", "integer", "LEVEL", "0")
globals
// Group that contains all units that have Cold Snap on them.
private group gr = CreateGroup()
// A pointer for a dummy unit.
private unit dum = null
endglobals
private struct Data
unit targ
timer tim
effect sfx
static method create takes unit targ returns Data
local Data d = Data.allocate()
set d.targ = targ
set d.tim = NewTimer()
call SetTimerData(d.tim, d)
return d
endmethod
method onDestroy takes nothing returns nothing
call DestroyEffect(.sfx)
call ReleaseTimer(.tim)
endmethod
endstruct
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == AID_COLD_SNAP
endfunction
private function Refresh takes nothing returns nothing
local timer tim = GetExpiredTimer()
local Data d = GetTimerData(tim)
// Allow the target to be affected by a ministun next time it gets damaged.
set AFFECTED[d.targ] = false
call d.destroy()
set tim = null
endfunction
private function OnDamage takes nothing returns boolean
local unit cast = GetEventDamageSource()
local unit targ = GetTriggerUnit()
local Data d
// Is the unit allowed to get ministunned? Does it have Cold Snap on it?
if AFFECTED[targ] == false and IsUnitInGroup(targ, gr) and GetEventDamage() > 1. then
// No more ministun activating until the timer expires.
set AFFECTED[targ] = true
set d = Data.create(targ)
call TimerStart(d.tim, MINISTUN_INTERVAL(LEVEL[targ]), false, function Refresh)
// Creating the dummy and cause it to cast the ministun.
set dum = CreateUnit(GetOwningPlayer(cast), UID_DUMMY, GetUnitX(targ), GetUnitY(targ), 0.)
call UnitAddAbility(dum, 039;Aloc039;)
call UnitAddAbility(dum, AID_COLD_SNAP_MINISTUN)
call IssueTargetOrder(dum, OID_COLD_SNAP_MINISTUN, targ)
call UnitApplyTimedLife(dum, 039;BTLF039;, 0.5)
set dum = null
endif
set cast = null
set targ = null
return false
endfunction
private function Callback takes nothing returns nothing
local timer tim = GetExpiredTimer()
local Data d = GetTimerData(tim)
// Remove the affected unit from the Cold Snap group because the duration has ended.
call GroupRemoveUnit(gr, d.targ)
call d.destroy()
set tim = null
endfunction
private function Actions takes nothing returns nothing
local unit cast = GetTriggerUnit()
local integer lvl = GetUnitAbilityLevel(cast, AID_QUAS)
local Data d = Data.create(GetSpellTargetUnit())
// Pass the level of Quas for the casting unit to the target.
// This value gets accessed when the target gets damaged.
set LEVEL[d.targ] = lvl
// Add an effect.
set d.sfx = AddSpecialEffectTarget(SFX_ONE, d.targ, AP_ONE)
// Add the unit to the Cold Snap group.
call GroupAddUnit(gr, d.targ)
call TimerStart(d.tim, DURATION(lvl), false, function Callback)
set cast = null
endfunction
private function Init takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trig, Condition(function Conditions))
call TriggerAddAction(trig, function Actions)
call AddOnDamageFunc(Condition(function OnDamage))
call Preload(SFX_ONE)
endfunction
endscope
EMP: (see the wiki link about the spell)
Screenshot 1: http://i40.tinypic.com/wre73t.jpg
Screenshot 2: http://i44.tinypic.com/2q07qdk.jpg
JASS:
scope EMP initializer Init
// Requires TimerUtils, InvokerConfig.
//===============================================================================
// C O N F I G U R A T I O N M E N U
//===============================================================================
globals
// Period used for changing the size of the EMP unit.
// Keep it in range 0.10 - 0.20.
private constant real PERIOD = 0.1
// Attack type of the damaging when EMP explodes.
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_CHAOS
// Damage type of the damaging when EMP explodes.
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_UNIVERSAL
// Weapon type of the damaging when EMP explodes.
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
endglobals
// The duration of the wait between casting EMP and the explosion.
private constant function DELAY takes integer level returns real
return 4. - (0.29 * level)
endfunction
// Mana drained when the ball explodes.
private constant function MANA_DRAINED takes integer level returns real
return 57. * level
endfunction
// Damage dealt when the ball explodes (in this case - 50% of mana drained).
private constant function DAMAGE takes integer level returns real
return 0.5 * (MANA_DRAINED(level))
endfunction
// Area of effect in which enemies get damaged/mana drained.
private constant function AREA_OF_EFFECT takes integer level returns real
return 700.
endfunction
// Scaling of the EMP unit when it's created.
private constant function STARTING_SCALING takes integer level returns real
return 2.5
endfunction
// The maximum scaling the EMP unit reaches (it grows) before it explodes.
private constant function MAXIMUM_SCALING takes integer level returns real
return 5.
endfunction
// Animation speed of the EMP unit.
private constant function BALL_ANIMATION_SPEED takes integer level returns real
return 0.35
endfunction
// Animation speed of the EMP Blast unit (might want to be a little slower?).
private constant function BLAST_ANIMATION_SPEED takes integer level returns real
return 0.25
endfunction
// Duration of the EMP Blast unit (if you chose a faster effect you could decrease this
// so it doesn't get created multiple times).
private constant function BLAST_DURATION takes integer level returns real
return 4.
endfunction
//===============================================================================
// E N D O F C O N F I G U R A T I O N M E N U
//===============================================================================
globals
// Group used for enumerations.
private group gr = CreateGroup()
// Unit used for FirstOfGroup() and global caster passing for filters.
private unit fir = null
endglobals
private struct Data
unit cast
unit emp
integer lvl
location loc
timer tim
integer ticks
real change
real scale
static method create takes unit cast returns Data
local Data d = Data.allocate()
set d.cast = cast
set d.lvl = GetUnitAbilityLevel(d.cast, AID_WEX)
set d.loc = GetSpellTargetLoc()
set d.emp = CreateUnitAtLoc(GetOwningPlayer(cast), UID_EMP, d.loc, GetRandomReal(0., 359.))
set d.tim = NewTimer()
set d.ticks = R2I(DELAY(d.lvl) / PERIOD)
set d.change = (MAXIMUM_SCALING(d.lvl) - STARTING_SCALING(d.lvl)) / d.ticks
set d.scale = STARTING_SCALING(d.lvl)
call SetUnitScale(d.emp, d.scale, d.scale, d.scale)
call SetUnitTimeScale(d.emp, BALL_ANIMATION_SPEED(d.lvl))
//call UnitApplyTimedLife(d.emp, 'BTLF', DELAY(d.lvl))
call SetTimerData(d.tim, d)
return d
endmethod
method onDestroy takes nothing returns nothing
call RemoveLocation(.loc)
call ReleaseTimer(.tim)
endmethod
endstruct
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == AID_EMP
endfunction
private function GetEnemies takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(fir)) and GetUnitState(GetFilterUnit(), UNIT_STATE_MANA) > 0. and IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) == false
endfunction
private function Callback takes nothing returns nothing
local timer tim = GetExpiredTimer()
local Data d = GetTimerData(tim)
local unit blast
set d.scale = d.scale + d.change
call SetUnitScale(d.emp, d.scale, d.scale, d.scale)
set d.ticks = d.ticks - 1
if d.ticks <= 0 then
call RemoveUnit(d.emp) // Please don't bug. <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" class="smilie smilie--sprite smilie--sprite1" alt=":)" title="Smile :)" loading="lazy" data-shortname=":)" />
set blast = CreateUnitAtLoc(GetOwningPlayer(d.cast), UID_EMP_BLAST, d.loc, GetRandomReal(0., 359.))
call SetUnitTimeScale(blast, BLAST_ANIMATION_SPEED(d.lvl))
call UnitApplyTimedLife(blast, 039;BTLF039;, BLAST_DURATION(d.lvl))
set blast = null
set fir = d.cast
call GroupEnumUnitsInRangeOfLoc(gr, d.loc, AREA_OF_EFFECT(d.lvl), Condition(function GetEnemies))
loop
set fir = FirstOfGroup(gr)
exitwhen fir == null
if GetWidgetLife(fir) > DAMAGE(d.lvl) then
// It should "damage" through Tornado and other spells.
call SetWidgetLife(fir, GetWidgetLife(fir) - DAMAGE(d.lvl))
else
call UnitDamageTarget(d.cast, fir, DAMAGE(d.lvl), true, true, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
endif
call SetUnitState(fir, UNIT_STATE_MANA, GetUnitState(fir, UNIT_STATE_MANA) - MANA_DRAINED(d.lvl))
call GroupRemoveUnit(gr, fir)
endloop
call d.destroy()
endif
set tim = null
endfunction
private function Actions takes nothing returns nothing
local Data d = Data.create(GetTriggerUnit())
call TimerStart(d.tim, PERIOD, true, function Callback)
endfunction
private function Init takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trig, Condition(function Conditions))
call TriggerAddAction(trig, function Actions)
endfunction
endscope
Sun Strike: (see the wiki link)
Screenshot: http://i39.tinypic.com/14aydk7.jpg
JASS:
scope SunStrike initializer Init
// Requires TimerUtils, InvokerConfig.
//===============================================================================
// C O N F I G U R A T I O N M E N U
//===============================================================================
globals
// Attack type of the damaging.
private constant attacktype ATTACK_TYPE = ATTACK_TYPE_MAGIC
// Damage type of the damaging.
private constant damagetype DAMAGE_TYPE = DAMAGE_TYPE_MAGIC
// Weapon type of the damaging.
private constant weapontype WEAPON_TYPE = WEAPON_TYPE_WHOKNOWS
// Special effect created at the targeted location.
private constant string SFX_ONE = "Abilities\\Spells\\Other\\Doom\\DoomDeath.mdl"
endglobals
// Time to wait before Sun Strike damages the targeted area.
private constant function DELAY takes integer level returns real
return 1.7
endfunction
// Damage dealt in the area (which is spread amongst affected foes).
private constant function DAMAGE takes integer level returns real
return 12.5 + (level * 62.5)
endfunction
// Area of effect of the damaging.
private constant function AREA_OF_EFFECT takes integer level returns real
return 200.
endfunction
//===============================================================================
// E N D O F C O N F I G U R A T I O N M E N U
//===============================================================================
globals
// Group used for enumerations.
private group gr = CreateGroup()
// Unit used for FirstOfGroup() and global passing of the caster for the filter.
private unit fir = null
endglobals
private struct Data
unit cast
location loc
timer tim
integer lvl
static method create takes unit cast returns Data
local Data d = Data.allocate()
set d.cast = cast
set d.loc = GetSpellTargetLoc()
set d.tim = NewTimer()
set d.lvl = GetUnitAbilityLevel(d.cast, AID_EXORT)
call SetTimerData(d.tim, d)
return d
endmethod
method onDestroy takes nothing returns nothing
call ReleaseTimer(.tim)
call RemoveLocation(.loc)
endmethod
endstruct
private function Conditions takes nothing returns boolean
return GetSpellAbilityId() == AID_SUN_STRIKE
endfunction
private function GetEnemies takes nothing returns boolean
return IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(fir)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_DEAD) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) == false and IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) == false
endfunction
private function Callback takes nothing returns nothing
local timer tim = GetExpiredTimer()
local Data d = GetTimerData(tim)
local integer temp
call GroupEnumUnitsInRangeOfLoc(gr, d.loc, AREA_OF_EFFECT(d.lvl), Condition(function GetEnemies))
set temp = CountUnitsInGroup(gr)
if temp > 0 then
loop
set fir = FirstOfGroup(gr)
exitwhen fir == null
call UnitDamageTarget(d.cast, fir, DAMAGE(d.lvl) / temp, true, true, ATTACK_TYPE, DAMAGE_TYPE, WEAPON_TYPE)
call GroupRemoveUnit(gr, fir)
endloop
endif
call DestroyEffect(AddSpecialEffectLoc(SFX_ONE, d.loc))
call d.destroy()
set tim = null
endfunction
private function Actions takes nothing returns nothing
local Data d = Data.create(GetTriggerUnit())
call TimerStart(d.tim, DELAY(d.lvl), false, function Callback)
endfunction
private function Init takes nothing returns nothing
local trigger trig = CreateTrigger()
call TriggerRegisterAnyUnitEventBJ(trig, EVENT_PLAYER_UNIT_SPELL_EFFECT)
call TriggerAddCondition(trig, Condition(function Conditions))
call TriggerAddAction(trig, function Actions)
call Preload(SFX_ONE)
endfunction
endscope
(Continues bellow...)