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

[Spell] Add Unit to Group not recognized

Status
Not open for further replies.
Level 12
Joined
May 16, 2020
Messages
660
Hi all,

I'm trying to create a projectile which deals damage 1x to enemies it passes through.

The basic idea is:
1) Unit Group: Pick every enemy within 100 of the projectile
2) IF: Picked unit is not in Group A (= my group of already damaged units)
3) THEN: Add Picked unit to Group A and cause damage etc...

This trigger does not work however, the enemies always get hit 2x. Attached an image of the trigger.

How can I fix this?

Activator:

  • Deadly Throw
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Deadly Throw
    • Actions
      • Set VariableSet DT_Counts = (DT_Counts + 1)
      • Set VariableSet DT_CountMaxSize = 8191
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DT_Counts Greater than DT_CountMaxSize
        • Then - Actions
          • Set VariableSet DT_Counts = 1
        • Else - Actions
      • Set VariableSet DT_Caster[DT_Counts] = (Casting unit)
      • Set VariableSet DT_CasterLoc = (Position of DT_Caster[DT_Counts])
      • Set VariableSet DT_TargetPoint = (Target point of ability being cast)
      • Set VariableSet DT_Angle = (Angle from DT_CasterLoc to DT_TargetPoint)
      • Unit - Create 1 Deadly Throw Projectile for (Owner of DT_Caster[DT_Counts]) at DT_CasterLoc facing DT_Angle degrees
      • Unit - Set the custom value of (Last created unit) to DT_Counts
      • Unit Group - Add (Last created unit) to DT_StartGroup
      • Set VariableSet DT_Distance[DT_Counts] = 1100.00
      • Set VariableSet DT_DistanceTravel[DT_Counts] = 0.00
      • Set VariableSet DT_StunDuration[DT_Counts] = 1
      • Set VariableSet DT_DistanceCount[DT_Counts] = 0.00
      • Trigger - Turn on Deadly Throw Projectile <gen>
      • Custom script: call RemoveLocation (udg_DT_CasterLoc)
      • Custom script: call RemoveLocation (udg_DT_TargetPoint)

Trigger which doesn't work correctly:

  • Deadly Throw Projectile
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in DT_StartGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet DT_CusValue = (Custom value of (Picked unit))
          • Set VariableSet DT_DummyLoc = (Position of (Picked unit))
          • Set VariableSet DT_Movement = (DT_DummyLoc offset by 50.00 towards (Facing of (Picked unit)) degrees.)
          • Unit - Move (Picked unit) instantly to DT_Movement
          • Set VariableSet DT_DistanceTravel[DT_CusValue] = (DT_DistanceTravel[DT_CusValue] + 45.00)
          • Set VariableSet DT_DistanceCount[DT_CusValue] = (DT_DistanceCount[DT_CusValue] + 45.00)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • DT_DistanceCount[DT_CusValue] Greater than or equal to 100.00
            • Then - Actions
              • Set VariableSet DT_StunDuration[DT_CusValue] = (DT_StunDuration[DT_CusValue] + 1)
              • Set VariableSet DT_DistanceCount[DT_CusValue] = 0.00
            • Else - Actions
          • Destructible - Pick every destructible within 100.00 of DT_Movement and do (Destructible - Kill (Picked destructible))
          • Set VariableSet DT_UnitGroup = (Units within 75.00 of DT_Movement.)
          • Unit Group - Pick every unit in DT_UnitGroup and do (Actions)
            • Loop - Actions
              • Set VariableSet DT_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DT_TempUnit is A structure) Equal to False
                  • (DT_TempUnit is alive) Equal to True
                  • (DT_TempUnit belongs to an enemy of (Owner of DT_Caster[DT_CusValue]).) Equal to True
                  • (DT_TempUnit has buff Slow (Deadly Throw)) Equal to False
                  • (DT_TempUnit is in DT_Damaged.) Equal to False
                • Then - Actions
                  • Unit Group - Add (Picked unit) to DT_Damaged
                  • Unit - Cause DT_Caster[DT_CusValue] to damage (Picked unit), dealing 25.00 damage of attack type Hero and damage type Normal
                  • Unit - Create 1 Universal Dummy for (Owner of DT_Caster[DT_CusValue]) at DT_Movement facing Default building facing degrees
                  • Set VariableSet DT_Dummy = (Last created unit)
                  • Unit - Add Deadly Throw Slow to DT_Dummy
                  • Unit - Order DT_Dummy to Human Sorceress - Slow (Picked unit)
                  • Unit - Add a 1.00 second Generic expiration timer to DT_Dummy
                • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • DT_DistanceTravel[DT_CusValue] Greater than or equal to DT_Distance[DT_CusValue]
            • Then - Actions
              • Unit - Kill (Picked unit)
              • Unit Group - Remove (Picked unit) from DT_StartGroup.
            • Else - Actions
          • Custom script: call RemoveLocation (udg_DT_DummyLoc)
          • Custom script: call RemoveLocation (udg_DT_Movement)
          • Custom script: call DestroyGroup (udg_DT_UnitGroup)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in DT_StartGroup) Equal to 0
        • Then - Actions
          • Unit - Remove Combos 1 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 2 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 3 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 4 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 5 from DT_Caster[DT_CusValue]
          • Custom script: call DestroyGroup(udg_DT_Damaged)
          • Set VariableSet ComboPointCounter = 0
          • Trigger - Turn off (This trigger)
        • Else - Actions

