• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[General] Help me to Fix my Code for my Spear Trigger

Level 8
Joined
Oct 6, 2022
Messages
190
Hello, i'm making a spear skill, the base ability is the Stampede. what i would like to do is to make this spear is when an enemy got hit by it while the spear is moving, the enemy will get stun & knockback by the spear. but i don't know how would i do it here, can you guys able to help me with this one?


Hero's object editor:
1748216955800.png

Skill time channel cast:
1748217814147.png

Spear Trigger:

>>Initially On
  • Remilia_SEN
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to []Remilia[] Impaling Spear
    • Actions
      • Set Remilia_Cast_Unit[6] = (Triggering unit)
      • Set Remilia_SEN_IsCasted[1] = False
      • Set Remilia_SEN_IsCasted[2] = True
      • Set Remilia_SEN_Countdown = 2.90
      • Set Remilia_SEN_Point[2] = (Target point of ability being cast)
      • Set Remilia_SEN_angle = (Angle from (Position of Remilia_Cast_Unit[6]) to Remilia_SEN_Point[2])
      • Set Remilia_SEN_Speed = 100.00
      • Set Remilia_SEN_Distance = 0.00
      • Set Remilia_SEN_MaxDistance = 900.00
      • Set Remilia_KnockDuration = 0.00
      • Wait 0.01 seconds
      • Unit - Add (Fujiwara) DMG block to Remilia_Cast_Unit[6]
      • Unit - For Remilia_Cast_Unit[6], Ability (Fujiwara) DMG block , Disable ability: False, Hide UI: True
      • Animation - Play Remilia_Cast_Unit[6]'s attack animation
      • Animation - Queue Remilia_Cast_Unit[6]'s stand animation
      • Trigger - Turn on Remilia_SENCountdown <gen>
  • Remilia_SEN Cancel
    • Events
      • Unit - A unit Stops casting an ability
    • Conditions
      • (Ability being cast) Equal to []Remilia[] Impaling Spear
    • Actions
      • Set Remilia_SEN_IsCasted[1] = False
      • Set Remilia_SEN_IsCasted[2] = False

