• 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.

[Spell] Shockwave Charge Ability

Rheiko

Spell Reviewer
Level 27
Joined
Aug 27, 2013
Messages
4,250
You need to trigger it. You will have to check the hero's location and update it every frame to a new location. You can either stop when the hero reaches the designated location or when the hero has traveled for X distance.

The basic functional trigger with the most barebone logic will look like this:
  • Charge
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge
    • Actions
      • -------- Store the caster --------
      • Set Charge_Caster = (Triggering unit)
      • -------- Store the location where he's currently at --------
      • Set Charge_CasterLocation = (Position of Charge_Caster)
      • -------- Store the location where the ability is casted at --------
      • Set Charge_TargetLocation = (Target point of ability being cast)
      • -------- Store the angle between these two locations --------
      • Set Charge_Angle = (Angle from Charge_CasterLocation to Charge_TargetLocation)
      • -------- Continue to the next trigger (Charge Loop is initially off) --------
      • Trigger - Turn on Charge Loop <gen>
  • Charge Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- Store the location where he's currently at --------
      • Set Charge_CasterLocation = (Position of Charge_Caster)
      • -------- Store the location where he's going to be in the next frame --------
      • Set Charge_CasterNewLocation = (Charge_Location1 offset by 33.00 towards Charge_Angle degrees)
      • -------- Move the guy --------
      • Unit - Move Charge_Caster instantly to Charge_CasterNewLocation
      • -------- Check if he's getting close to the designated location --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between Charge_CasterNewLocation and Charge_TargetLocation) Less than or equal to 100.00
        • Then - Actions
          • -------- When he does get close, turn off this trigger to stop the movement --------
          • Trigger - Turn off (This trigger)
        • Else - Actions
But this is not MUI, meaning if you have multiple units casting this ability, it will not work properly. This is due to how the variables are being overwritten whenever the trigger runs.

To make this MUI, we need to organize the data flow with multiple units in mind. The most beginner friendly and probably easiest method to understand is a technique known as Dynamic Indexing, the tutorial can be found here: Visualize: Dynamic Indexing
  • Charge MUI
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge MUI
    • Actions
      • -------- Everytime the ability is casted, we increase the index by 1 --------
      • Set Charge_MaxIndex = (Charge_MaxIndex + 1)
      • -------- We assign the index to the caster variable so each caster will have different indexes --------
      • Set Charge_CasterArray[Charge_MaxIndex] = (Triggering unit)
      • -------- Store the location where he's currently at, just like before --------
      • Set Charge_CasterLocation = (Position of Charge_CasterArray[Charge_MaxIndex])
      • -------- Store the location where the ability is casted at, each caster could have different target location --------
      • Set Charge_TargetLocationArray[Charge_MaxIndex] = (Target point of ability being cast)
      • -------- Store the angle between these two locations --------
      • Set Charge_AngleArray[Charge_MaxIndex] = (Angle from Charge_CasterLocation to Charge_TargetLocationArray[Charge_MaxIndex])
      • -------- If it is the first index then --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Charge_MaxIndex Equal to 1
        • Then - Actions
          • -------- Continue to the next trigger (Charge Loop is initially off) --------
          • Trigger - Turn on Charge MUI Loop <gen>
        • Else - Actions
  • Charge MUI Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- Loop through all the indexes --------
      • For each (Integer Charge_CurrentIndex) from 1 to Charge_MaxIndex, do (Actions)
        • Loop - Actions
          • -------- Store the location where he's currently at --------
          • Set Charge_CasterLocation = (Position of Charge_CasterArray[Charge_CurrentIndex])
          • -------- Store the location where he's going to be in the next frame --------
          • Set Charge_CasterNewLocation = (Charge_CasterLocation offset by 33.00 towards Charge_AngleArray[Charge_CurrentIndex] degrees)
          • -------- Move the guy --------
          • Unit - Move Charge_CasterArray[Charge_CurrentIndex] instantly to Charge_CasterNewLocation
          • -------- Check if he's getting close to the designated location --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between Charge_CasterLocation and Charge_TargetLocationArray[Charge_CurrentIndex]) Less than or equal to 100.00
            • Then - Actions
              • -------- When he does get close, we recycle the index --------
              • Set Charge_TargetLocationArray[Charge_CurrentIndex] = Charge_TargetLocationArray[Charge_MaxIndex]
              • Set Charge_CasterArray[Charge_CurrentIndex] = Charge_CasterArray[Charge_MaxIndex]
              • Set Charge_CasterArray[Charge_MaxIndex] = No unit
              • Set Charge_AngleArray[Charge_CurrentIndex] = Charge_AngleArray[Charge_MaxIndex]
              • Set Charge_AngleArray[Charge_MaxIndex] = 0.00
              • Set Charge_CurrentIndex = (Charge_CurrentIndex - 1)
              • Set Charge_MaxIndex = (Charge_MaxIndex - 1)
              • -------- Turn the trigger off when there is no more active indexes --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Charge_MaxIndex Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