***
BTW: This guys had the same problem, but I don't understand how he solved it:
Unit Group - Add Unit
 

Attachments

  • Add Unit to Group.PNG
    Add Unit to Group.PNG
    91.7 KB · Views: 43
Last edited:
Level 20
Joined
Aug 13, 2013
Messages
1,696
Next time, use [trigger]<Paste>[/trigger] tags.
where you can use 'Copy As Text' by right-clicking the script name preceded by red flag 'Events',
And then replacing the <Paste> between the tags.

Make your container (DT_Damaged) a unit group array using the
custom value of projectile unit as an index then create and destroy each time.
However, unit group creation and destroy is not available in GUI functions
but achievable only via JASS within custom script action:

onCast where DT_CusValue variable has a value of projectile unit:
  • Custom Script: set udg_DT_Damaged[udg_DT_CusValue] = CreateGroup()
onPeriodic where you kill and remove the projectile unit in a group:
  • Custom Script: call DestroyGroup(udg_DT_Damaged[udg_DT_CusValue])
In this way, there's a unique container per projectile instead of making it a global container.
The downside of making it global is where you have multiple projectiles casted and only one projectile
can damage the picked unit at the same time which is obviously not intended.
 
Level 12
Joined
May 16, 2020
Messages
660
When you destroy the group, you can't add units to a group that doesn't exist anymore. You have to replace that customscript with "Clear group" instead.

I don't think that would fix the problem, as the group is only destroyed at a branch where the units are already damaged (which happens much later than the damage).


Next time, use [trigger]<Paste>[/trigger] tags.
where you can use 'Copy As Text' by right-clicking the script name preceded by red flag 'Events',
And then replacing the <Paste> between the tags.

Make your container (DT_Damaged) a unit group array using the
custom value of projectile unit as an index then create and destroy each time.
However, unit group creation and destroy is not available in GUI functions
but achievable only via JASS within custom script action:

onCast where DT_CusValue variable has a value of projectile unit:
  • Custom Script: set udg_DT_Damaged[udg_DT_CusValue] = CreateGroup()
onPeriodic where you kill and remove the projectile unit in a group:
  • Custom Script: call DestroyGroup(udg_DT_Damaged[udg_DT_CusValue])
In this way, there's a unique container per projectile instead of making it a global container.
The downside of making it global is where you have multiple projectiles casted and only one projectile
can damage the picked unit at the same time which is obviously not intended.

Thank you, added the trigger to the top message for completeness. I think I implemented your comment correctly, but it still doesn't work...