>>Initially off
  • Remilia_SENCountdown
    • Events
      • Time - Every 0.02 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Remilia_SEN_IsCasted[1] Equal to False
          • Remilia_SEN_IsCasted[2] Equal to True
        • Then - Actions
          • Set Remilia_SEN_Countdown = (Remilia_SEN_Countdown - 0.10)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Remilia_SEN_Countdown Equal to 0.00
            • Then - Actions
              • Set Remilia_SEN_IsCasted[1] = True
              • Set Remilia_SEN_IsCasted[2] = True
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Remilia_SEN_IsCasted[1] Equal to True
                  • Remilia_SEN_IsCasted[2] Equal to True
                • Then - Actions
                  • Unit - Remove (Fujiwara) DMG block from Remilia_Cast_Unit[6]
                  • Unit - Remove [][]Fuji[][] DMGblock buff from Remilia_Cast_Unit[6]
                  • Set Remilia_SEN_OriginPoint = ((Position of Remilia_Cast_Unit[6]) offset by 50.00 towards ((Facing of Remilia_Cast_Unit[6]) + 0.00) degrees)
                  • Unit - Create 1 Remilia Spear Dummy for (Owner of Remilia_Cast_Unit[6]) at Remilia_SEN_OriginPoint facing (Facing of Remilia_Cast_Unit[6]) degrees
                  • Animation - Play (Last created unit)'s death animation
                  • Set Remilia_SEN_Dummy2[2] = (Last created unit)
                  • Trigger - Turn on Remilia_SENReleased Loop <gen>
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Remilia_SEN_IsCasted[1] Equal to False
              • Remilia_SEN_IsCasted[2] Equal to False
            • Then - Actions
              • Trigger - Turn off (This trigger)
            • Else - Actions
  • Remilia_SENReleased Loop
    • Events
      • Time - Every 0.04 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Remilia_SEN_Distance Less than or equal to Remilia_SEN_MaxDistance
        • Then - Actions
          • For each (Integer A) from 1 to 2, do (Actions)
            • Loop - Actions
              • Unit - Move Remilia_SEN_Dummy2[(Integer A)] instantly to ((Position of Remilia_SEN_Dummy2[(Integer A)]) offset by Remilia_SEN_Speed towards Remilia_SEN_angle degrees), facing Remilia_SEN_angle degrees
              • Animation - Play Remilia_SEN_Dummy2[(Integer A)]'s stand animation
              • Unit Group - Pick every unit in (Units within 200.00 of (Position of Remilia_SEN_Dummy2[(Integer A)]) matching ((((Matching unit) belongs to an enemy of (Owner of Remilia_Cast_Unit[6])) Equal to True) and (((((Matching unit) is A structure) Equal to False) and (((Matching unit) is alive) Eq and do (Actions)
                • Loop - Actions
                  • Unit - Cause Remilia_SEN_Dummy2[(Integer A)] to damage (Picked unit), dealing (100.00 x (Real((Level of []Remilia[] Impaling Spear for Remilia_Cast_Unit[6])))) damage of attack type Spells and damage type Normal
                  • Unit - Order (Picked unit) to Stop
                  • Special Effect - Create a special effect at (Position of (Picked unit)) using war3mapImported\Dota_Effect_lina_longpozhan.mdx
                  • Special Effect - Set Scale of (Last created special effect) to 0.50
                  • Special Effect - Destroy (Last created special effect)
                  • Trigger - Turn on Remilia_SEN Knock Loop <gen>
          • Set Remilia_SEN_Distance = (Remilia_SEN_Distance + Remilia_SEN_Speed)
        • Else - Actions
          • Trigger - Turn off (This trigger)
          • For each (Integer A) from 1 to 2, do (Actions)
            • Loop - Actions
              • Unit - Remove Remilia_SEN_Dummy2[(Integer A)] from the game
              • Special Effect - Create a special effect at (Position of Remilia_SEN_Dummy2[(Integer A)]) using war3mapImported\Dota_Effect_lina_longpozhan.mdx
              • Special Effect - Set Scale of (Last created special effect) to 0.50
              • Special Effect - Destroy (Last created special effect)
              • Set Remilia_SEN_Dummy2[(Integer A)] = No unit
  • Remilia_SEN Knock Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • And - All (Conditions) are true
            • Conditions
              • Remilia_KnockDuration Less than or equal to 1.00
        • Then - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
            • Then - Actions
              • Special Effect - Create a special effect at (Position of (Picked unit)) using Abilities\Spells\Other\Doom\DoomTarget.mdl
              • Special Effect - Destroy (Last created special effect)
            • Else - Actions
          • Special Effect - Create a special effect at (Position of (Picked unit)) using Abilities\Spells\Items\AIfb\AIfbSpecialArt.mdl
          • Special Effect - Destroy (Last created special effect)
          • Unit - Move (Picked unit) instantly to ((Position of (Picked unit)) offset by 10.00 towards (Distance between (Position of Remilia_SEN_Dummy2[(Integer A)]) and (Position of (Picked unit))) degrees)
          • Set Remilia_KnockDuration = (Remilia_KnockDuration + 0.05)
        • Else - Actions
          • Unit - Remove Remilia_SEN_Dummy2[(Integer A)] from the game
          • Trigger - Turn off (This trigger)
 
Level 13
Joined
Nov 13, 2010
Messages
282
in your trigger Loop you are already picking up enemy units when the spear moves and hits something so to make sure you (stunned and knockback) correctly then try add the unit to a unit group
try something like Unit Group - Add (Picked unit) to Remilia_Hit_UnitGroup

for the stun you need a dummy to stun so try something like
Unit - Create 1 Dummy Caster for (Owner of Remilia_Cast_Unit[6]) at (Position of (Picked unit)) facing any angle
Unit - Add Storm Bolt to (Last created unit)
Unit - Order (Last created unit) to Human Mountain King - Storm Bolt (Picked unit)
Unit - Add a 1.00 second expiration timer to (Last created unit)

and then we come to Knockback i can see in your trigger you are trying to move (Picked unit)
but outside the picking loop (Picked unit) it becomes invalid so
instead you should store hit units in a list or array so you can reference the unit
you can do something like
Set TempPoint = (Position of Remilia_KnockTarget[what you use])
Set Knock_Angle = (Angle from (Position of Remilia_SEN_Dummy2[1]) to tempPoint)
Set New_Position = TempPoint offset by 25.00 towards Knock_Angle degrees
Unit - Move Remilia_KnockTarget[what you use] to New_Position
You can run this over a duration that is controlled by Remilia_KnockDuration
and you can increase the offset per tick for smoother knockback if you like
 
Level 8
Joined
Oct 6, 2022
Messages
190
in your trigger Loop you are already picking up enemy units when the spear moves and hits something so to make sure you (stunned and knockback) correctly then try add the unit to a unit group
try something like Unit Group - Add (Picked unit) to Remilia_Hit_UnitGroup

for the stun you need a dummy to stun so try something like
Unit - Create 1 Dummy Caster for (Owner of Remilia_Cast_Unit[6]) at (Position of (Picked unit)) facing any angle
Unit - Add Storm Bolt to (Last created unit)
Unit - Order (Last created unit) to Human Mountain King - Storm Bolt (Picked unit)
Unit - Add a 1.00 second expiration timer to (Last created unit)

and then we come to Knockback i can see in your trigger you are trying to move (Picked unit)
but outside the picking loop (Picked unit) it becomes invalid so
instead you should store hit units in a list or array so you can reference the unit
you can do something like
Set TempPoint = (Position of Remilia_KnockTarget[what you use])
Set Knock_Angle = (Angle from (Position of Remilia_SEN_Dummy2[1]) to tempPoint)
Set New_Position = TempPoint offset by 25.00 towards Knock_Angle degrees
Unit - Move Remilia_KnockTarget[what you use] to New_Position
You can run this over a duration that is controlled by Remilia_KnockDuration
and you can increase the offset per tick for smoother knockback if you like
Hello, Thank you for helping me out. may i know what is this "what you use" in "Remilia_KnockTarget[what you use]"?
 
Level 13
Joined
Nov 13, 2010
Messages
282
Add to you knockback list (Remilia_KnockTarget) ad the start of knock loop
and is a unit array .... so for this we to count units ass well
so in your Remilia_SENReleased Loop we set
Remilia_KnockTarget[1] = Unit A
Remilia_KnockTarget[2] = Unit B etc etc etc is how you store them is when the spear hits enemies
we also set this 2 .... -> KnockTarget is unit array and KnockCount is integer
Set Remilia_KnockCount = Remilia_KnockCount + 1
Set Remilia_KnockTarget[Remilia_KnockCount] = (Picked unit)

and in your knock loop set
For each (Integer i) from 1 to Remilia_KnockCount, do (Actions)
Loop - Actions
we Move the Remilia_KnockTarget toward the knockback direction
and
For each (Integer i) from 1 to Remilia_KnockCount, do (Actions)
Set TempUnit = Remilia_KnockTarget
we Move the TempUnit toward the spear direction

so let break it down
first Variables
Remilia_KnockTarget (unit Array) .. Remilia_KnockCount(Integer) .. Remilia_KnockDuration (Real) .. TempUnit (Unit) .. TempPoint (Point) ..
SpearPoint (Point) .. NewPoint. (Point) .. KnockbackAngle (Real)
then trigger Remilia_SEN Knock Loop


  • Remilia_SEN Knock Loop
    • Event
      • Time - Every 0.03 seconds of game time
    • Condition
      • (Remilia_KnockCount Greater than 0)
    • Action
      • Set Remilia_KnockDuration = (Remilia_KnockDuration + 0.03)
      • For each (Integer i) from 1 to Remilia_KnockCount, do (Actions)
        • Loop - Actions
          • Set TempUnit = Remilia_KnockTarget
          • Set TempPoint = (Position of TempUnit)
          • Set SpearPoint = (Position of Remilia_SEN_Dummy2[1]) or 2 depens if you are using both
          • Set KnockbackAngle = (Angle from SpearPoint to TempPoint)
          • Set NewPoint = TempPoint offset by 15.00 towards KnockbackAngle degrees
          • Unit - Move TempUnit instantly to NewPoint
          • Special Effect - Create a special effect at TempPoint using Abilities\Spells\Items\AIfb\AIfbSpecialArt.mdl or what ever you like here
          • Special Effect - Destroy (Last created special effect)
          • Custom script: call RemoveLocation(udg_TempPoint)
          • Custom script: call RemoveLocation(udg_SpearPoint)
          • Custom script: call RemoveLocation(udg_NewPoint)
        • If (Remilia_KnockDuration Greater than or equal to 0.45) then do (Actions)
          • Set Remilia_KnockCount = 0
          • Set Remilia_KnockDuration = 0.00
          • Trigger - Turn off (This trigger)
 
Last edited:

Rheiko

Spell Reviewer
Level 27
Joined
Aug 27, 2013
Messages
4,230
I hope you could elaborate more on the purpose of this spell. What does it do exactly? I can only guess from the code for now. So your goal is:
  • You want the caster to channel for X seconds
  • After channeling for X seconds, the spell will summon a spear?
  • The spear will then travel for X distance
  • Enemies that got hit by the spear will get a knockback effect for X duration?
Please correct me if I assume incorrectly.
This is quite an ambitious goal for a start, but I like the spirit!

Get ready for a wall of text!
Please read the trigger comments as well for a better understanding of things!

Configuration Trigger​

First, I prefer to keep every "configurables" in a separate trigger dedicated only to configuration-related things. I will call it "Impaling Spear Config" trigger. This trigger will only run once when the map is loaded, to do so we can use "Map Initialization" event.
  • Impaling Spear Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- - --------
      • -------- These values will remain the same throughout the spell --------
      • -------- We call these "constants" --------
      • -------- - --------
      • -------- Store the ability we use in object editor --------
      • -------- Variable Type: Ability --------
      • -------- - --------
      • Set ImpalingSpear_Ability = Impaling Spear
      • -------- - --------
      • -------- Store the dummy unit-type we use in object editor --------
      • -------- Variable Type: Unit-type --------
      • -------- - --------
      • Set ImpalingSpear_UnitType = Spear Dummy
      • -------- - --------
      • -------- Store the duration it takes to wait before the spear is launched --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Delay = 2.90
      • -------- - --------
      • -------- Store the maximum distance for the spear to travel --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_MaxDistance = 900.00
      • -------- - --------
      • -------- Store how fast the spear will travel --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Speed = 1000.00
      • -------- - --------
      • -------- Store the damage when the spear collides with enemies --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Damage = 100.00
      • -------- - --------
      • -------- Store how long the knockback duration should be --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_MaxKnockDuration = 1.00
      • -------- - --------
      • -------- Store the interval of the timer we will be using --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Interval = 0.03

Main Trigger​

Now, we can start with the trigger that actually runs when we cast the spell! You don't need to use array variables at all, let's keep it simple by using only normal variables so you don't have to worry about arrays! Also, do not use waits, as they are imprecise and tend to cause troubles along the way.

In order to do this, we will use the event "Unit - A unit Starts the effect of an ability" which runs right when the ability is casted.
The condition is "(Ability being cast) Equal to ImpalingSpear_Ability", which uses the variable we declared earlier in Impaling Spear Config trigger.
  • Impaling Spear
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to ImpalingSpear_Ability
    • Actions
      • -------- - --------
      • -------- There is no need to use array yet, do not worry about it! --------
      • -------- To store the caster, you can use either "triggering unit" or "casting unit" --------
      • -------- But for now, all you need to know is "triggering unit" is better and superior --------
      • -------- - --------
      • Set ImpalingSpear_Unit = (Triggering unit)
      • -------- - --------
      • -------- Now let's store the point where the caster is standing right now! --------
      • -------- Don't forget to use the variables you have previously declared! --------
      • -------- Using variables correctly allow your code to run with better performance --------
      • -------- - --------
      • Set ImpalingSpear_CastPoint = (Position of ImpalingSpear_Unit)
      • -------- - --------
      • -------- Now let's store the point that becomes the target of our spell --------
      • -------- - --------
      • Set ImpalingSpear_TargetPoint = (Target point of ability being cast)
      • -------- - --------
      • -------- Now, to get an angle between points, we need 2 points first --------
      • -------- which we have prepared earlier! they are ImpalingSpear_CastPoint and ImpalingSpear_TargetPoint --------
      • -------- that means we can use them right away and store the angle into a variable --------
      • -------- Again, don't forget to use the variables you have previously declared! --------
      • -------- - --------
      • Set ImpalingSpear_Angle = (Angle from ImpalingSpear_CastPoint to ImpalingSpear_TargetPoint)
      • -------- - --------
      • -------- Assign the delay value to delay counter variable --------
      • -------- We will use delay counter variable later in loop trigger to do the countdown logic --------
      • -------- Before throwing the spear --------
      • -------- This way, the actual "delay" variable from config trigger will remain the same no matter what --------
      • -------- - --------
      • Set ImpalingSpear_DelayCounter = ImpalingSpear_Delay
      • -------- - --------
      • -------- Let's initialize a boolean value with "false" --------
      • -------- This marks that the spear has not reached the stage to be thrown yet --------
      • -------- We will change this to true later when the spear is actually launched --------
      • -------- - --------
      • Set ImpalingSpear_TimeToLaunch = False
      • -------- - --------
      • -------- This will be used later in loop trigger to keep tracks of dummy unit's current distance --------
      • -------- So let's initialize it as 0 --------
      • -------- - --------
      • Set ImpalingSpear_CurrentDistance = 0.00
      • -------- - --------
      • -------- Everything is ready, you can do whatever you want here before we turn on the loop trigger --------
      • -------- If you want to add or hide ability or play unit animation --------
      • -------- You can do it here --------
      • -------- - --------
      • -------- < INSERT WHAT YOU WANT TO DO HERE > --------
      • -------- - --------
      • -------- Now that we are done, we can continue to the next trigger --------
      • -------- There are many ways to do a "loop" --------

What is Loop Trigger?​

A loop is basically a repeating code. For this context, we will be using a repeating timer as a loop. There are two ways to do it. You can do it just like how you did before, something like this:
  • Impaling Spear Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- Do your actions here --------
      • -------- When you're done, you can pause the timer like this --------
      • Trigger - Turn off (This trigger)
However, the downside is we cannot alter the value directly on the event so we cannot use our previously declared variable "ImpalingSpear_Interval". Luckily, there is a workaround for that, we can use "Trigger - Add New Event" function to the "Impaling Spear Loop" trigger. To set it up, we need to go back to our "Impaling Spear Config" and add another line of code just like this.
  • Impaling Spear Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- - --------
      • -------- These values will remain the same throughout the spell --------
      • -------- We call these "constants" --------
      • -------- - --------
      • -------- Store the ability we use in object editor --------
      • -------- Variable Type: Ability --------
      • -------- - --------
      • Set ImpalingSpear_Ability = Impaling Spear
      • -------- - --------
      • -------- Store the dummy unit-type we use in object editor --------
      • -------- Variable Type: Unit-type --------
      • -------- - --------
      • Set ImpalingSpear_UnitType = Spear Dummy
      • -------- - --------
      • -------- Store the duration it takes to wait before the spear is launched --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Delay = 2.90
      • -------- - --------
      • -------- Store the maximum distance for the spear to travel --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_MaxDistance = 900.00
      • -------- - --------
      • -------- Store how fast the spear will travel --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Speed = 1000.00
      • -------- - --------
      • -------- Store the damage when the spear collides with enemies --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Damage = 100.00
      • -------- - --------
      • -------- Store how long the knockback duration should be --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_MaxKnockDuration = 1.00
      • -------- - --------
      • -------- Store the interval of the timer we will be using --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Interval = 0.03
      • -------- - --------
      • -------- Add the event using our variable to our "Impaling Spear Loop" trigger --------
      • -------- - --------
      • Trigger - Add to Impaling Spear Loop <gen> the event (Time - Every ImpalingSpear_Interval seconds of game time)
We can leave our "Impaling Spear Loop" event empty just like this for now
  • Impaling Spear Loop
    • Events
    • Conditions
    • Actions
      • -------- Do your actions here --------
      • -------- When you're done, you can pause the timer like this --------
      • Trigger - Turn off (This trigger)
We can go back to our "Impaling Spear" trigger and add this at the end
  • Impaling Spear
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to ImpalingSpear_Ability
    • Actions
      • -------- - --------
      • -------- There is no need to use array yet, do not worry about it! --------
      • -------- To store the caster, you can use either "triggering unit" or "casting unit" --------
      • -------- But for now, all you need to know is "triggering unit" is better and superior --------
      • -------- - --------
      • Set ImpalingSpear_Unit = (Triggering unit)
      • -------- - --------
      • -------- Now let's store the point where the caster is standing right now! --------
      • -------- Don't forget to use the variables you have previously declared! --------
      • -------- Using variables correctly allow your code to run with better performance --------
      • -------- - --------
      • Set ImpalingSpear_CastPoint = (Position of ImpalingSpear_Unit)
      • -------- - --------
      • -------- Now let's store the point that becomes the target of our spell --------
      • -------- - --------
      • Set ImpalingSpear_TargetPoint = (Target point of ability being cast)
      • -------- - --------
      • -------- Now, to get an angle between points, we need 2 points first --------
      • -------- which we have prepared earlier! they are ImpalingSpear_CastPoint and ImpalingSpear_TargetPoint --------
      • -------- that means we can use them right away and store the angle into a variable --------
      • -------- Again, don't forget to use the variables you have previously declared! --------
      • -------- - --------
      • Set ImpalingSpear_Angle = (Angle from ImpalingSpear_CastPoint to ImpalingSpear_TargetPoint)
      • -------- - --------
      • -------- Assign the delay value to delay counter variable --------
      • -------- We will use delay counter variable later in loop trigger to do the countdown logic --------
      • -------- Before throwing the spear --------
      • -------- This way, the actual "delay" variable from config trigger will remain the same no matter what --------
      • -------- - --------
      • Set ImpalingSpear_DelayCounter = ImpalingSpear_Delay
      • -------- - --------
      • -------- Let's initialize a boolean value with "false" --------
      • -------- This marks that the spear has not reached the stage to be thrown yet --------
      • -------- We will change this to true later when the spear is actually launched --------
      • -------- - --------
      • Set ImpalingSpear_TimeToLaunch = False
      • -------- - --------
      • -------- This will be used later in loop trigger to keep tracks of dummy unit's current distance --------
      • -------- So let's initialize it as 0 --------
      • -------- - --------
      • Set ImpalingSpear_CurrentDistance = 0.00
      • -------- - --------
      • -------- Everything is ready, you can do whatever you want here before we turn on the loop trigger --------
      • -------- If you want to add or hide ability or play unit animation --------
      • -------- You can do it here --------
      • -------- - --------
      • -------- < INSERT WHAT YOU WANT TO DO HERE > --------
      • -------- - --------
      • Trigger - Turn on Impaling Spear Loop <gen>
Great! The loop will be activated when we cast the spell. That was the first method.
The second method, you will have to create a timer variable first, lets call it ImpalingSpear_Timer

  • Impaling Spear
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to ImpalingSpear_Ability
    • Actions
      • -------- - --------
      • -------- There is no need to use array yet, do not worry about it! --------
      • -------- To store the caster, you can use either "triggering unit" or "casting unit" --------
      • -------- But for now, all you need to know is "triggering unit" is better and superior --------
      • -------- - --------
      • Set ImpalingSpear_Unit = (Triggering unit)
      • -------- - --------
      • -------- Now let's store the point where the caster is standing right now! --------
      • -------- Don't forget to use the variables you have previously declared! --------
      • -------- Using variables correctly allow your code to run with better performance --------
      • -------- - --------
      • Set ImpalingSpear_CastPoint = (Position of ImpalingSpear_Unit)
      • -------- - --------
      • -------- Now let's store the point that becomes the target of our spell --------
      • -------- - --------
      • Set ImpalingSpear_TargetPoint = (Target point of ability being cast)
      • -------- - --------
      • -------- Now, to get an angle between points, we need 2 points first --------
      • -------- which we have prepared earlier! they are ImpalingSpear_CastPoint and ImpalingSpear_TargetPoint --------
      • -------- that means we can use them right away and store the angle into a variable --------
      • -------- Again, don't forget to use the variables you have previously declared! --------
      • -------- - --------
      • Set ImpalingSpear_Angle = (Angle from ImpalingSpear_CastPoint to ImpalingSpear_TargetPoint)
      • -------- - --------
      • -------- Assign the delay value to delay counter variable --------
      • -------- We will use delay counter variable later in loop trigger to do the countdown logic --------
      • -------- Before throwing the spear --------
      • -------- This way, the actual "delay" variable from config trigger will remain the same no matter what --------
      • -------- - --------
      • Set ImpalingSpear_DelayCounter = ImpalingSpear_Delay
      • -------- - --------
      • -------- Let's initialize a boolean value with "false" --------
      • -------- This marks that the spear has not reached the stage to be thrown yet --------
      • -------- We will change this to true later when the spear is actually launched --------
      • -------- - --------
      • Set ImpalingSpear_TimeToLaunch = False
      • -------- - --------
      • -------- This will be used later in loop trigger to keep tracks of dummy unit's current distance --------
      • -------- So let's initialize it as 0 --------
      • -------- - --------
      • Set ImpalingSpear_CurrentDistance = 0.00
      • -------- - --------
      • -------- Everything is ready, you can do whatever you want here before we turn on the loop trigger --------
      • -------- If you want to add or hide ability or play unit animation --------
      • -------- You can do it here --------
      • -------- - --------
      • -------- < INSERT WHAT YOU WANT TO DO HERE > --------
      • -------- - --------
      • -------- This will start the timer and repeat it every "ImpalingSpear_Interval" --------
      • Countdown Timer - Start ImpalingSpear_Timer as a Repeating timer that will expire in ImpalingSpear_Interval seconds
In the loop trigger, we need to use the event "Time - ImpalingSpear_Timer expires" and instead of turning off the trigger when we're done, we need to pause the timer using "Countdown Timer - Pause ImpalingSpear_Timer" like so

  • Impaling Spear Loop
    • Events
      • Time - ImpalingSpear_Timer expires
    • Conditions
    • Actions
      • -------- Do your actions here --------
      • -------- When you're done, you can pause the timer like this --------
      • Countdown Timer - Pause ImpalingSpear_Timer
We will use the first method, since you seem to be more familiar with that one.

Loop Trigger​

Now, we are ready to code the logic for the delay (preparing the spear before throwing it) and the movement of the spear after it is thrown. First, we need to check if the caster is still casting the spell. We want the spell to be cancelled if the caster is interrupted during the waiting phase.
  • Impaling Spear Loop
    • Events
    • Conditions
    • Actions
      • -------- - --------
      • -------- We check whether the caster is still casting the spell --------
      • -------- And the spear is not launched yet --------
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Current order of ImpalingSpear_Unit) Equal to (Order(stampede))
          • ImpalingSpear_TimeToLaunch Equal to False
        • Then - Actions
          • -------- - --------
          • -------- The caster is still casting it! That means we can do the countdown logic --------
          • -------- Let's substract "ImpalingSpear_Interval" from "ImpalingSpear_DelayCounter" --------
          • -------- - --------
          • Set ImpalingSpear_DelayCounter = (ImpalingSpear_DelayCounter - ImpalingSpear_Interval)
          • -------- - --------
          • -------- This will eventually reach 0 or below --------
          • -------- When it does, we want to create a dummy for the spear missile --------
          • -------- So let's check it first, if it's 0 or lower then --------
          • -------- - --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ImpalingSpear_DelayCounter Less than or equal to 0.00
            • Then - Actions
              • -------- - --------
              • -------- We create the dummy here --------
              • -------- Depending on where you want your dummy to spawn --------
              • -------- You might need another Point variable --------
              • -------- But to keep this simple, I will create the dummy at the Caster's position instead --------
              • -------- - --------
              • Unit - Create 1 Spear Dummy for (Owner of ImpalingSpear_Unit) at ImpalingSpear_CastPoint facing ImpalingSpear_Angle degrees
              • -------- - --------
              • -------- Now, we need to store this unit into a variable, so we can use the reference for later --------
              • -------- - --------
              • Set ImpalingSpear_Dummy = (Last created unit)
              • -------- - --------
              • -------- It is time to throw the spear! --------
              • -------- Let's change the boolean value --------
              • -------- - --------
              • Set ImpalingSpear_TimeToLaunch = True
              • -------- - --------
              • -------- Play our unit animation! --------
              • -------- - --------
              • Animation - Play ImpalingSpear_Unit's attack animation
            • Else - Actions
        • Else - Actions
          • -------- - --------
          • -------- The caster is interrupted --------
          • -------- The rest of this trigger will not run --------
          • -------- - --------
      • -------- - --------
      • -------- Let's check if it is time to launch --------
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ImpalingSpear_TimeToLaunch Equal to True
        • Then - Actions
          • -------- - --------
          • -------- Now, we must handle the movement of the spear --------
          • -------- To do so, we will update its location, bit by bit --------
          • -------- - --------
          • -------- This will store the current position of our dummy unit --------
          • -------- - --------
          • Set ImpalingSpear_DummyPoint = (Position of ImpalingSpear_Dummy)
          • -------- - --------
          • -------- This will store the next position where our dummy unit will go --------
          • -------- I'm using this formula to imitate how missiles from default abilities in object editor works --------
          • -------- Speed * Interval --------
          • -------- - --------
          • Set ImpalingSpear_DummyNextPoint = (ImpalingSpear_DummyPoint offset by (ImpalingSpear_Speed x ImpalingSpear_Interval) towards ImpalingSpear_Angle degrees)
          • -------- - --------
          • -------- Now, we can update the dummy's position --------
          • -------- - --------
          • Unit - Move ImpalingSpear_Dummy instantly to ImpalingSpear_DummyNextPoint
          • -------- - --------
          • -------- We must also update the distance that the dummy unit has gained --------
          • -------- - --------
          • Set ImpalingSpear_CurrentDistance = (ImpalingSpear_CurrentDistance + (ImpalingSpear_Speed x ImpalingSpear_Interval))
          • -------- - --------
          • -------- Let's deal damage to nearby enemy units --------
          • -------- - --------
          • Unit Group - Pick every unit in (Units within 200.00 of ImpalingSpear_DummyNextPoint) and do (Actions)
            • Loop - Actions
              • -------- - --------
              • -------- I recommend to use IF THEN ELSE for a better readability! --------
              • -------- We must check: --------
              • -------- * The unit is not a structure --------
              • -------- * The unit belongs to the caster's enemy --------
              • -------- * The unit is not dead --------
              • -------- * The unit is not in already damaged group --------
              • -------- - --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked unit) is A structure) Equal to False
                  • ((Picked unit) belongs to an enemy of (Owner of ImpalingSpear_Unit)) Equal to True
                  • ((Picked unit) is dead) Equal to False
                  • ((Picked unit) is in ImpalingSpear_AlreadyDamaged) Equal to False
                • Then - Actions
                  • -------- - --------
                  • -------- The unit fits our criteria! --------
                  • -------- Let's deal damage to them using our previously declared value --------
                  • -------- "ImpalingSpear_Damage" variable from Impaling Spear Config Trigger --------
                  • -------- - --------
                  • Unit - Cause ImpalingSpear_Unit to damage (Picked unit), dealing ImpalingSpear_Damage damage of attack type Spells and damage type Normal
                  • -------- - --------
                  • -------- The unit is damaged, let's mark it by inserting it into a unit group --------
                  • -------- This way, the enemy unit will only take the damage once --------
                  • -------- We can also use this group to do a knockback --------
                  • -------- - --------
                  • Unit Group - Add (Picked unit) to ImpalingSpear_AlreadyDamaged
                  • -------- - --------
                  • -------- You can create a special effect here if you wish --------
                  • -------- Destroy it right away as we no longer need it --------
                  • -------- - --------
                  • Special Effect - Create a special effect attached to the chest of (Picked unit) using Abilities\Spells\Other\Stampede\StampedeMissileDeath.mdl
                  • Special Effect - Destroy (Last created special effect)
                  • -------- - --------
                  • -------- Handling a knockback takes extra effort --------
                  • -------- You need to learn "Dynamic Indexing" or "Hashtable" first --------
                  • -------- If you want to make your own knockback system --------
                  • -------- - --------
                  • -------- Luckily for you, we have many Knockback System to choose from in Hiveworkshop --------
                  • -------- For this, I will use Bribe's knockback 2D --------
                  • -------- - --------
                  • -------- First store the position of the enemy unit --------
                  • -------- - --------
                  • Set ImpalingSpear_EnemyPoint = (Position of (Picked unit))
                  • -------- - --------
                  • -------- Then you need these four variables: --------
                  • -------- - --------
                  • Set Knockback2DAngle = (Angle from ImpalingSpear_DummyNextPoint to ImpalingSpear_EnemyPoint)
                  • Set Knockback2DDistance = 500.00
                  • Set Knockback2DTime = 1.00
                  • Set Knockback2DUnit = (Picked unit)
                  • -------- - --------
                  • -------- Then simply run the Knockback 2D trigger --------
                  • -------- - --------
                  • Trigger - Run Knockback 2D <gen> (checking conditions)
                  • -------- - --------
                  • -------- This does not stun them, so you have to create another dummy and order it to cast stun ability at these units --------
                  • -------- This will be an example: --------
                  • -------- - --------
                  • Unit - Create 1 StunDummy for (Owner of ImpalingSpear_Unit) at ImpalingSpear_EnemyPoint facing Default building facing degrees
                  • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
                  • Unit - Order (Last created unit) to Human Mountain King - Storm Bolt (Picked unit)
                  • -------- - --------
                  • -------- This will create a dummy that cast a storm bolt to stun --------
                  • -------- For every enemy unit --------
                  • -------- Which means, if you pick 10 enemies, you will create 10 dummies --------
                  • -------- Not very ideal, ideally you want only one dummy and order it again and again. --------
                  • -------- You can achieve that by creating the dummy for neutral passive at config trigger once --------
                  • -------- Then you can order that dummy to cast storm bolt here --------
                  • -------- - --------
                • Else - Actions
          • -------- - --------
          • -------- Let's check whether the dummy unit has reached maximum distance or not --------
          • -------- We can achieve this by comparing CurrentDistance to MaximumDistance --------
          • -------- - --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ImpalingSpear_CurrentDistance Greater than or equal to ImpalingSpear_MaxDistance
            • Then - Actions
              • -------- - --------
              • -------- It has reached the maximum distance --------
              • -------- Let's kill or remove the dummy unit --------
              • -------- - --------
              • Unit - Kill ImpalingSpear_Dummy
              • -------- - --------
              • -------- Don't forget to clear the "AlreadyDamaged" group, so it can be used again next time --------
              • -------- - --------
              • Unit Group - Remove all units from ImpalingSpear_AlreadyDamaged
              • -------- - --------
              • -------- This trigger is now finished, let's turn it back off --------
              • -------- - --------
              • Trigger - Turn off (This trigger)
            • Else - Actions
        • Else - Actions
Now, this works perfectly and aligns with the goal I assumed earlier. Hopefully, I assumed correctly, I spent time writing this, lol.
The final code should look like this:


  • Impaling Spear Config
    • Events
      • Map initialization
    • Conditions
    • Actions
      • -------- - --------
      • -------- These values will remain the same throughout the spell --------
      • -------- We call these "constants" --------
      • -------- - --------
      • -------- Store the ability we use in object editor --------
      • -------- Variable Type: Ability --------
      • -------- - --------
      • Set ImpalingSpear_Ability = Impaling Spear
      • -------- - --------
      • -------- Store the dummy unit-type we use in object editor --------
      • -------- Variable Type: Unit-type --------
      • -------- - --------
      • Set ImpalingSpear_UnitType = Spear Dummy
      • -------- - --------
      • -------- Store the duration it takes to wait before the spear is launched --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Delay = 2.90
      • -------- - --------
      • -------- Store the maximum distance for the spear to travel --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_MaxDistance = 900.00
      • -------- - --------
      • -------- Store how fast the spear will travel --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Speed = 1000.00
      • -------- - --------
      • -------- Store the damage when the spear collides with enemies --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Damage = 100.00
      • -------- - --------
      • -------- Store how long the knockback duration should be --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_MaxKnockDuration = 1.00
      • -------- - --------
      • -------- Store the interval of the timer we will be using --------
      • -------- Variable Type: Real --------
      • -------- - --------
      • Set ImpalingSpear_Interval = 0.03
      • -------- - --------
      • -------- Add the event using our variable to our "Impaling Spear Loop" trigger --------
      • -------- - --------
      • Trigger - Add to Impaling Spear Loop <gen> the event (Time - Every ImpalingSpear_Interval seconds of game time)


  • Impaling Spear
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to ImpalingSpear_Ability
    • Actions
      • -------- - --------
      • -------- There is no need to use array yet, do not worry about it! --------
      • -------- To store the caster, you can use either "triggering unit" or "casting unit" --------
      • -------- But for now, all you need to know is "triggering unit" is better and superior --------
      • -------- - --------
      • Set ImpalingSpear_Unit = (Triggering unit)
      • -------- - --------
      • -------- Now let's store the point where the caster is standing right now! --------
      • -------- Don't forget to use the variables you have previously declared! --------
      • -------- Using variables correctly allow your code to run with better performance --------
      • -------- - --------
      • Set ImpalingSpear_CastPoint = (Position of ImpalingSpear_Unit)
      • -------- - --------
      • -------- Now let's store the point that becomes the target of our spell --------
      • -------- - --------
      • Set ImpalingSpear_TargetPoint = (Target point of ability being cast)
      • -------- - --------
      • -------- Now, to get an angle between points, we need 2 points first --------
      • -------- which we have prepared earlier! they are ImpalingSpear_CastPoint and ImpalingSpear_TargetPoint --------
      • -------- that means we can use them right away and store the angle into a variable --------
      • -------- Again, don't forget to use the variables you have previously declared! --------
      • -------- - --------
      • Set ImpalingSpear_Angle = (Angle from ImpalingSpear_CastPoint to ImpalingSpear_TargetPoint)
      • -------- - --------
      • -------- Assign the delay value to delay counter variable --------
      • -------- We will use delay counter variable later in loop trigger to do the countdown logic --------
      • -------- Before throwing the spear --------
      • -------- This way, the actual "delay" variable from config trigger will remain the same no matter what --------
      • -------- - --------
      • Set ImpalingSpear_DelayCounter = ImpalingSpear_Delay
      • -------- - --------
      • -------- Let's initialize a boolean value with "false" --------
      • -------- This marks that the spear has not reached the stage to be thrown yet --------
      • -------- We will change this to true later when the spear is actually launched --------
      • -------- - --------
      • Set ImpalingSpear_TimeToLaunch = False
      • -------- - --------
      • -------- This will be used later in loop trigger to keep tracks of dummy unit's current distance --------
      • -------- So let's initialize it as 0 --------
      • -------- - --------
      • Set ImpalingSpear_CurrentDistance = 0.00
      • -------- - --------
      • -------- Everything is ready, you can do whatever you want here before we turn on the loop trigger --------
      • -------- If you want to add or hide ability or play unit animation --------
      • -------- You can do it here --------
      • -------- - --------
      • -------- < INSERT WHAT YOU WANT TO DO HERE > --------
      • -------- - --------
      • Trigger - Turn on Impaling Spear Loop <gen>


  • Impaling Spear Loop
    • Events
    • Conditions
    • Actions
      • -------- - --------
      • -------- We check whether the caster is still casting the spell --------
      • -------- And the spear is not launched yet --------
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Current order of ImpalingSpear_Unit) Equal to (Order(stampede))
          • ImpalingSpear_TimeToLaunch Equal to False
        • Then - Actions
          • -------- - --------
          • -------- The caster is still casting it! That means we can do the countdown logic --------
          • -------- Let's substract "ImpalingSpear_Interval" from "ImpalingSpear_DelayCounter" --------
          • -------- - --------
          • Set ImpalingSpear_DelayCounter = (ImpalingSpear_DelayCounter - ImpalingSpear_Interval)
          • -------- - --------
          • -------- This will eventually reach 0 or below --------
          • -------- When it does, we want to create a dummy for the spear missile --------
          • -------- So let's check it first, if it's 0 or lower then --------
          • -------- - --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ImpalingSpear_DelayCounter Less than or equal to 0.00
            • Then - Actions
              • -------- - --------
              • -------- We create the dummy here --------
              • -------- Depending on where you want your dummy to spawn --------
              • -------- You might need another Point variable --------
              • -------- But to keep this simple, I will create the dummy at the Caster's position instead --------
              • -------- - --------
              • Unit - Create 1 Spear Dummy for (Owner of ImpalingSpear_Unit) at ImpalingSpear_CastPoint facing ImpalingSpear_Angle degrees
              • -------- - --------
              • -------- Now, we need to store this unit into a variable, so we can use the reference for later --------
              • -------- - --------
              • Set ImpalingSpear_Dummy = (Last created unit)
              • -------- - --------
              • -------- It is time to throw the spear! --------
              • -------- Let's change the boolean value --------
              • -------- - --------
              • Set ImpalingSpear_TimeToLaunch = True
              • -------- - --------
              • -------- Play our unit animation! --------
              • -------- - --------
              • Animation - Play ImpalingSpear_Unit's attack animation
            • Else - Actions
        • Else - Actions
          • -------- - --------
          • -------- The caster is interrupted --------
          • -------- The rest of this trigger will not run --------
          • -------- - --------
      • -------- - --------
      • -------- Let's check if it is time to launch --------
      • -------- - --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ImpalingSpear_TimeToLaunch Equal to True
        • Then - Actions
          • -------- - --------
          • -------- Now, we must handle the movement of the spear --------
          • -------- To do so, we will update its location, bit by bit --------
          • -------- - --------
          • -------- This will store the current position of our dummy unit --------
          • -------- - --------
          • Set ImpalingSpear_DummyPoint = (Position of ImpalingSpear_Dummy)
          • -------- - --------
          • -------- This will store the next position where our dummy unit will go --------
          • -------- I'm using this formula to imitate how missiles from default abilities in object editor works --------
          • -------- Speed * Interval --------
          • -------- - --------
          • Set ImpalingSpear_DummyNextPoint = (ImpalingSpear_DummyPoint offset by (ImpalingSpear_Speed x ImpalingSpear_Interval) towards ImpalingSpear_Angle degrees)
          • -------- - --------
          • -------- Now, we can update the dummy's position --------
          • -------- - --------
          • Unit - Move ImpalingSpear_Dummy instantly to ImpalingSpear_DummyNextPoint
          • -------- - --------
          • -------- We must also update the distance that the dummy unit has gained --------
          • -------- - --------
          • Set ImpalingSpear_CurrentDistance = (ImpalingSpear_CurrentDistance + (ImpalingSpear_Speed x ImpalingSpear_Interval))
          • -------- - --------
          • -------- Let's deal damage to nearby enemy units --------
          • -------- - --------
          • Unit Group - Pick every unit in (Units within 200.00 of ImpalingSpear_DummyNextPoint) and do (Actions)
            • Loop - Actions
              • -------- - --------
              • -------- I recommend to use IF THEN ELSE for a better readability! --------
              • -------- We must check: --------
              • -------- * The unit is not a structure --------
              • -------- * The unit belongs to the caster's enemy --------
              • -------- * The unit is not dead --------
              • -------- * The unit is not in already damaged group --------
              • -------- - --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked unit) is A structure) Equal to False
                  • ((Picked unit) belongs to an enemy of (Owner of ImpalingSpear_Unit)) Equal to True
                  • ((Picked unit) is dead) Equal to False
                  • ((Picked unit) is in ImpalingSpear_AlreadyDamaged) Equal to False
                • Then - Actions
                  • -------- - --------
                  • -------- The unit fits our criteria! --------
                  • -------- Let's deal damage to them using our previously declared value --------
                  • -------- "ImpalingSpear_Damage" variable from Impaling Spear Config Trigger --------
                  • -------- - --------
                  • Unit - Cause ImpalingSpear_Unit to damage (Picked unit), dealing ImpalingSpear_Damage damage of attack type Spells and damage type Normal
                  • -------- - --------
                  • -------- The unit is damaged, let's mark it by inserting it into a unit group --------
                  • -------- This way, the enemy unit will only take the damage once --------
                  • -------- We can also use this group to do a knockback --------
                  • -------- - --------
                  • Unit Group - Add (Picked unit) to ImpalingSpear_AlreadyDamaged
                  • -------- - --------
                  • -------- You can create a special effect here if you wish --------
                  • -------- Destroy it right away as we no longer need it --------
                  • -------- - --------
                  • Special Effect - Create a special effect attached to the chest of (Picked unit) using Abilities\Spells\Other\Stampede\StampedeMissileDeath.mdl
                  • Special Effect - Destroy (Last created special effect)
                  • -------- - --------
                  • -------- Handling a knockback takes extra effort --------
                  • -------- You need to learn "Dynamic Indexing" or "Hashtable" first --------
                  • -------- If you want to make your own knockback system --------
                  • -------- - --------
                  • -------- Luckily for you, we have many Knockback System to choose from in Hiveworkshop --------
                  • -------- For this, I will use Bribe's knockback 2D --------
                  • -------- - --------
                  • -------- First store the position of the enemy unit --------
                  • -------- - --------
                  • Set ImpalingSpear_EnemyPoint = (Position of (Picked unit))
                  • -------- - --------
                  • -------- Then you need these four variables: --------
                  • -------- - --------
                  • Set Knockback2DAngle = (Angle from ImpalingSpear_DummyNextPoint to ImpalingSpear_EnemyPoint)
                  • Set Knockback2DDistance = 500.00
                  • Set Knockback2DTime = ImpalingSpear_MaxKnockDuration
                  • Set Knockback2DUnit = (Picked unit)
                  • -------- - --------
                  • -------- Then simply run the Knockback 2D trigger --------
                  • -------- - --------
                  • Trigger - Run Knockback 2D <gen> (checking conditions)
                  • -------- - --------
                  • -------- This does not stun them, so you have to create another dummy and order it to cast stun ability at these units --------
                  • -------- This will be an example: --------
                  • -------- - --------
                  • Unit - Create 1 StunDummy for (Owner of ImpalingSpear_Unit) at ImpalingSpear_EnemyPoint facing Default building facing degrees
                  • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
                  • Unit - Order (Last created unit) to Human Mountain King - Storm Bolt (Picked unit)
                  • -------- - --------
                  • -------- This will create a dummy that cast a storm bolt to stun --------
                  • -------- For every enemy unit --------
                  • -------- Which means, if you pick 10 enemies, you will create 10 dummies --------
                  • -------- Not very ideal, ideally you want only one dummy and order it again and again. --------
                  • -------- You can achieve that by creating the dummy for neutral passive at config trigger once --------
                  • -------- Then you can order that dummy to cast storm bolt here --------
                  • -------- - --------
                • Else - Actions
          • -------- - --------
          • -------- Let's check whether the dummy unit has reached maximum distance or not --------
          • -------- We can achieve this by comparing CurrentDistance to MaximumDistance --------
          • -------- - --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ImpalingSpear_CurrentDistance Greater than or equal to ImpalingSpear_MaxDistance
            • Then - Actions
              • -------- - --------
              • -------- It has reached the maximum distance --------
              • -------- Let's kill or remove the dummy unit --------
              • -------- - --------
              • Unit - Kill ImpalingSpear_Dummy
              • -------- - --------
              • -------- Don't forget to clear the "AlreadyDamaged" group, so it can be used again next time --------
              • -------- - --------
              • Unit Group - Remove all units from ImpalingSpear_AlreadyDamaged
              • -------- - --------
              • -------- This trigger is now finished, let's turn it back off --------
              • -------- - --------
              • Trigger - Turn off (This trigger)
            • Else - Actions
        • Else - Actions


You should check the testmap that I attached, you can see the object editor as well to see how I set up things.

The code I have written is actually very far from perfect.
  • It is not leakless, you can read it here for more details -> Memory Leaks
  • It is not MUI, meaning it will not work properly when casted by multiple units at the same time. For a start, you can read this -> Visualize: Dynamic Indexing
  • It creates dummy for each damaged enemy (dummy caster should be created once and reused).
  • Some constants are not written in the config trigger. For examples: Area of Effect, KnockbackDistance.
  • Adjustments are absolutely necessary as the spear spawns and thrown before the animation is properly finished.

I highly recommend reading and learning about Dynamic Indexing or hashtable first for a better understanding of MUI.
I am writing this as a Non MUI spell so you can get a better understanding of how the trigger logic work using what you already know.
Hopefully, it is helpful for you and the readers.

Your next task is to read the tutorials from the link that I gave you and try to make a MUI version of this spell.
Good luck! and feel free to ask!

Credits:
Bribe, for GUI Knockback 2.5D v4.2.5.0
 

Attachments

  • Impaling Spear.w3x
    45.6 KB · Views: 1
Last edited:
Top