When you store a location into a variable, you're creating a new location object. This will consume memory. When you store another location into that same variable (overwriting it) without destroying the previous location object, you will lose reference to the previous location but that previous location is still being kept in the memory, thus causing a memory leak.
Read more about Memory Leak here: Memory Leaks

You need to prevent this by using a custom script like this
  • Custom script: call RemoveLocation(udg_YourLocationVariableName)
call RemoveLocation will destroy the previous location object. Don't forget the prefix udg_ before your variable name.

So we will end up with this trigger:
  • Charge MUI
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge MUI
    • Actions
      • -------- Everytime the ability is casted, we increase the index by 1 --------
      • Set Charge_MaxIndex = (Charge_MaxIndex + 1)
      • -------- We assign the index to the caster variable so each caster will have different indexes --------
      • Set Charge_CasterArray[Charge_MaxIndex] = (Triggering unit)
      • -------- Store the location where he's currently at, just like before --------
      • Set Charge_CasterLocation = (Position of Charge_CasterArray[Charge_MaxIndex])
      • -------- Store the location where the ability is casted at, each caster could have different target location --------
      • Set Charge_TargetLocationArray[Charge_MaxIndex] = (Target point of ability being cast)
      • -------- Store the angle between these two locations --------
      • Set Charge_AngleArray[Charge_MaxIndex] = (Angle from Charge_CasterLocation to Charge_TargetLocationArray[Charge_MaxIndex])
      • -------- If it is the first index then --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Charge_MaxIndex Equal to 1
        • Then - Actions
          • -------- Continue to the next trigger (Charge Loop is initially off) --------
          • Trigger - Turn on Charge MUI Loop <gen>
        • Else - Actions
      • -------- Prevent memory leaks --------
      • Custom script: call RemoveLocation(udg_Charge_CasterLocation)
  • Charge MUI Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- Loop through all the indexes --------
      • For each (Integer Charge_CurrentIndex) from 1 to Charge_MaxIndex, do (Actions)
        • Loop - Actions
          • -------- Store the location where he's currently at --------
          • Set Charge_CasterLocation = (Position of Charge_CasterArray[Charge_CurrentIndex])
          • -------- Store the location where he's going to be in the next frame --------
          • Set Charge_CasterNewLocation = (Charge_CasterLocation offset by 33.00 towards Charge_AngleArray[Charge_CurrentIndex] degrees)
          • -------- Move the guy --------
          • Unit - Move Charge_CasterArray[Charge_CurrentIndex] instantly to Charge_CasterNewLocation
          • -------- Check if he's getting close to the designated location --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between Charge_CasterLocation and Charge_TargetLocationArray[Charge_CurrentIndex]) Less than or equal to 100.00
            • Then - Actions
              • -------- Prevent memory leak --------
              • Custom script: call RemoveLocation(udg_Charge_TargetLocationArray[udg_Charge_CurrentIndex])
              • -------- When he does get close, we recycle the index --------
              • Set Charge_TargetLocationArray[Charge_CurrentIndex] = Charge_TargetLocationArray[Charge_MaxIndex]
              • Set Charge_CasterArray[Charge_CurrentIndex] = Charge_CasterArray[Charge_MaxIndex]
              • Set Charge_CasterArray[Charge_MaxIndex] = No unit
              • Set Charge_AngleArray[Charge_CurrentIndex] = Charge_AngleArray[Charge_MaxIndex]
              • Set Charge_AngleArray[Charge_MaxIndex] = 0.00
              • Set Charge_CurrentIndex = (Charge_CurrentIndex - 1)
              • Set Charge_MaxIndex = (Charge_MaxIndex - 1)
              • -------- Turn the trigger off when there is no more active indexes --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Charge_MaxIndex Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
          • -------- Prevent memory leaks --------
          • Custom script: call RemoveLocation(udg_Charge_CasterLocation)
          • Custom script: call RemoveLocation(udg_Charge_CasterNewLocation)
 

Attachments

  • Charge Example.w3x
    21.1 KB · Views: 2