First trigger:

  • Deadly Throw
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Deadly Throw
    • Actions
      • Set VariableSet DT_Counts = (DT_Counts + 1)
      • Set VariableSet DT_CountMaxSize = 8191
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DT_Counts Greater than DT_CountMaxSize
        • Then - Actions
          • Set VariableSet DT_Counts = 1
        • Else - Actions
      • Set VariableSet DT_Caster[DT_Counts] = (Casting unit)
      • Set VariableSet DT_CasterLoc = (Position of DT_Caster[DT_Counts])
      • Set VariableSet DT_TargetPoint = (Target point of ability being cast)
      • Set VariableSet DT_Angle = (Angle from DT_CasterLoc to DT_TargetPoint)
      • Unit - Create 1 Deadly Throw Projectile for (Owner of DT_Caster[DT_Counts]) at DT_CasterLoc facing DT_Angle degrees
      • Unit - Set the custom value of (Last created unit) to DT_Counts
      • Unit Group - Add (Last created unit) to DT_StartGroup
      • Set VariableSet DT_Distance[DT_Counts] = 1100.00
      • Set VariableSet DT_DistanceTravel[DT_Counts] = 0.00
      • Set VariableSet DT_StunDuration[DT_Counts] = 1
      • Set VariableSet DT_DistanceCount[DT_Counts] = 0.00
      • Trigger - Turn on Deadly Throw Projectile <gen>
      • Custom script: call RemoveLocation (udg_DT_CasterLoc)
      • Custom script: call RemoveLocation (udg_DT_TargetPoint)

Second trigger (the one already posted):

  • Deadly Throw Projectile
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in DT_StartGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet DT_CusValue = (Custom value of (Picked unit))
          • Set VariableSet DT_DummyLoc = (Position of (Picked unit))
          • Set VariableSet DT_Movement = (DT_DummyLoc offset by 50.00 towards (Facing of (Picked unit)) degrees.)
          • Unit - Move (Picked unit) instantly to DT_Movement
          • Set VariableSet DT_DistanceTravel[DT_CusValue] = (DT_DistanceTravel[DT_CusValue] + 45.00)
          • Set VariableSet DT_DistanceCount[DT_CusValue] = (DT_DistanceCount[DT_CusValue] + 45.00)
          • Custom script: set udg_DT_Damaged[udg_DT_CusValue] = CreateGroup()
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • DT_DistanceCount[DT_CusValue] Greater than or equal to 100.00
            • Then - Actions
              • Set VariableSet DT_StunDuration[DT_CusValue] = (DT_StunDuration[DT_CusValue] + 1)
              • Set VariableSet DT_DistanceCount[DT_CusValue] = 0.00
            • Else - Actions
          • Destructible - Pick every destructible within 100.00 of DT_Movement and do (Destructible - Kill (Picked destructible))
          • Set VariableSet DT_UnitGroup = (Units within 75.00 of DT_Movement.)
          • Unit Group - Pick every unit in DT_UnitGroup and do (Actions)
            • Loop - Actions
              • Set VariableSet DT_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DT_TempUnit is A structure) Equal to False
                  • (DT_TempUnit is alive) Equal to True
                  • (DT_TempUnit belongs to an enemy of (Owner of DT_Caster[DT_CusValue]).) Equal to True
                  • (DT_TempUnit has buff Slow (Deadly Throw)) Equal to False
                  • (DT_TempUnit is in DT_Damaged[DT_CusValue].) Equal to False
                • Then - Actions
                  • Unit Group - Add (Picked unit) to DT_Damaged[DT_CusValue]
                  • Unit - Cause DT_Caster[DT_CusValue] to damage (Picked unit), dealing 25.00 damage of attack type Hero and damage type Normal
                  • Unit - Create 1 Universal Dummy for (Owner of DT_Caster[DT_CusValue]) at DT_Movement facing Default building facing degrees
                  • Set VariableSet DT_Dummy = (Last created unit)
                  • Unit - Add Deadly Throw Slow to DT_Dummy
                  • Unit - Order DT_Dummy to Human Sorceress - Slow (Picked unit)
                  • Unit - Add a 1.00 second Generic expiration timer to DT_Dummy
                • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • DT_DistanceTravel[DT_CusValue] Greater than or equal to DT_Distance[DT_CusValue]
            • Then - Actions
              • Unit - Kill (Picked unit)
              • Unit Group - Remove (Picked unit) from DT_StartGroup.
              • Custom script: call DestroyGroup(udg_DT_Damaged[udg_DT_CusValue])
            • Else - Actions
          • Custom script: call RemoveLocation (udg_DT_DummyLoc)
          • Custom script: call RemoveLocation (udg_DT_Movement)
          • Custom script: call DestroyGroup (udg_DT_UnitGroup)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in DT_StartGroup) Equal to 0
        • Then - Actions
          • Unit - Remove Combos 1 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 2 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 3 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 4 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 5 from DT_Caster[DT_CusValue]
          • Set VariableSet ComboPointCounter = 0
          • Trigger - Turn off (This trigger)
        • Else - Actions
 
