• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

How to make dummy move while channeling?

Status
Not open for further replies.
Level 3
Joined
Oct 22, 2022
Messages
13
how do you make it so that the dummy follows the hero while channeling an ability? I based the dummy spell on stampede, and I want the stampede to follow my hero
  • Untitled Trigger 002 Copy Copy
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Eagle Airstrike
    • Actions
      • Set Caster = (Triggering unit)
      • Set Target2 = (Target unit of issued order)
      • Set CasLoc = (Position of (Triggering unit))
  • Unit - Create 1 dummy (eagle airstrike) for (Owner of (Triggering unit)) at (Target point of ability being cast) facing ((X of ((Target point of ability being cast) offset by 256.00 towards 0.00 degrees)) + (Y of ((Target point of ability being cast) offset by 500.00 towards 0.00 degrees))) degrees
    • Unit - Add Eagle Airstrike (Rexxar) to Target2
    • Unit - Order (Last created unit) to Neutral Beastmaster - Stampede ((Target point of ability being cast) offset by 256.00 towards (Facing of (Triggering unit)) degrees)
    • Unit - Add a 10.00 second Generic expiration timer to (Last created unit)
Do note that the point offset is on purpose since I want to make it look like the airstrike is coming out from the hero itself
(bonus: if you know how to change the height of missiles in spells that would be really helpful since I want to increase the missile (air planes) height when I use this airstike)

Also, can you please make it as gui friendly as possible? idk how to use jass nor have the time to learn it, but if it really requires me to do jass then please tell me how)
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
Does it need to be MUI (Multi Unit Instanceable) or will MPI suffice (Multi Player Instanceable)? In other words, can any number of units have and use this ability at the same time? Or will there only be 1 hero with this ability? Or maybe up to 1 hero per player?

The design of the trigger becomes more complex if it's MUI.
 
Level 3
Joined
Oct 22, 2022
Messages
13
Does it need to be MUI (Multi Unit Instanceable) or will MPI suffice (Multi Player Instanceable)? In other words, can any number of units have and use this ability at the same time? Or will there only be 1 hero with this ability? Or maybe up to 1 hero per player?

The design of the trigger becomes more complex if it's MUI.
Only 1 hero has this ability
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
Only 1 hero has this ability
Okay, that makes it simple. You need to use the SetUnitX/Y functions which require the use of Custom Script:
  • Stampede Loop
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Stampede_Point = (Position of Stampede_Dummy)
      • Set VariableSet X = (X of Stampede_Point)
      • Set VariableSet Y = (Y of Stampede_Point)
      • Custom script: call SetUnitX(Stampede_Dummy, udg_X)
      • Custom script: call SetUnitY(Stampede_Dummy, udg_Y)
      • Custom script: call RemoveLocation(udg_Stampede_Point)
These functions will Move a unit without ordering it to Stop.

Your first trigger would Set Stampede_Dummy to the Dummy unit and then Turn On the Stampede Loop trigger. Then when the Hero stops Casting the ability you would Turn Off the Stampede Loop trigger and Remove the Dummy from the game.

You can't adjust the Missile Height of the Stampede Missiles as far as I know. For something like that you would want to trigger the whole thing yourself, although I'm sure there's a custom Stampede system on this site you can try to use.

Also, your first trigger is leaking a few Points and seems to have some wrong/unused variables. There is no Target Unit for the Stampede ability, it doesn't target units, it targets Points. An ability like Storm Bolt or Holy Light targets Units. If it did target a unit, you would use (Target unit of ability being cast) instead of (Target unit of issued order), which is intended for Issued Order Events.
 
Last edited:
Level 3
Joined
Oct 22, 2022
Messages
13
Okay, that makes it simple. You need to use the SetUnitX/Y functions which require the use of Custom Script:
  • Stampede Loop
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • Set VariableSet Stampede_Point = (Position of Stampede_Dummy)
      • Set VariableSet X = (X of Stampede_Point)
      • Set VariableSet Y = (Y of Stampede_Point)
      • Custom script: call SetUnitX(Stampede_Dummy, udg_X)
      • Custom script: call SetUnitY(Stampede_Dummy, udg_Y)
      • Custom script: call RemoveLocation(udg_Stampede_Point)