You need to trigger it. You will have to check the hero's location and update it every frame to a new location. You can either stop when the hero reaches the designated location or when the hero has traveled for X distance.

The basic functional trigger with the most barebone logic will look like this:
  • Charge
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge
    • Actions
      • -------- Store the caster --------
      • Set Charge_Caster = (Triggering unit)
      • -------- Store the location where he's currently at --------
      • Set Charge_CasterLocation = (Position of Charge_Caster)
      • -------- Store the location where the ability is casted at --------
      • Set Charge_TargetLocation = (Target point of ability being cast)
      • -------- Store the angle between these two locations --------
      • Set Charge_Angle = (Angle from Charge_CasterLocation to Charge_TargetLocation)
      • -------- Continue to the next trigger (Charge Loop is initially off) --------
      • Trigger - Turn on Charge Loop <gen>
  • Charge Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- Store the location where he's currently at --------
      • Set Charge_CasterLocation = (Position of Charge_Caster)
      • -------- Store the location where he's going to be in the next frame --------
      • Set Charge_CasterNewLocation = (Charge_Location1 offset by 33.00 towards Charge_Angle degrees)
      • -------- Move the guy --------
      • Unit - Move Charge_Caster instantly to Charge_CasterNewLocation
      • -------- Check if he's getting close to the designated location --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Distance between Charge_CasterNewLocation and Charge_TargetLocation) Less than or equal to 100.00
        • Then - Actions
          • -------- When he does get close, turn off this trigger to stop the movement --------
          • Trigger - Turn off (This trigger)
        • Else - Actions
But this is not MUI, meaning if you have multiple units casting this ability, it will not work properly. This is due to how the variables are being overwritten whenever the trigger runs.

To make this MUI, we need to organize the data flow with multiple units in mind. The most beginner friendly and probably easiest method to understand is a technique known as Dynamic Indexing, the tutorial can be found here: Visualize: Dynamic Indexing
  • Charge MUI
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge MUI
    • Actions
      • -------- Everytime the ability is casted, we increase the index by 1 --------
      • Set Charge_MaxIndex = (Charge_MaxIndex + 1)
      • -------- We assign the index to the caster variable so each caster will have different indexes --------
      • Set Charge_CasterArray[Charge_MaxIndex] = (Triggering unit)
      • -------- Store the location where he's currently at, just like before --------
      • Set Charge_CasterLocation = (Position of Charge_CasterArray[Charge_MaxIndex])
      • -------- Store the location where the ability is casted at, each caster could have different target location --------
      • Set Charge_TargetLocationArray[Charge_MaxIndex] = (Target point of ability being cast)
      • -------- Store the angle between these two locations --------
      • Set Charge_AngleArray[Charge_MaxIndex] = (Angle from Charge_CasterLocation to Charge_TargetLocationArray[Charge_MaxIndex])
      • -------- If it is the first index then --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Charge_MaxIndex Equal to 1
        • Then - Actions
          • -------- Continue to the next trigger (Charge Loop is initially off) --------
          • Trigger - Turn on Charge MUI Loop <gen>
        • Else - Actions
  • Charge MUI Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- Loop through all the indexes --------
      • For each (Integer Charge_CurrentIndex) from 1 to Charge_MaxIndex, do (Actions)
        • Loop - Actions
          • -------- Store the location where he's currently at --------
          • Set Charge_CasterLocation = (Position of Charge_CasterArray[Charge_CurrentIndex])
          • -------- Store the location where he's going to be in the next frame --------
          • Set Charge_CasterNewLocation = (Charge_CasterLocation offset by 33.00 towards Charge_AngleArray[Charge_CurrentIndex] degrees)
          • -------- Move the guy --------
          • Unit - Move Charge_CasterArray[Charge_CurrentIndex] instantly to Charge_CasterNewLocation
          • -------- Check if he's getting close to the designated location --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between Charge_CasterLocation and Charge_TargetLocationArray[Charge_CurrentIndex]) Less than or equal to 100.00
            • Then - Actions
              • -------- When he does get close, we recycle the index --------
              • Set Charge_TargetLocationArray[Charge_CurrentIndex] = Charge_TargetLocationArray[Charge_MaxIndex]
              • Set Charge_CasterArray[Charge_CurrentIndex] = Charge_CasterArray[Charge_MaxIndex]
              • Set Charge_CasterArray[Charge_MaxIndex] = No unit
              • Set Charge_AngleArray[Charge_CurrentIndex] = Charge_AngleArray[Charge_MaxIndex]
              • Set Charge_AngleArray[Charge_MaxIndex] = 0.00
              • Set Charge_CurrentIndex = (Charge_CurrentIndex - 1)
              • Set Charge_MaxIndex = (Charge_MaxIndex - 1)
              • -------- Turn the trigger off when there is no more active indexes --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Charge_MaxIndex Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