Level 20
Joined
Aug 13, 2013
Messages
1,696
I think I implemented your comment correctly, but it still doesn't work...
  • Custom script: set udg_DT_Damaged[udg_DT_CusValue] = CreateGroup()
should be in the 'Deadly Throw' so it will be:
  • Custom script: set udg_DT_Damaged[udg_DT_Counts] = CreateGroup()
EDIT:

You might want to check this out to make things easier...
GUI Unit Indexer 1.4.0.0 already handles the indexing and recycling a custom value for a unit.
 
Last edited:
Level 12
Joined
May 16, 2020
Messages
660
  • Custom script: set udg_DT_Damaged[udg_DT_CusValue] = CreateGroup()
should be in the 'Deadly Throw' so it will be:
  • Custom script: set udg_DT_Damaged[udg_DT_Counts] = CreateGroup()
EDIT:

You might want to check this out to make things easier...
GUI Unit Indexer 1.4.0.0 already handles the indexing and recycling a custom value for a unit.

Still doesn't work :-( (~50 damage instead of 25)

Edit: And thanks for the link. I think I get the idea, but I want to first solve this before I try to rebuild it with another system.


  • Deadly Throw Projectile
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in DT_StartGroup and do (Actions)
        • Loop - Actions
          • Set VariableSet DT_CusValue = (Custom value of (Picked unit))
          • Set VariableSet DT_DummyLoc = (Position of (Picked unit))
          • Set VariableSet DT_Movement = (DT_DummyLoc offset by 50.00 towards (Facing of (Picked unit)) degrees.)
          • Unit - Move (Picked unit) instantly to DT_Movement
          • Set VariableSet DT_DistanceTravel[DT_CusValue] = (DT_DistanceTravel[DT_CusValue] + 45.00)
          • Set VariableSet DT_DistanceCount[DT_CusValue] = (DT_DistanceCount[DT_CusValue] + 45.00)
          • Custom script: set udg_DT_Damaged[udg_DT_Counts] = CreateGroup()
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • DT_DistanceCount[DT_CusValue] Greater than or equal to 100.00
            • Then - Actions
              • Set VariableSet DT_StunDuration[DT_CusValue] = (DT_StunDuration[DT_CusValue] + 1)
              • Set VariableSet DT_DistanceCount[DT_CusValue] = 0.00
            • Else - Actions
          • Destructible - Pick every destructible within 100.00 of DT_Movement and do (Destructible - Kill (Picked destructible))
          • Set VariableSet DT_UnitGroup = (Units within 75.00 of DT_Movement.)
          • Unit Group - Pick every unit in DT_UnitGroup and do (Actions)
            • Loop - Actions
              • Set VariableSet DT_TempUnit = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (DT_TempUnit is A structure) Equal to False
                  • (DT_TempUnit is alive) Equal to True
                  • (DT_TempUnit belongs to an enemy of (Owner of DT_Caster[DT_CusValue]).) Equal to True
                  • (DT_TempUnit has buff Slow (Deadly Throw)) Equal to False
                  • (DT_TempUnit is in DT_Damaged[DT_Counts].) Equal to False
                • Then - Actions
                  • Unit Group - Add (Picked unit) to DT_Damaged[DT_Counts]
                  • Unit - Cause DT_Caster[DT_CusValue] to damage (Picked unit), dealing 25.00 damage of attack type Hero and damage type Normal
                  • Unit - Create 1 Universal Dummy for (Owner of DT_Caster[DT_CusValue]) at DT_Movement facing Default building facing degrees
                  • Set VariableSet DT_Dummy = (Last created unit)
                  • Unit - Add Deadly Throw Slow to DT_Dummy
                  • Unit - Order DT_Dummy to Human Sorceress - Slow (Picked unit)
                  • Unit - Add a 1.00 second Generic expiration timer to DT_Dummy
                • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • DT_DistanceTravel[DT_CusValue] Greater than or equal to DT_Distance[DT_CusValue]
            • Then - Actions
              • Unit - Kill (Picked unit)
              • Unit Group - Remove (Picked unit) from DT_StartGroup.
              • Custom script: call DestroyGroup(udg_DT_Damaged[udg_DT_Counts])
            • Else - Actions
          • Custom script: call RemoveLocation (udg_DT_DummyLoc)
          • Custom script: call RemoveLocation (udg_DT_Movement)
          • Custom script: call DestroyGroup (udg_DT_UnitGroup)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in DT_StartGroup) Equal to 0
        • Then - Actions
          • Unit - Remove Combos 1 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 2 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 3 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 4 from DT_Caster[DT_CusValue]
          • Unit - Remove Combos 5 from DT_Caster[DT_CusValue]
          • Set VariableSet ComboPointCounter = 0
          • Trigger - Turn off (This trigger)
        • Else - Actions
 
