• 🏆 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!

Help With Triggers for AoE Ensnare

Status
Not open for further replies.
Level 4
Joined
Feb 2, 2023
Messages
28
Hello, I've been currently working on a custom hero for a campaign I've decided to have a go at, I've never made any Blizzard maps, but I have made plenty using Bethesda's modkits. But anywho, learning the differences has been a bit jarring, but I've managed to make some headway until I got to my first trigger, creating a AoE Ensnare ability for a hero, I've used cluster rockets to throw out multiple nets, but I cannot get a dummy caster to cast the spell, or maybe the dummy isnt placing properly, hopefully someone here can tell me what I'm doing wrong.

Dummy Ensnare is just a copy of ensnare with the stats messed with a bit, and techtree requirements removed
Dummy Caster is no model.
Triggers are as follows:
  • Aoe Ensnare
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Aoe Ensnare
    • Actions
      • Set VariableSet Points[1] = (Target point of ability being cast)
      • Set VariableSet TempGroup = (Units within 500.00 of Points[1].)
      • Custom script: call RemoveLocation(udg_Points[1])
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet Points[1] = (Position of (Picked unit))
          • Unit - Create 1 Dummy Caster for (Owner of Caster) at Points[1] facing Default building facing degrees
          • Unit - Add Dummy Ensnare to (Last created unit)
          • Unit - Order (Last created unit) to Orc Raider - Ensnare (Picked unit)
          • Unit - Add a 1.00 second Generic expiration timer to (Last created unit)
          • Custom script: call RemoveLocation(udg_Points[1])
          • Custom script: call DestroyGroup(udg_TempGroup)
 
Level 24
Joined
Feb 9, 2009
Messages
1,787
Welcome to our forums!
For your first post, your enthusiasm and skill is apparent & refreshing.

Now for your trigger, you're stopping the loop when it runs once; causing the Unit Group Loop to stop searching for units after picking only one.
Move the Custom Script to destroy the group outside the loop and below "Unit Group - Pick...";
This will allow the loop to run it's course and select all available units.