When you store a location into a variable, you're creating a new location object. This will consume memory. When you store another location into that same variable (overwriting it) without destroying the previous location object, you will lose reference to the previous location but that previous location is still being kept in the memory, thus causing a memory leak.
Read more about Memory Leak here: Memory Leaks

You need to prevent this by using a custom script like this
  • Custom script: call RemoveLocation(udg_YourLocationVariableName)
call RemoveLocation will destroy the previous location object. Don't forget the prefix udg_ before your variable name.

So we will end up with this trigger:
  • Charge MUI
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Charge MUI
    • Actions
      • -------- Everytime the ability is casted, we increase the index by 1 --------
      • Set Charge_MaxIndex = (Charge_MaxIndex + 1)
      • -------- We assign the index to the caster variable so each caster will have different indexes --------
      • Set Charge_CasterArray[Charge_MaxIndex] = (Triggering unit)
      • -------- Store the location where he's currently at, just like before --------
      • Set Charge_CasterLocation = (Position of Charge_CasterArray[Charge_MaxIndex])
      • -------- Store the location where the ability is casted at, each caster could have different target location --------
      • Set Charge_TargetLocationArray[Charge_MaxIndex] = (Target point of ability being cast)
      • -------- Store the angle between these two locations --------
      • Set Charge_AngleArray[Charge_MaxIndex] = (Angle from Charge_CasterLocation to Charge_TargetLocationArray[Charge_MaxIndex])
      • -------- If it is the first index then --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Charge_MaxIndex Equal to 1
        • Then - Actions
          • -------- Continue to the next trigger (Charge Loop is initially off) --------
          • Trigger - Turn on Charge MUI Loop <gen>
        • Else - Actions
      • -------- Prevent memory leaks --------
      • Custom script: call RemoveLocation(udg_Charge_CasterLocation)
  • Charge MUI Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- Loop through all the indexes --------
      • For each (Integer Charge_CurrentIndex) from 1 to Charge_MaxIndex, do (Actions)
        • Loop - Actions
          • -------- Store the location where he's currently at --------
          • Set Charge_CasterLocation = (Position of Charge_CasterArray[Charge_CurrentIndex])
          • -------- Store the location where he's going to be in the next frame --------
          • Set Charge_CasterNewLocation = (Charge_CasterLocation offset by 33.00 towards Charge_AngleArray[Charge_CurrentIndex] degrees)
          • -------- Move the guy --------
          • Unit - Move Charge_CasterArray[Charge_CurrentIndex] instantly to Charge_CasterNewLocation
          • -------- Check if he's getting close to the designated location --------
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Distance between Charge_CasterLocation and Charge_TargetLocationArray[Charge_CurrentIndex]) Less than or equal to 100.00
            • Then - Actions
              • -------- Prevent memory leak --------
              • Custom script: call RemoveLocation(udg_Charge_TargetLocationArray[udg_Charge_CurrentIndex])
              • -------- When he does get close, we recycle the index --------
              • Set Charge_TargetLocationArray[Charge_CurrentIndex] = Charge_TargetLocationArray[Charge_MaxIndex]
              • Set Charge_CasterArray[Charge_CurrentIndex] = Charge_CasterArray[Charge_MaxIndex]
              • Set Charge_CasterArray[Charge_MaxIndex] = No unit
              • Set Charge_AngleArray[Charge_CurrentIndex] = Charge_AngleArray[Charge_MaxIndex]
              • Set Charge_AngleArray[Charge_MaxIndex] = 0.00
              • Set Charge_CurrentIndex = (Charge_CurrentIndex - 1)
              • Set Charge_MaxIndex = (Charge_MaxIndex - 1)
              • -------- Turn the trigger off when there is no more active indexes --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Charge_MaxIndex Equal to 0
                • Then - Actions
                  • Trigger - Turn off (This trigger)
                • Else - Actions
            • Else - Actions
          • -------- Prevent memory leaks --------
          • Custom script: call RemoveLocation(udg_Charge_CasterLocation)
          • Custom script: call RemoveLocation(udg_Charge_CasterNewLocation)
Thanks
 
Top