Level 20
Joined
Aug 13, 2013
Messages
1,696
You have 'Deadly Throw' named script which is what I refer to be 'onCast'.
You have 'Deadly Throw Projectile' named script which is what I refer to be 'onPeriodic'

Then:

onCast, this line should be present
  • Custom Script: set udg_DT_Damaged[udg_DT_Counts] = CreateGroup()
onPeriodic, this line should be removed
  • Custom script: set udg_DT_Damaged[udg_DT_Counts] = CreateGroup()
And use udg_DT_Damaged[udg_DT_CusValue] to refer instead.
I hope this is crystal-clear or else give me the demo map :xxd:
 
Level 12
Joined
May 16, 2020
Messages
660
Works! I think I did it correctly now (I attached it just to be sure, sorry quite big due to all the icons I imported).

And use udg_DT_Damaged[udg_DT_CusValue] to refer instead.

I don't understand why we do this. Initially we say to open a group with the array DT_Counts (and DT_Counts increases with every cast of the ability). So why not simply use DT_Counts to refer to groups in the projectile instead of CusValue?

(sorry arrays still very much confuse me)

If you look at the map: General observations what I'm doing wrong or things I could improve would be very much appreciated!
 
Level 20
Joined
Aug 13, 2013
Messages
1,696
I'm unable to open your map as I'm using a legacy version,
but glad to hear that it's now working... at least the problem is now solved.

I don't understand why we do this. Initially we say to open a group with the array DT_Counts (and DT_Counts increases with every cast of the ability). So why not simply use DT_Counts to refer to groups in the projectile instead of CusValue?
No, imagine this scenario:

3 projectiles are made onCast. each of their custom value
uniquely varies to DT_Counts so: projectile[1], projectile[2], projectile[3]

DT_Counts as statically increasing, its value would be 3.
If you refer that variable inside the unit group then it will always refer
to the group created of projectile[3] so in this case: udg_DT_Damaged[3] will only be considered.

This makes sense onCast,
  • Unit - Set the custom value of (Last created unit) to DT_Counts
  • Custom Script: set udg_DT_Damaged[udg_DT_Counts] = CreateGroup()
onPeriodic you refer that custom value by doing this,
  • Set VariableSet DT_CusValue = (Custom value of (Picked unit))
  • Custom script: call DestroyGroup(udg_DT_Damaged[udg_DT_CusValue])
Don't be confused with arrays, they are just an index of a variable.
 
Level 12
Joined
May 16, 2020
Messages
660
I'm unable to open your map as I'm using a legacy version,
but glad to hear that it's now working... at least the problem is now solved.


No, imagine this scenario:

3 projectiles are made onCast. each of their custom value
uniquely varies to DT_Counts so: projectile[1], projectile[2], projectile[3]

DT_Counts as statically increasing, its value would be 3.
If you refer that variable inside the unit group then it will always refer
to the group created of projectile[3] so in this case: udg_DT_Damaged[3] will only be considered.

This makes sense onCast,
  • Unit - Set the custom value of (Last created unit) to DT_Counts
  • Custom Script: set udg_DT_Damaged[udg_DT_Counts] = CreateGroup()
onPeriodic you refer that custom value by doing this,
  • Set VariableSet DT_CusValue = (Custom value of (Picked unit))
  • Custom script: call DestroyGroup(udg_DT_Damaged[udg_DT_CusValue])
Don't be confused with arrays, they are just an index of a variable.

Ahh got it, so the projectile[1] and projectile[2] would refer to [3] which can cause problems (same as the goal of making spells MUI guess). Thank you very much for the explanation and help with the trigger!
 
Status
Not open for further replies.
Top