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

[Trigger] Deal AoE damage per second trigger with waits. Is this spell MUI?

Status
Not open for further replies.
Level 5
Joined
Dec 25, 2018
Messages
110
This trigger doesn't work properly, when units are inside AoE range they take damage, but if they go out and come back to it they are not affected.
Did I miss out on something?
  • Smoke
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Smoke
    • Actions
      • Custom script: local unit udg_Caster
      • Custom script: local location udg_SmokePoint
      • Set Caster = (Triggering unit)
      • Set SmokePoint = (Target point of ability being cast)
      • Set SmokeDMG = ((40.00 x (Real((Level of Smoke for Caster)))) + ((Real((Agility of Caster (Include bonuses)))) / 2.00))
      • Unit - Create 1 Dummy for (Owner of Caster) at SmokePoint facing Default building facing degrees
      • Unit - Add a 6.00 second Generic expiration timer to (Last created unit)
      • Unit - Add Smoke1 to (Last created unit)
      • Unit - Set level of Smoke1 for (Last created unit) to (Level of Smoke for Caster)
      • Unit - Order (Last created unit) to Human Dragonhawk Rider - Cloud SmokePoint
      • Set SmokeGroup = (Units within 350.00 of SmokePoint matching ((((Matching unit) belongs to an ally of (Owner of (Last created unit))) Equal to False) and (((Matching unit) is alive) Equal to True)))
      • Unit Group - Pick every unit in SmokeGroup and do (Actions)
        • Loop - Actions
          • Unit - Cause (Last created unit) to damage (Picked unit), dealing SmokeDMG damage of attack type Spells and damage type Normal
      • Custom script: call DestroyGroup(udg_SmokeGroup)
      • Wait 1.00 seconds
      • Set SmokeGroup = (Units within 350.00 of SmokePoint matching ((((Matching unit) belongs to an ally of (Owner of (Last created unit))) Equal to False) and (((Matching unit) is alive) Equal to True)))
      • Unit Group - Pick every unit in SmokeGroup and do (Actions)
        • Loop - Actions
          • Unit - Cause (Last created unit) to damage (Picked unit), dealing SmokeDMG damage of attack type Spells and damage type Normal
      • Custom script: call DestroyGroup(udg_SmokeGroup)
      • Wait 1.00 seconds
      • Set SmokeGroup = (Units within 350.00 of SmokePoint matching ((((Matching unit) belongs to an ally of (Owner of (Last created unit))) Equal to False) and (((Matching unit) is alive) Equal to True)))
      • Unit Group - Pick every unit in SmokeGroup and do (Actions)
        • Loop - Actions
          • Unit - Cause (Last created unit) to damage (Picked unit), dealing SmokeDMG damage of attack type Spells and damage type Normal
      • Custom script: call DestroyGroup(udg_SmokeGroup)
      • Wait 1.00 seconds
      • Set SmokeGroup = (Units within 350.00 of SmokePoint matching ((((Matching unit) belongs to an ally of (Owner of (Last created unit))) Equal to False) and (((Matching unit) is alive) Equal to True)))
      • Unit Group - Pick every unit in SmokeGroup and do (Actions)
        • Loop - Actions
          • Unit - Cause (Last created unit) to damage (Picked unit), dealing SmokeDMG damage of attack type Spells and damage type Normal
      • Custom script: call DestroyGroup(udg_SmokeGroup)
      • Wait 1.00 seconds
      • Set SmokeGroup = (Units within 350.00 of SmokePoint matching ((((Matching unit) belongs to an ally of (Owner of (Last created unit))) Equal to False) and (((Matching unit) is alive) Equal to True)))
      • Unit Group - Pick every unit in SmokeGroup and do (Actions)
        • Loop - Actions
          • Unit - Cause (Last created unit) to damage (Picked unit), dealing SmokeDMG damage of attack type Spells and damage type Normal
      • Custom script: call DestroyGroup(udg_SmokeGroup)
      • Wait 1.00 seconds
      • Set SmokeGroup = (Units within 350.00 of SmokePoint matching ((((Matching unit) belongs to an ally of (Owner of (Last created unit))) Equal to False) and (((Matching unit) is alive) Equal to True)))
      • Unit Group - Pick every unit in SmokeGroup and do (Actions)
        • Loop - Actions
          • Unit - Cause (Last created unit) to damage (Picked unit), dealing SmokeDMG damage of attack type Spells and damage type Normal
      • Custom script: call DestroyGroup(udg_SmokeGroup)
      • Custom script: call RemoveLocation(udg_SmokePoint)
      • Custom script: set udg_Caster = null
      • Custom script: set udg_SmokePoint = null
 
