Tutorial Triggered Custom Spell Tutorial

Reaction score
456
Triggered Custom Spell

This is my first tutorial so say if something is missing.
I did this for the people who don't know how to make triggered abilities work of course. You should know few things about triggering before doing this.

1.
First of all, create new map, size of 32x32. It should be big enough for this spell. This spell is going to be a "nova" like spell, so it needs space.

Now, go to object editor, to the Units category.
Make here the hero who casts the ability.
I created new custom unit from paladin and deleted his abilities.

2.
After that, go to Abilities category and make new custom ability from Fan of Knives. Now we need to remove missile art and effect from it. Then set damage per target and maximum total damage to 0.

I did some other changes to it that you don't need to do.

3.
Now, go to trigger editor and create new category and new trigger. Then make variables called:

Name - Type
Nova_Caster = Unit
Nova_Dummy = Unit (array 12)
Nova_Group = Unit Group
Nova_Point = Point
Nova_Angle = Real
Nova_Distance = Real
Nova_Around = Real (array 12)



After that we are going to start the triggering!
First we need event that responds to our need :D :
Code:
Events
   Unit - Unit Starts the effect of an ability
Without this condition it does the actions when you cast any spell. Make sure that you put your ability to the condition!
Code:
Conditions
   (Ability being cast) Equal to Lighning Nova
When this is done we have to do actions.
First action is wait, without it the caster wouldn't cast the ability to the end and it would do it again and again...
Here is the trigger where is the wait action and few variables:
Code:
Actions
   Wait 0.20 seconds
   Set Nova_Caster = (Triggering unit)
   Set Nova_Point = (Position of Nova_Caster)
   Set Nova_Angle = 0.00
   Set Nova_Distance = 0.00
4.
Hold it! Back to object editor, to the units category! Are you going to do the nova without dummy unit? If you don't know what are dummy units I won't tell that in this tutorial. However, we are going to make one.
Now, create new unit based of a Footman and name it to Dummy Ball.
Remove all the abilites of our new dummy and add there abilities called:Invulnerable (Neutral) and Locust.

We use locust because we don't want to have dummy that you can select or dummy that stop going when wall comes to its way.

Changes in dummy:
Art - Model File = Chain Lighning <Missile.
Art - Shadow Image (Unit) = None.
Combat - Attacks Enabled = None.
Movement - Speed Base = 522
Movement - Type = Fly
Pathing - Collision Size = 0
Stats - Food Cost = 0
Stats - Sight Radius (Day) = 100
Stats - Sight Radius (Night) = 100

5.
Now the Dummy Ball should be ready for use. So, back to the trigger Editor.
Let's begin our trigger.
Now we use my style of creating dummies to the game (We use loop :p).
Code:
Actions
   Wait 0.20 seconds
   Set Nova_Caster = (Casting unit)
   Set Nova_Point = (Position of Nova_Caster)
   Set Nova_Angle = 0.00
   Set Nova_Distance = 0.00
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
           Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
There you see, it creates 12 balls to the point. But now we have to move the units to their own places. Just wait and read.
Code:
Actions
   Wait 0.20 seconds
   Set Nova_Caster = (Casting unit)
   Set Nova_Point = (Position of Nova_Caster)
   Set Nova_Angle = 0.00
   Set Nova_Distance = 0.00
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
           Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
           Set Nova_Dummy[(Integer A)] = (Last created unit)
           Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
           Set Nova_Angle = (Nova_Angle + 30.00)
There you see, it moves the Dummies to their points (from 0 to 360)
360/12 = 30 and we have 12 dummies created, so now they are there "systematically". Lets continue.
Code:
Actions
   Wait 0.20 seconds
   Set Nova_Caster = (Casting unit)
   Set Nova_Point = (Position of Nova_Caster)
   Set Nova_Angle = 0.00
   Set Nova_Distance = 0.00
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
           Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
           Set Nova_Dummy[(Integer A)] = (Last created unit)
           Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
           Set Nova_Angle = (Nova_Angle + 30.00)
   Unit - Pause Nova_Caster
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
          Set Variable Nova_Around[(Integer A)] = (Angle from (Position of Nova_Caster) to (Position of Nova_Dummy[(Integer A)]))
   Wait for 0.20 seconds
   Unit - Unpause Nova_Caster
Now it sets variable Nova_Around to different for all arrays. We need that variable when we are making Dummy Balls to move. Now we have to stop making this trigger for a while.

6.
Now we are making the balls to move so, create new trigger. And lets start from the event of course. Turn the Initially off for this trigger.
Code:
Events
   Time - Every 0.01 seconds of game time