These functions will Move a unit without ordering it to Stop.

Your first trigger would Set Stampede_Dummy to the Dummy unit and then Turn On the Stampede Loop trigger. Then when the Hero stops Casting the ability you would Turn Off the Stampede Loop trigger and Remove the Dummy from the game.

You can't adjust the Missile Height of the Stampede Missiles as far as I know. For something like that you would want to trigger the whole thing yourself, although I'm sure there's a custom Stampede system on this site you can try to use.

Also, your first trigger is leaking a few Points and seems to have some wrong/unused variables. There is no Target Unit for the Stampede ability, it doesn't target units, it targets Points. An ability like Storm Bolt or Holy Light targets Units. If it did target a unit, you would use (Target unit of ability being cast) instead of (Target unit of issued order), which is intended for Issued Order Events.
I got an error when I did that, how do I fix it?
  • EA Loop
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • Set EAir_Point = (Position of (Last created unit))
      • Set EAir_X = (X of EAir_Point)
      • Set EAir_Y = (Y of EAir_Point)
      • Custom script: call SetUnitX(EAir_Point, udg_X)
      • Custom script: call SetUnitY(EAir_Point, udg_Y)
      • Custom script: call RemoveLocation(udg_EAir_Point)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
You need to reference the same Variable names in the Custom Script. There is no udg_X or udg_Y because you named your Variables EAir_X and EAir_Y.

And you can't do this inside of the Loop trigger:
  • (Position of (Last created unit))
The (Last created unit) is literally whichever unit was created last. There's no guarantee that this will be your Dummy unit every 0.01 seconds.

Edit: Anyway, this Point should be referencing the Position of the Hero since the Dummy is supposed to follow the Hero.
 
Last edited:
Level 19
Joined
Feb 27, 2019
Messages
590
Custom script is the same as code so it has different rules.

In custom script global variables require udg_ before the name. Global variables are those you use in GUI. In custom script EAir_X would become udg_EAir_X.

The function SetUnitX() requires the following arguments SetUnitX(unit, real)
Unit: The unit would be the reference to the unit the change should happen to. (For example GetLastCreatedUnit() or udg_YourVariable)
Real: The real value would be the X co-ordinate of where that unit should be placed. (For example GetUnitX(unit) or udg_YourVariable)

An example of how your code could look like however the reference last created unit is not reliable as Uncle pointed out:
  • Custom script: call SetUnitX(GetLastCreatedUnit(), GetUnitX(udg_Caster))
or
  • Set VariableSet Eair_Point = (Position of Caster)
  • Set VariableSet EAir_X = (X of Eair_Point)
  • Custom script: call SetUnitX(GetLastCreatedUnit(), udg_EAir_Point_X)
However I dont think it will matter if you move the unit that casts the stampede since the ability is cast at a certain point so moving the caster is irrelevant. It may change the direction of the stampede, I am not sure, but it will not yield your desired result, at least I dont think so.
 
Last edited:
Level 3
Joined
Oct 22, 2022
Messages
13
I tried to attach the command to the skill and it stopped working completely, how do I fix it? Or is it hopeless?
  • EA
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Eagle Airstrike
    • Actions
      • Set Caster = (Triggering unit)
      • Set EAir_Point = (Target point of ability being cast)
      • Set CasLoc = (Position of (Triggering unit))
      • Set Target2 = (Last created unit)
      • Set LCU_Pos = (Position of (Last created unit))
      • Unit - Create 1 dummy (eagle airstrike) for (Owner of Caster) at EAir_Point facing ((X of (EAir_Point offset by 256.00 towards 0.00 degrees)) + (Y of (EAir_Point offset by 500.00 towards 0.00 degrees))) degrees
      • Unit - Add Eagle Airstrike (Rexxar) to Target2
      • Unit - Set level of Eagle Airstrike (Rexxar) for Target2 to (Level of Eagle Airstrike for Caster)
      • Unit - Order Target2 to Neutral Beastmaster - Stampede (EAir_Point offset by 256.00 towards (Facing of Caster) degrees)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Ability being cast) Equal to Eagle Airstrike
        • Then - Actions
          • Set EAir_X = (X of LCU_Pos)
          • Set EAir_Y = (Y of LCU_Pos)
        • Else - Actions
          • Custom script: call SetUnitX(udg_Target2, udg_EAir_X)
          • Custom script: call SetUnitY(udg_Target2, udg_EAir_Y)
          • Custom script: call RemoveLocation(udg_LCU_Pos)
      • Unit - Add a 8.00 second Generic expiration timer to (Last created unit)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