There's room for improvement(Not for the faint of heart):
  • Aoe Ensnare
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Animate Dead
    • Actions
      • Set VariableSet Points[1] = (Target point of ability being cast)
      • Set VariableSet AOE = 500.00
      • Unit - Create 1 Universal Dummy Unit for Neutral Passive at Points[1] facing Default building facing degrees
      • Set VariableSet Dummy = (Last created unit)
      • Unit - Add Ensnare (Neutral Hostile) to Dummy
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within (AOE + Collision_Maximum_Radius(it's 200.00See Gameplay Constants) of Points[1].) and do (Actions)
        • Loop - Actions
          • Custom script: if IsUnitInRangeLoc(GetEnumUnit(), udg_Points[1],udg_AOE) then
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is alive) Equal to True
              • ((Unit-type of (Picked unit)) is A structure) Equal to False
            • Then - Actions
              • Unit - Order Dummy to Orc Raider - Ensnare (Picked unit)
            • Else - Actions
          • Custom script: endif
      • Unit - Add a 0.50 second Generic expiration timer to Dummy
      • Custom script: call RemoveLocation(udg_Points[1])
Edit:
I added the customscript to the unit group loop, I wish someone had told me when I was starting out.
Remove it if you want, but it's to keep your aoe selection accurate to war3's aoe selection highlight when you are selecting an area to cast on (in game and manually with the aoe display circle) you need to incorporate collision size so unit's that are highlighted are selected.
Exibit A from my first run in with this issue (Learn more on the post it originates from):
2dgxg9-png.392396




Also some excellent tutorials I recommend:
 
Last edited:
Level 4
Joined
Feb 2, 2023
Messages
28
Awesome, thanks so much, ya I was planning to finesse it a bit, I just always like to see a proof of concept before I go dabbling with more complex functions. Thanks again, I'll let ya know how it goes :D
For the AOE would that be saved as an integer? The coding system I'm familiar with uses float values for partial numbers and integers for whole numbers, just wondering because of the ".00"

edit: I just had a thought, it could be wrong, but since it was picking out 1 of the units hit, shouldn't at least one of them been hit by ensnare? Regardless I'll keep tinkering with it, thx again :D
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,570
Reals (floats) have a decimal. Integers are whole numbers. You can always tell the difference by the lack of or inclusion of the ".00" as you mentioned.

An important thing and possibly the source of your issue is the Dummy unit. I've found that 9 times out of 10 people are setting it up wrong.
With a proper setup you can use a single Dummy unit to cast any number of abilities at the same time.

What you want to do is copy and paste the Locust unit, then change the following fields:
Attacks Enabled = None
Movement Type = None
Speed Base = 0
Model = None
Shadow = None
Classification = None

You'll notice the Locust has an Art - Cast Point of 0.00 and Art - Cast Backswing of 0.00. These fields control how long the delay is before a unit casts a spell (Point) and how long they will continue playing their cast animation afterwards (Backswing). With a value of 0 the unit won't have any delay when casting spells.

Also, by adjusting the Movement Type and Speed Base (I believe both are necessary but I could be wrong) you allow your unit to cast spells without needing to turn and face it's target, similar to how Buildings function.

After that, double check to make sure that your Ensnare ability doesn't have any restrictions:
Cast Range = 99999
Requirements = None
Mana Cost = 0
Targets Allowed = Air, Ground (might have to mess with these depending on the ability)

You can always give the ability to one of your units and test it in-game. If it works then that narrows the issue down to either a mistake with the Dummy unit or a mistake in your trigger(s).

Some other possible issues: Your Dummy unit is owned by the wrong player, you have lost reference to your Dummy unit (using a Unit variable can help avoid this, although (Last created unit) is almost always fine), you're reusing variables that shouldn't be shared.
 
Last edited:
Level 4
Joined
Feb 2, 2023
Messages
28
Awesome thanks guys, got it working as intended, if you could give my final script a once over and tell me if I have any leaks (which I don't know how to identify yet, I assume people are talking about code unnecessarily running in the background) If you wanna use the skill its set to match the projectile count from the respective level of the copied cluster rocket spell.

  • [SPOILER="Trigger Script"]
  • Aoe Ensnare
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Aoe Ensnare
    • Actions
      • Set VariableSet Caster = (Triggering unit)
      • Set VariableSet Points[1] = (Target point of ability being cast)
      • Game - Display to (All players) for 0.00 seconds the text: phase1
      • Unit - Create 1 Dummy Caster for Neutral Passive at Points[1] facing Default building facing degrees
      • Set VariableSet Dummy = (Last created unit)
      • Unit - Add Dummy Ensnare to Dummy
      • Unit - Set level of Dummy Ensnare for Dummy to (Level of Aoe Ensnare for Caster)
      • Set VariableSet TargetCount = (Level of Aoe Ensnare for Caster)
      • Set VariableSet TargetCount = (TargetCount x 3)
      • Set VariableSet AOE = 300.00
      • Set VariableSet TargetHit = 0
      • Custom script: set bj_wantDestroyGroup = true
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • TargetCount Equal to 3
        • Then - Actions
          • Set VariableSet AOE = 200.00
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TargetCount Equal to 6
            • Then - Actions
              • Set VariableSet AOE = 250.00
              • Game - Display to (All players) for 0.00 seconds the text: lvl 2
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • TargetCount Equal to 9
                • Then - Actions
                  • Set VariableSet AOE = 300.00
                  • Game - Display to (All players) for 0.00 seconds the text: lvl 3
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • TargetCount Equal to 12
                    • Then - Actions
                      • Set VariableSet AOE = 350.00
                    • Else - Actions
          • Game - Display to (All players) for 0.00 seconds the text: phasefail
      • Unit Group - Pick every unit in (Units within AOE of Points[1].) and do (Actions)
        • Loop - Actions
          • Custom script: if IsUnitInRangeLoc(GetEnumUnit(), udg_Points[1],udg_AOE) then
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is alive) Equal to True
              • TargetHit Less than TargetCount
              • ((Picked unit) belongs to an ally of Player 1 (Red).) Equal to False
              • ((Unit-type of (Picked unit)) is A structure) Equal to False
            • Then - Actions
              • Game - Display to (All players) for 0.00 seconds the text: phase3
              • Unit - Order Dummy to Orc Raider - Ensnare (Picked unit)
              • Set VariableSet TargetHit = (TargetHit + 1)
            • Else - Actions
          • Custom script: endif
      • Unit - Add a 0.50 second Generic expiration timer to (Last created unit)
      • Custom script: call RemoveLocation(udg_Points[1])
  • [/SPOILER]
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,570
That looks good but just for the sake of perfectionism:
  • Aoe Ensnare
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Aoe Ensnare
    • Actions
      • Set VariableSet Caster = (Triggering unit)
      • Set Variableset CastingPlayer = (Triggering player)
      • Set VariableSet Level = (Level of (Ability being cast))
      • Set VariableSet Points[1] = (Target point of ability being cast)
      • Set VariableSet AOE = (150.00 + (50.00 * Real(Level)))
      • Set VariableSet TargetCount = (Level * 3)
      • Set VariableSet TargetHit = 0
      • Unit - Create 1 Dummy Caster for CastingPlayer at Points[1] facing Default building facing degrees
      • Set VariableSet Dummy = (Last created unit)
      • Unit - Add a 0.50 second Generic expiration timer to Dummy
      • Unit - Add Dummy Ensnare to Dummy
      • Unit - Set level of Dummy Ensnare for Dummy to Level
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within AOE of Points[1].) and do (Actions)
        • Loop - Actions
          • Set Variable Target = (Picked unit)
          • Custom script: if IsUnitInRangeLoc(udg_Target, udg_Points[1], udg_AOE) then
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • TargetHit Less than TargetCount
              • (Target is alive) Equal to True
              • (Target belongs to an enemy of CastingPlayer) Equal to True
              • (Target is A structure) Equal to False
            • Then - Actions
              • Unit - Order Dummy to Orc Raider - Ensnare Target
              • Set VariableSet TargetHit = (TargetHit + 1)
            • Else - Actions
          • Custom script: endif
      • Custom script: call RemoveLocation(udg_Points[1])
Arithmetic allows you to simplify the TargetCount and AOE variables so that you don't need to bloat the trigger with If Then Else statements.
 
Last edited:
Level 4
Joined
Feb 2, 2023
Messages
28
Awesome I was trying to find a function to convert an integer to real, that was all I needed, thanks so much, the ability is working beautifully.
 
Level 39
Joined
Feb 27, 2007
Messages
5,024
A memory leak is some object that is no longer needed but no longer has any variable pointing to it, and so can’t be cleaned up. This then becomes permanently allocated memory until the map ends.

 
Status
Not open for further replies.
Top