We are going to make the Dummy Balls to move every 0.01 second.
No conditions are needed for this trigger.
So, we can go to the actions right away:
Code:
Actions
    For each (Integer A) from 1 to 12, do (Actions)
        Loop - Actions
            Unit - Move Nova_Dummy[(Integer A)] instantly to (Nova_Point offset by Nova_Distance towards Nova_Around[(Integer A)] degrees
            Set Nova_Distance = (Nova_Distance + 0.10)
            Set Nova_Around[(Integer A)] =  (Nova_Around[(Integer A)] + 1.00)
7.
Okay, so now it moves unit away from the Nova_Point and it makes them move around it too.
That trigger is ready, but it doesn't go when you test? Of course not! Initially is off, so what we'll do now is open the first trigger. Okay.. The last thing we made to this trigger was the unpausing caster? Lets continue it:
Code:
Actions
   Wait 0.20 seconds
   Set Nova_Caster = (Casting unit)
   Set Nova_Point = (Position of Nova_Caster)
   Set Nova_Angle = 0.00
   Set Nova_Distance = 0.00
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
           Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
           Set Nova_Dummy[(Integer A)] = (Last created unit)
           Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
           Set Nova_Angle = (Nova_Angle + 30.00)
   Unit - Pause Nova_Caster
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
          Set Variable Nova_Around[(Integer A)] = (Angle from (Position of Nova_Caster) to (Position of Nova_Dummy[(Integer A)]))
   Wait for 0.20 seconds
   Unit - Unpause Nova_Caster
   Trigger - Turn on "The trigger that you made a while ago" <gen>
   Wait for 6.00 seconds
   Trigger - Turn off "The trigger that you made a while ago" <gen>
   For each (Integer A) from 1 to 12, do (Actions)
      Loop - Actions
         Unit - Kill Nova_Dummy[(Integer A)]
Hold it again! That loop kills every Nova_Dummy [Every array from 1 to 12. But, something isn't right here... Oh! Memory leaks? Say idiot if im not right please! I'll show you all what I have in my pocket! Lets continue this:
Code:
Actions
   Wait 0.20 seconds
   Set Nova_Caster = (Casting unit)
   Set Nova_Point = (Position of Nova_Caster)
   Set Nova_Angle = 0.00
   Set Nova_Distance = 0.00
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
           Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
           Set Nova_Dummy[(Integer A)] = (Last created unit)
           Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
           Set Nova_Angle = (Nova_Angle + 30.00)
   Unit - Pause Nova_Caster
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
          Set Variable Nova_Around[(Integer A)] = (Angle from (Position of Nova_Caster) to (Position of Nova_Dummy[(Integer A)]))
   Wait for 0.20 seconds
   Unit - Unpause Nova_Caster
   Trigger - Turn on "The trigger that you made a while ago" <gen>
   Wait for 6.00 seconds
   Trigger - Turn off "The trigger that you made a while ago" <gen>
   For each (Integer A) from 1 to 12, do (Actions)
      Loop - Actions
         Unit - Kill Nova_Dummy[(Integer A)]
   Custom script:  call RemoveLocation (udg_Nova_Point)
   Set Nova_Distance = 0.00
   Set Nova_Angle = 0.00
   Set Nova_Caster = No unit

8.
This have been too easy... Something is missing again, I thought that it was a perfect spell with all those long codes and things. What we have to do now is damaging? So, make new trigger again. Initially off for this trigger too.
Event for this trigger is:
Code:
Events
   Time - Every 0.05 seconds of game time
We are making it to damage the enemy units every 0.05 seconds of game time.
In this trigger there are not conditions yet. Im not so sure about custom script that is waiting us in future, but say if Im not right. We use loop again to pick nearby enemy units.
Code:
For each (Integer A) from 1 to12, do (Actions)
   Loop - Actions
This is the part where Im not sure what I do, but lets continue:
Code:
For each (Integer A) from 1 to 12, do (Actions)
   Loop - Actions
      Custom script   set bj_wantDestroyGroup = true
      Unit Group - Pick every unit in (Units within 50.00 of (Position of Nova_Dummy[(Integer A)])) and do (Actions)
We used loop because of this... There is 12 dummies so we have to pick every nearby units of them. Continue:
Code:
For each (Integer A) from 1 to 12, do (Actions)
   Loop - Actions
      Custom script   set bj_wantDestroyGroup = true
      Unit Group - Pick every unit in (Units within 50.00 of (Position of Nova_Dummy[(Integer A)])) and do (Actions)
          Loop - Actions
             Set Nova_Group = (Last created unit group)
             If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                If - Conditions
                    ((Picked unit) Magic Immune) Equal to False
                    ((Picked unit) belongs to an ally of (Owner of Nova_Caster)) Equal to False
Okay.. So there it checks if the unit is ally of the caster or if it is magic immune. If it is either of them, then actions won't affect to them. Continue again:
Code:
For each (Integer A) from 1 to 12, do (Actions)
   Loop - Actions
      Custom script   set bj_wantDestroyGroup = true
      Unit Group - Pick every unit in (Units within 50.00 of (Position of Nova_Dummy[(Integer A)])) and do (Actions)
          Loop - Actions
             Set Nova_Group = (Last created unit group)
             If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                If - Conditions
                   ((Picked unit) Magic Immune) Equal to False
                   ((Picked unit) belongs to an ally of (Owner of Nova_Caster)) Equal to False
                Then - Actions
                   Unit - Cause Nova_Caster to damage (Picked unit), dealing ((Real((Level of Lighning Nova for Nova_Caster))) x (Nova_Distance / 20.00)) damage of attack type Spells and damage type Normal
                Else - Actions
                   Do Nothing
That trigger is ready, now it damages all enemy units that aren't magic immunes. That damage thing is kinda simple, distance is about 600 at the end of the ability.

Level 1: 1 x (Nova_Distance / 20.00) = 30
Level 2: 2 x (Nova_Distance / 20.00) = 60
Level 3: 3 x (Nova_Distance / 20.00) = 90


The damage depends on the distance of the balls from the Nova_Point to the Dummy Balls. Now it's ready and we can go to the first trigger again.

9.
Now we have to turn on the trigger that we made and destroy group of course.
Code:
  Wait 0.20 seconds
   Set Nova_Caster = (Casting unit)
   Set Nova_Point = (Position of Nova_Caster)
   Set Nova_Angle = 0.00
   Set Nova_Distance = 0.00
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
           Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing Nova_Point
           Set Nova_Dummy[(Integer A)] = (Last created unit)
           Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
           Set Nova_Angle = (Nova_Angle + 30.00)
   Unit - Pause Nova_Caster
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
          Set Variable Nova_Around[(Integer A)] = (Angle from (Position of Nova_Caster) to (Position of Nova_Dummy[(Integer A)]))
   Wait for 0.20 seconds
   Unit - Unpause Nova_Caster
   Trigger - Turn on "The trigger that you made a while ago" <gen>
   Trigger - Turn on "The trigger that we just made" <gen>
   Wait for 6.00 seconds
   Trigger - Turn off "The trigger that you made a while ago" <gen>
   Trigger - Turn off "The trigger that we just made" <gen>
   For each (Integer A) from 1 to 12, do (Actions)
      Loop - Actions
         Unit - Kill Nova_Dummy[(Integer A)]
   Custom script:  call RemoveLocation (udg_Nova_Point)
   Custom script:  call DestroyGroup (udg_Nova_Group)
   Set Nova_Distance = 0.00
   Set Nova_Angle = 0.00
   Set Nova_Caster = No unit
Finish!

Now test it and tell me if something went wrong? Few pics from it and example map: (Comment)






Triggered Custom Spell Tutorial
 

Prometheus

Everything is mutable; nothing is sacred
Reaction score
589
Here are leaks I found
1.
Code:
Actions
   Wait 0.20 seconds
   Set Nova_Caster = (Casting unit)
   Set Nova_Point = (Position of Nova_Caster)
   Set Nova_Angle = 0.00
   Set Nova_Distance = 0.00
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
           Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing ([B]Position of (Triggering unit)[/B])
change bolded part to Nova_Point
2.
Code:
Actions
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
           Unit - Create 1 Dummy Ball for (Owner of Nova_Caster) at Nova_Point facing ([B]Position of (Triggering unit)[/B])
           Set Nova_Dummy[(Integer A)] = (Last created unit)
           Unit - Move Nova_Dummy[(Integer A)] to (Nova_Point offset by 20.00 towards Nova_Angle degrees)
           Set Nova_Angle = (Nova_Angle + 30.00)
once again change bolded part to Nova_Point
3.
Code:
Actions
 [B]- For each (Integer A) from 1 to 12, do (Actions)[/B]
   Unit - Pause Nova_Caster
   For each (Integer A) from 1 to 12, do (Actions)
       Loop - Actions
          Set Variable Nova_Around[(Integer A)] = (Angle from (Position of Nova_Caster) to (Position of Nova_Dummy[(Integer A)]))
   Wait for 0.20 seconds
   Unit - Unpause Nova_Caster

Bolded part is useless code

Overall It was good though ^^
 
Reaction score
456
Yah yah.. Some mistakes and typos :D ... It's not finished yet you know? Here we go again. Now Im gonna do the damaging part...
 
Reaction score
456
I made some major changes to it. And Im from Finland so my English isn't the best :D
 

Prometheus

Everything is mutable; nothing is sacred
Reaction score
589
Chocobo said:
Instead of (casting unit) write (Triggering unit)
This is not suggested, only if you have no idea what the right one is then use this.
 
Reaction score
456
So? Would be better to use triggering unit always instead of casting unit or something?
 

Daelin

Kelani Mage
Reaction score
172
Chocobo said:
(Triggering unit) stands until the trigger end whereas (Casting unit) doesn't.

U sure about that? I also thought to think like this but now I'm not that sure... Anyway, Triggering Unit is faster than Casting Unit. Was tested by Vexorian!

~Daelin
 
Reaction score
456
Thanks :D ! That damage trigger could be better, but the balls are so fast... :rolleyes:
 

Zakyath

Member
Reaction score
238
Since Fan of Knives doesn't do anything really, wouldn't it be good to base it of channel to show people the possibilities of that skill? :p Correct me if I'm wrong...
 
Reaction score
456
You're not wrong, but im doing more complicated spells based off channel :)
And; if there are 2 spells based of channel you can't use them very good. The caster starts cast both of them ;)
 
Reaction score
456
Oh.. Hmm.. You're right :eek: Shit.. How can this be!? I was perfect! :banghead:
 
Reaction score
456
Bump :rolleyes: Please tell if there are any mistakes or something.. And is this in even in right place?
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top