Level 12
Joined
Jun 12, 2010
Messages
413
Se Pyrogasms post in this thread to see why this solution isn't good.

Try using:
  • Unit Group - Remove all units from SmokeGroup
Instead of:
  • Custom script: call DestroyGroup(udg_SmokeGroup)
If you destory the group, you have to create a new group every time you want to pick the units in range. It's easier to just clear the group instead. If you ever want to make SmokeGroup a local, you can just destroy it and null it at the end of the trigger. It doesn't need to be a local variable for the spell to be MUI, though.

But the spell is currently not MUI, since you are using Last Created Unit, and that variable (bj_lastCreatedUnit) changes every time a new instance of the spell is cast, since a new unit is created. Sure, the spell will still work, however, the unit dealing the damage will be the wrong one. If you don't mind that, I guess there is no issue.
 
Last edited:
Level 5
Joined
Dec 25, 2018
Messages
110
Try using:
  • Unit Group - Remove all units from SmokeGroup
Instead of:
  • Custom script: call DestroyGroup(udg_SmokeGroup)
If you destory the group, you have to create a new group every time you want to pick the units in range. It's easier to just clear the group instead. If you ever want to make SmokeGroup a local, you can just destroy it and null it at the end of the trigger. It doesn't need to be a local variable for the spell to be MUI, though.

But the spell is currently not MUI, since you are using Last Created Unit, and that variable (bj_lastCreatedUnit) changes every time a new instance of the spell is cast, since a new unit is created. Sure, the spell will still work, however, the unit dealing the damage will be the wrong one. If you don't mind that, I guess there is no issue.
Then should I make dummy a local unit too to make it MUI?
 
Level 12
Joined
Jun 12, 2010
Messages
413
So the only way to make it MUI is indexing?
For this simple application, I recommend you use a system like this:

[GUI-friendly] Timer System

If you want, I can show you what your spell would look like with that system.

PS: Using waits can be pretty bad, since in a multiplayer game they have an innacuracy of like, 10%-20% for 1-second waits, iirc. They also don't stop when the game is paused, so one could pause the game for 6 seconds and deal all the damage instantaneously.

PSS: If you still want to use waits, you can do something like this:
- Save (Last Created Unit) to a local variable (localUnit).
- Create a new global variable (UNIT)
- Whenever you are about to deal damage: Set UNIT = localUnit
- In the For Group loop actions, use UNIT instead of (Last Created Unit)

Please keep in mind though, that dealing damage generates an Event. So if you use a Damage Detection System and you use this global UNIT variable in any other trigger, there is a chance that the actions fired by the damage event will change the value of the global UNIT variable.
 
Last edited:
Level 5
Joined
Dec 25, 2018
Messages
110
For this simple application, I recommend you use a system like this:

[GUI-friendly] Timer System

If you want, I can show you what your spell would look like with that system.

PS: Using waits can be pretty bad, since in a multiplayer game they have an innacuracy of like, 10%-20% for 1-second waits, iirc. They also don't stop when the game is paused, so one could pause the game for 6 seconds and deal all the damage instantaneously.
If you could I would be thankful, only way I could do it is by indexing but I also have an idea to spawn dummy, set its base damage to lvlofability+Agi of caster do periodic event every 1 sec and order dummy to attack every unit in group, am I overcomplicating this too much?
 
Level 12
Joined
Jun 12, 2010
Messages
413
  • Casting
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to TestAbility
    • Actions
      • Set GTS_TimeOut = 1.00
      • Set GTS_Trigger = Periodic <gen>
      • Trigger - Run GTS Main <gen> (checking conditions)
      • Hashtable - Save Handle Of(Triggering unit) as 0 of GTS_CustomValue in GTS_Hashtable
      • Hashtable - Save Handle Of(Target point of ability being cast) as 1 of GTS_CustomValue in GTS_Hashtable
  • Periodic
    • Events
    • Conditions
    • Actions
      • Set TempGroup = (Units within 350.00 of (Load 1 of GTS_CustomValue in GTS_Hashtable))
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Set TempUnit = (Load 0 of GTS_CustomValue in GTS_Hashtable)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Owner of TempUnit) is an ally of (Owner of (Picked unit))) Equal to False
              • ((Picked unit) is alive) Equal to True
            • Then - Actions
              • Set TempReal = ((40.00 x (Real((Level of TestAbility for TempUnit)))) + ((Real((Agility of TempUnit (Include bonuses)))) / 2.00))
              • Unit - Cause (Load 0 of GTS_CustomValue in GTS_Hashtable) to damage (Picked unit), dealing TempReal damage of attack type Spells and damage type Normal
              • Special Effect - Create a special effect attached to the overhead of (Picked unit) using Abilities\Spells\Other\AcidBomb\BottleMissile.mdl
              • Special Effect - Destroy (Last created special effect)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GTS_ExecutionCounter Equal to 6
        • Then - Actions
          • Set GTS_DestroyTimer = True
          • Custom script: call RemoveLocation(LoadLocationHandle(udg_GTS_Hashtable, udg_GTS_CustomValue, 1))
        • Else - Actions