Actions happen sequentially from top to bottom, left to right. If you're Setting Target2 to the (Last created unit) then there needs to be a Unit that was Created for it to work. Same applies to EAir_Point, the Point actually needs to exist before you try to use it.

For example, this trigger doesn't kill the dummy unit:
  • Actions
  • Unit - Kill (Last created unit)
  • Unit - Create 1 dummy for player...
But this trigger does kill the dummy:
  • Actions
  • Unit - Create 1 dummy for player...
  • Unit - Kill (Last created unit)
In the first example the Dummy doesn't exist yet so the (Last created unit) will be referencing either nothing (if no other Unit has been created yet) or some other Unit that you have created previously in another trigger. The second example works because the (Last created unit) gets Set to the Dummy unit BEFORE we try to kill it. The dummy is literally the last CREATED unit, in other words, it's the most recent unit to be created using the Create Unit action.

There were some other mistakes as well which is partially my fault for not being more clear. Your triggers should look something like this:
  • Eagle Airstrike Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Eagle Airstrike
    • Actions
      • Set EAir_Hero = (Triggering unit)
      • Set EAir_Point1 = (Position of EAir_Hero)
      • Set EAir_Point2 = (Target point of ability being cast)
      • Set EAir_Point3 = (EAir_Point2 offset by 256 towards (Angle between EAir_Point1 and EAir_Point2) degrees
      • Unit - Create 1 dummy (eagle airstrike) for (Owner of EAir_Hero) at EAir_Point2 facing Default building degrees
      • Set EAir_Dummy = (Last created unit)
      • Unit - Add Eagle Airstrike (Rexxar) to EAir_Dummy
      • Unit - Order EAir_Dummy to Neutral Beastmaster - Stampede EAir_Point3
      • Custom script: call RemoveLocation(udg_EAir_Point1)
      • Custom script: call RemoveLocation(udg_EAir_Point2)
      • Custom script: call RemoveLocation(udg_EAir_Point3)
      • Trigger - Turn on Eagle Airstrike Loop <gen>
^ I'm using the function (Point with polar offset) when Setting EAir_Point3. This should be used when determining a Point that's offset from another Point, and not used to determine (Facing degrees) like you were doing in your original trigger. The reason for using 3 separate Point variables is to avoid Memory Leaks. Alternatively, you can use a single Point variable Array if you want to keep things more organized, it would look like EAir_Point[1], EAir_Point[2], EAir_Point[3].

  • Eagle Airstrike Stop
    • Events
      • Unit - A unit Stops casting an ability
    • Conditions
      • (Ability being cast) Equal to Eagle Airstrike (Rexxar)
    • Actions
      • Unit - Remove (Triggering unit) from the game
      • Trigger - Turn off Eagle Airstrike Loop <gen>
  • Eagle Airstrike Loop
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • Set EAir_Point1 = (Position of EAir_Hero)
      • Set EAir_X = (X of EAir_Point1)
      • Set EAir_Y = (Y of EAir_Point1)
      • Custom script: call SetUnitX(EAir_Dummy, udg_EAir_X)
      • Custom script: call SetUnitY(EAir_Dummy, udg_EAir_Y)
      • Custom script: call RemoveLocation(udg_EAir_Point1)
Also, remember to set the Eagle Airstrike Loop trigger to be Initially OFF in the trigger editor. We don't want this trigger to be running unless there's an Eagle Airstrike dummy actually active on the map.

One last thing, your Dummy unit should have these settings in the Object Editor: Abilities: Locust, Movement Type: None, Speed Base: 0, Attacks Enabled: None, Death Type: Can't raise, does not Decay, Model: "none", Shadows: Off, Art - Cast Point / Backswing: 0.00

With those settings your Dummy unit should be completely invisible and will cast Stampede instantaneously without ever needing to turn to face it's target. Note that some of these settings will cause problems if you want your Dummy unit to be able to move around and have a visible model, this is meant for Dummy units that simply cast spells for you.
 
Last edited:
Level 3
Joined
Oct 22, 2022
Messages
13
Actions happen sequentially from top to bottom, left to right. If you're Setting Target2 to the (Last created unit) then there needs to be a Unit that was Created for it to work. Same applies to EAir_Point, the Point actually needs to exist before you try to use it.

For example, this trigger doesn't kill the dummy unit:
  • Actions
  • Unit - Kill (Last created unit)
  • Unit - Create 1 dummy for player...
But this trigger does kill the dummy:
  • Actions
  • Unit - Create 1 dummy for player...
  • Unit - Kill (Last created unit)
In the first example the Dummy doesn't exist yet so the (Last created unit) will be referencing either nothing (if no other Unit has been created yet) or some other Unit that you have created previously in another trigger. The second example works because the (Last created unit) gets Set to the Dummy unit BEFORE we try to kill it. The dummy is literally the last CREATED unit, in other words, it's the most recent unit to be created using the Create Unit action.

There were some other mistakes as well which is partially my fault for not being more clear. Your triggers should look something like this:
  • Eagle Airstrike Cast
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Eagle Airstrike
    • Actions
      • Set EAir_Hero = (Triggering unit)
      • Set EAir_Point1 = (Position of EAir_Hero)
      • Set EAir_Point2 = (Target point of ability being cast)
      • Set EAir_Point3 = (EAir_Point2 offset by 256 towards (Angle between EAir_Point1 and EAir_Point2) degrees
      • Unit - Create 1 dummy (eagle airstrike) for (Owner of EAir_Hero) at EAir_Point2 facing Default building degrees
      • Set EAir_Dummy = (Last created unit)
      • Unit - Add Eagle Airstrike (Rexxar) to EAir_Dummy
      • Unit - Order EAir_Dummy to Neutral Beastmaster - Stampede EAir_Point3
      • Custom script: call RemoveLocation(udg_EAir_Point1)
      • Custom script: call RemoveLocation(udg_EAir_Point2)
      • Custom script: call RemoveLocation(udg_EAir_Point3)
      • Trigger - Turn on Eagle Airstrike Loop <gen>
^ I'm using the function (Point with polar offset) when Setting EAir_Point3. This should be used when determining a Point that's offset from another Point, and not used to determine (Facing degrees) like you were doing in your original trigger. The reason for using 3 separate Point variables is to avoid Memory Leaks. Alternatively, you can use a single Point variable Array if you want to keep things more organized, it would look like EAir_Point[1], EAir_Point[2], EAir_Point[3].

  • Eagle Airstrike Stop
    • Events
      • Unit - A unit Stops casting an ability
    • Conditions
      • (Ability being cast) Equal to Eagle Airstrike (Rexxar)
    • Actions
      • Unit - Remove (Triggering unit) from the game
      • Trigger - Turn off Eagle Airstrike Loop <gen>
  • Eagle Airstrike Loop
    • Events
      • Time - Every 0.01 seconds of game time
    • Conditions
    • Actions
      • Set EAir_Point1 = (Position of EAir_Hero)
      • Set EAir_X = (X of EAir_Point1)
      • Set EAir_Y = (Y of EAir_Point1)
      • Custom script: call SetUnitX(EAir_Dummy, udg_EAir_X)
      • Custom script: call SetUnitY(EAir_Dummy, udg_EAir_Y)
      • Custom script: call RemoveLocation(udg_EAir_Point1)
Also, remember to set the Eagle Airstrike Loop trigger to be Initially OFF in the trigger editor. We don't want this trigger to be running unless there's an Eagle Airstrike dummy actually active on the map.

One last thing, your Dummy unit should have these settings in the Object Editor: Abilities: Locust, Movement Type: None, Speed Base: 0, Attacks Enabled: None, Death Type: Can't raise, does not Decay, Model: "none", Shadows: Off

With those settings your Dummy unit should be completely invisible and will cast Stampede instantaneously without ever needing to turn to face it's target.
Alright that worked thanks, now how do I make my dummy move while casting so it follows my hero wherever it goes?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
If it worked then the Dummy unit will follow the Hero. You need to create all 3 of those Airstrike triggers in my previous post and read everything I said.

If you did that already then you messed something up but I can't know what exactly unless I see your triggers.
 
Last edited:
Level 3
Joined
Oct 22, 2022
Messages
13
If it worked then the Dummy unit will follow the Hero. You need to create all 3 of those Airstrike triggers in my previous post and read everything I said.

If you did that already then you messed something up but I can't know what exactly unless I see your triggers.
Ok it actually worked (somehow?) the stampede is now following the hero but it kinda looks weird since when I used the ability facing west and my hero starts moving to north, the stampede follows my hero but it's facing west (idk if you get what I mean) but I'll just post the video as well as the spellpack here later and hopefully, have other of my problems regarding the spellpack fixed. Thank you.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
The direction of Stampede is most likely set in stone at the time of casting. The fact that the spell even moves along with the caster is pretty strange, I don't think there's anything in Warcraft 3's ladder games that would push or move the Beastmaster without cancelling the spell so it's a little weird that it has this feature.

Anyway, you can try changing the facing angle of the Dummy unit inside of the Loop trigger but I doubt that'll do anything.
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,015
Unfortunately, stampede's behavior in general is pretty unique in WC3 and it would be a little annoying to completely remake from scratch as a triggered spell... but it could definitely be done. That would allow you to be able to turn the effect with the hero, but honestly you might not like how it looks because of how the charging units far from the hero will get whipped around as the hero turns. Kinda hard to know for sure, though.

You could have a triggered stampede turn to follow the caster but only with some specific angular acceleration/velocity caps to make it lag behind in a perhaps-acceptable way.
 
Level 3
Joined
Oct 22, 2022
Messages
13
Alright, I posted the spellpack, I would be really happy if you guys can help me fix some of it's errors

 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,543
Alright, I posted the spellpack, I would be really happy if you guys can help me fix some of it's errors

There's a lot to look at here so I'll just give you a quick breakdown for now:
1) You have a lot of memory leaks and unused/unnecessary variables.
2) You're using Polar Offset wrong, I explained before that it's meant for determining a Point, not a facing Angle.
3) Your Dummy units are pretty much all setup incorrectly and you have a lot of unnecessary Dummy units. I explained before how they should be setup.
4) Don't create a separate trigger to Play a sound. You should have one trigger for each Event.
5) You have a lot of unnecessary triggers, instead of creating a trigger for each level of the Ability, simply design your single trigger to use the current level of the ability in it's Actions. For example you can use Arrays to store all of your data that needs to scale based on ability level:
  • Set Variable Lvl = (Level of (Ability being cast))
  • Unit - Add HellcatDeathDmg[Lvl] to (Last created unit)
6) Your use of Waits will cause a lot of problems and are not MUI friendly. There is no (Target point of ability being cast) after a Wait.
7) None of the spells are MUI which is going to be necessary if people will use your spellpack. This will require you to redesign the spells to take advantage of things like Unit Indexers/Hashtables to store data to Units and methods like Dynamic Indexing to handle delays in time (Waits).

So to sum it up, you're making all of the beginner mistakes and I recommend learning how to use the following:
Arrays, Hashtables, Unit Indexers (often a simpler solution to Hashtables), Dynamic Indexing (a method for creating MUI triggers), setting up a Dummy unit, and avoiding Memory Leaks.

I attached an example map of an MUI spell using Dynamic Indexing (requires latest patch to open).
 

Attachments

  • Custom Shockwave Fixed1.w3x
    25.6 KB · Views: 1
Last edited:
Status
Not open for further replies.
Top