If you could I would be thankful, only way I could do it is by indexing but I also have an idea to spawn dummy, set its base damage to lvlofability+Agi of caster do periodic event every 1 sec and order dummy to attack every unit in group, am I overcomplicating this too much?

Making the dummy attack the units in the group won't achieve anything over having the dummy damage them through a trigger, and its more complicated :S
 

Attachments

  • Ability Test.w3x
    23.5 KB · Views: 20
Level 5
Joined
Dec 25, 2018
Messages
110
  • Casting
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to TestAbility
    • Actions
      • Set GTS_TimeOut = 1.00
      • Set GTS_Trigger = Periodic <gen>
      • Trigger - Run GTS Main <gen> (checking conditions)
      • Hashtable - Save Handle Of(Triggering unit) as 0 of GTS_CustomValue in GTS_Hashtable
      • Hashtable - Save Handle Of(Target point of ability being cast) as 1 of GTS_CustomValue in GTS_Hashtable
  • Periodic
    • Events
    • Conditions
    • Actions
      • Set TempGroup = (Units within 350.00 of (Load 1 of GTS_CustomValue in GTS_Hashtable))
      • Unit Group - Pick every unit in TempGroup and do (Actions)
        • Loop - Actions
          • Set TempUnit = (Load 0 of GTS_CustomValue in GTS_Hashtable)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Owner of TempUnit) is an ally of (Owner of (Picked unit))) Equal to False
              • ((Picked unit) is alive) Equal to True
            • Then - Actions
              • Set TempReal = ((40.00 x (Real((Level of TestAbility for TempUnit)))) + ((Real((Agility of TempUnit (Include bonuses)))) / 2.00))
              • Unit - Cause (Load 0 of GTS_CustomValue in GTS_Hashtable) to damage (Picked unit), dealing TempReal damage of attack type Spells and damage type Normal
              • Special Effect - Create a special effect attached to the overhead of (Picked unit) using Abilities\Spells\Other\AcidBomb\BottleMissile.mdl
              • Special Effect - Destroy (Last created special effect)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • GTS_ExecutionCounter Equal to 6
        • Then - Actions
          • Set GTS_DestroyTimer = True
          • Custom script: call RemoveLocation(LoadLocationHandle(udg_GTS_Hashtable, udg_GTS_CustomValue, 1))
        • Else - Actions


Making the dummy attack the units in the group won't achieve anything over having the dummy damage them through a trigger, and its more complicated :S
Works like a charm so far, thanks a lot.
 
Level 39
Joined
Feb 27, 2007
Messages
5,010
Try using:
  • Unit Group - Remove all units from SmokeGroup
Instead of:
  • Custom script: call DestroyGroup(udg_SmokeGroup)
I see that the final solution in this thread doesn't use this method but as a followup to this suggestion to help the OP learn a little more: this change wouldn't have affected anything other than actually making you leak more groups. The Set SmokeGroup = (Units within 350.00 of SmokePoint matching ((((Matching unit) belongs to an ally of (Owner of (Last created unit))) Equal to False) and (((Matching unit) is alive) Equal to True))) line already creates a new group and assigns the variable to it every time (so it did need to be destroyed afterward).
 
Level 12
Joined
Jun 12, 2010
Messages
413
I see that the final solution in this thread doesn't use this method but as a followup to this suggestion to help the OP learn a little more: this change wouldn't have affected anything other than actually making you leak more groups. The Set SmokeGroup = (Units within 350.00 of SmokePoint matching ((((Matching unit) belongs to an ally of (Owner of (Last created unit))) Equal to False) and (((Matching unit) is alive) Equal to True))) line already creates a new group and assigns the variable to it every time (so it did need to be destroyed afterward).

Yeah that's true, it's been a while since I've used GUI. I forgot the reason I don't even use GUI enumerations is that they all leak a group handle by not nulling the local group they create. The reason the code in the OP wasn't working originally was probably due to Last Created Unit changing into a unit of an ally of the player.
 
Status
Not open for further replies.
Top