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

1 unit in more than 1 unit group?

Status
Not open for further replies.
Level 3
Joined
Jan 7, 2010
Messages
37
I created a trigger based Shockwave.

The Shockwave works fine the first time. But from the second cast on, it will hit a single target everytime the periodic trigger runs.
So far I figgured out, the "target unit" is put in the "Wave_TargetGroup[1]", but never in "Wave_TargetGroup[2,3,4,...]" when hit from another wave.


Am I correct assuming a unit can only be in 1 unit group at a time?
And how to solve this?


  • Unit Group - Pick every unit in (Units within Wave_Projectile_Size of Wave_Point_Origin[Wave_CustomValue]) and do (Actions)
    • Loop - Actions
      • -------- if the unit has already been damaged, IGNORE THIS UNIT --------
      • -------- else.... --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Picked unit) is in Wave_TargetGroup[Wave_CustomValue]) Equal to False
        • Then - Actions
          • -------- add unit to TARGET GROUP and then apply DMG --------
          • Unit Group - Add (Picked unit) to Wave_TargetGroup[Wave_CustomValue]
          • Unit - Cause Wave_Caster[Wave_CustomValue] to damage (Picked unit), dealing Wave_DMG damage of attack type Spells and damage type Normal
        • Else - Actions
          • Do nothing
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
can u post ur whole spell plz. also if im correct im guessing ur using unit groups to pick and deal damage which isnt good to do. also did u set the array index in the variable editor to more than one for the unit groups ? you should instead index the units using arrays. you shouldnt use groups for spells unless absolutely needed. check out my tutorial there is a chapter in there that shows u how to index http://www.hiveworkshop.com/forums/tutorial-submission-283/things-gui-user-should-know-233242/

if u have any questions feel free to ask
 
Level 18
Joined
May 11, 2012
Messages
2,103
I also had this problem.
So I just created new trigger with event: a unit comes within *** range of your dummy shockwave.
No problem since then. Not sure if this helped you or not, but that how I did it without any unit groups and shit...
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
The issue is that the group is not created for indexes higher than 1. Indexes upto the initial size of the array are created at map initialization. That is why indexes 0 and 1 work, but not 2, 3, 4 etc. You need to create the groups.

Example:
  • Custom script : set udg_Wave_TargetGroup[2] = CreateGroup()
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
Post your whole triggers... There could be any number of causes.

As a rough guess, a lack of understanding with GUI and group leaks has resulted in you destroying a group after the first cast but your GUI dependence means you never create the group again on subsequent casts. This means that it tries to add and test the unit with a null group.

The flow the group in the ability instances should have is as follows.
Initialize -> get a clean group, either creating one or using a recycled one (green coding).
Duration -> if a nearby unit is not in the group, add it to the group and deal damage.
End -> destroy or recycle group. Remember to clear group if recycling.

In GUI, the global array may already be initialized with size number of empty groups. You clearly do not want this as the groups should only exist in the spell system as long as there are instances of the ability. As a size of 0 is illegal, you need to check if an index already contains a group, and if it does then do not create or fetch one for that index (otherwise you will leak a group). At the end of the instance you need to destroy or recycle the group and set the index value to null (the null is to avoid bugs or leaks even if not strictly nescescary). Welcome to the pain of WC3 GUI.
 
Level 3
Joined
Jan 7, 2010
Messages
37
can u post ur whole spell plz. also if im correct im guessing ur using unit groups to pick and deal damage which isnt good to do. also did u set the array index in the variable editor to more than one for the unit groups ? you should instead index the units using arrays. you shouldnt use groups for spells unless absolutely needed. check out my tutorial there is a chapter in there that shows u how to index http://www.hiveworkshop.com/forums/tutorial-submission-283/things-gui-user-should-know-233242/

if u have any questions feel free to ask

yes, I do use unit groups that way.
and yes, the array index gets updated every instance.

I just checked out your index tutorial, nice stuff! I will see what I can do, but for now my brain is melting :D

here's the spell so far:


  • Shockwave
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to TESTWAVE
    • Actions
      • -------- -------- --------
      • -------- allow multiple instances --------
      • -------- -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Wave_CustomValue Less than 1000
        • Then - Actions
          • Set Wave_CustomValue = (Wave_CustomValue + 1)
        • Else - Actions
          • Set Wave_CustomValue = 1
      • -------- -------- --------
      • -------- set CASTER and its current POSITION --------
      • -------- -------- --------
      • Set Wave_Caster[Wave_CustomValue] = (Triggering unit)
      • Set Temp_Point = (Position of Wave_Caster[Wave_CustomValue])
      • -------- -------- --------
      • -------- set spell ANGLE (moving direction) --------
      • -------- -------- --------
      • Set Temp_Point2 = (Target point of ability being cast)
      • Set Wave_Moving_Angle[Wave_CustomValue] = (Angle from Temp_Point to Temp_Point2)
      • -------- -------- --------
      • -------- set the spell STARTING POINT and DESTINATION --------
      • -------- -------- --------
      • Set Wave_Point_Origin[Wave_CustomValue] = (Temp_Point offset by 250.00 towards Wave_Moving_Angle[Wave_CustomValue] degrees)
      • Set Wave_Point_Destination[Wave_CustomValue] = (Wave_Point_Origin[Wave_CustomValue] offset by Wave_Max_Range towards Wave_Moving_Angle[Wave_CustomValue] degrees)
      • -------- -------- --------
      • -------- create the DUMMY (includes the effect) --------
      • -------- setting it up and adding to DUMMY_GROUP --------
      • -------- -------- --------
      • Unit - Create 1 DUMMY SHOCKWAVE for (Owner of Wave_Caster[Wave_CustomValue]) at Wave_Point_Origin[Wave_CustomValue] facing Wave_Moving_Angle[Wave_CustomValue] degrees
      • Unit - Set the custom value of (Last created unit) to Wave_CustomValue
      • Unit Group - Add (Last created unit) to Wave_DummyGroup
      • Set Wave_Projectile[Wave_CustomValue] = (Last created unit)
      • -------- -------- --------
      • -------- sets the base periodic loops --------
      • -------- -------- --------
      • Set Wave_Repeats[Wave_CustomValue] = 0
      • -------- -------- --------
      • -------- clear LEAKS --------
      • -------- -------- --------
      • Custom script: call RemoveLocation (udg_Temp_Point)
      • Custom script: call RemoveLocation (udg_Temp_Point2)
      • -------- --------------------------------------------------------------- --------
      • -------- start periodic trigger --------
      • Trigger - Turn on Shockwave Periodic <gen>
  • Shockwave Periodic
    • Events
      • Time - Every 1.00 seconds of game time
    • Conditions
    • Actions
      • -------- ------- --------
      • -------- checks if a spell is still running --------
      • -------- if not ( no dummies left ) then turn off --------
      • -------- ------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in Wave_DummyGroup) Less than or equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
          • -------- ------- --------
          • -------- for each instance of this spell running, do... --------
          • -------- ------- --------
          • Unit Group - Pick every unit in Wave_DummyGroup and do (Actions)
            • Loop - Actions
              • -------- ------- --------
              • -------- set the custom value --------
              • -------- ------- --------
              • Set Wave_CustomValue = (Custom value of (Picked unit))
              • -------- ------- --------
              • -------- checks if the unit has still distance to go --------
              • -------- 32 times 25.00 = 800 --------
              • -------- if less then 32: the unit hasn't reached its destination --------
              • -------- ------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Wave_Repeats[Wave_CustomValue] Less than or equal to 32
                • Then - Actions
                  • -------- ------- --------
                  • -------- sets the NEW POINT and clears the old ones --------
                  • -------- ------- --------
                  • Set Temp_Point = Wave_Point_Origin[Wave_CustomValue]
                  • Custom script: call RemoveLocation (udg_Wave_Point_Origin[udg_Wave_CustomValue])
                  • Set Wave_Point_Origin[Wave_CustomValue] = (Temp_Point offset by 25.00 towards Wave_Moving_Angle[Wave_CustomValue] degrees)
                  • Custom script: call RemoveLocation (udg_Temp_Point)
                  • -------- ------- --------
                  • -------- moves the projectile forward --------
                  • -------- ------- --------
                  • Unit - Move Wave_Projectile[Wave_CustomValue] instantly to Wave_Point_Origin[Wave_CustomValue]
                  • -------- ------- --------
                  • -------- the projectile has moved ONE, so the REPEAT COUNTER --------
                  • -------- gets increased --------
                  • -------- ------- --------
                  • Set Wave_Repeats[Wave_CustomValue] = (Wave_Repeats[Wave_CustomValue] + 1)
                  • -------- ------- --------
                  • -------- DAMAGE HERE --------
                  • -------- picks all units withing range of the projectile --------
                  • -------- to determine if they get damaged --------
                  • -------- clear leak instantly --------
                  • -------- ------- --------
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within Wave_Projectile_Size of Wave_Point_Origin[Wave_CustomValue]) and do (Actions)
                    • Loop - Actions
                      • -------- ------- --------
                      • -------- if the unit has already been damaged, IGNORE THIS UNIT --------
                      • -------- else.... --------
                      • -------- ------- --------
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • ((Picked unit) is in Wave_TargetGroup[Wave_CustomValue]) Equal to False
                        • Then - Actions
                          • -------- ------- --------
                          • -------- add unit to TARGET GROUP and then apply DMG --------
                          • -------- ------- --------
                          • Unit Group - Add (Picked unit) to Wave_TargetGroup[Wave_CustomValue]
                          • Unit - Cause Wave_Caster[Wave_CustomValue] to damage (Picked unit), dealing Wave_DMG damage of attack type Spells and damage type Normal
                        • Else - Actions
                • Else - Actions
                  • -------- ------- --------
                  • -------- projectile reached its destination --------
                  • -------- clear leaks --------
                  • -------- ------- --------
                  • Custom script: call RemoveLocation (udg_Wave_Point_Destination[udg_Wave_CustomValue])
                  • Custom script: call RemoveLocation (udg_Wave_Point_Origin[udg_Wave_CustomValue])
                  • Unit Group - Remove all units from Wave_TargetGroup[Wave_CustomValue]
                  • -------- ------- --------
                  • -------- and remove projectile --------
                  • -------- ------- --------
                  • Unit Group - Remove Wave_Projectile[Wave_CustomValue] from Wave_DummyGroup
                  • Unit - Remove Wave_Projectile[Wave_CustomValue] from the game
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
ur problem is as expected.
  • Unit Group - Add (Picked unit) to Wave_TargetGroup[Wave_CustomValue]
also u dont lower the indexing value u use so u will eventually run out of indexes and spell will crash

u should switch it so it doesnt use groups, as per my tutorial.
this will solve the problem with the groups. also make sure u de-index things otherwise ur spells will all crash. already said but this is very important
 
Level 29
Joined
Oct 24, 2012
Messages
6,543
Groups are one of the most efficient ways to check if a unit has been seen or not as far as I am aware.

The problem is as we described, you are using a null group to check and add units to.

in spells i rather an array than a group loop. array with integer loop is faster. also since ur indexing you need to de-index which is a lot easier than using a group. and multiple groups for every instance of the spell is very inefficient. (never tested this b4, just going by the code i see generated.)
 
Level 3
Joined
Jan 7, 2010
Messages
37
Thanks guys! The problem is SOLVED. The spell is working as intended.
I think only adding this line below in the set up trigger was enough to get it going.

  • Custom script: set udg_Wave_TargetGroup[udg_Wave_CustomValue] = CreateGroup()

But I have one more question regarding leaks: as far as I know do dynamic locations (point with offset) create 2 leaks if not handled.
In my periodic trigger I have these lines:

  • Set Temp_Point = Wave_Point_Origin[Wave_CustomValue]
  • Custom script: call RemoveLocation (udg_Wave_Point_Origin[udg_Wave_CustomValue])
  • Set Wave_Point_Origin[Wave_CustomValue] = (Temp_Point offset by 25.00 towards Wave_Moving_Angle[Wave_CustomValue] degrees)
  • Custom script: call RemoveLocation (udg_Temp_Point)
Where the following line is deactivated, because it will crash the spell, setting Wave_Point_Origin to (0,0).

  • Custom script: call RemoveLocation (udg_Wave_Point_Origin[udg_Wave_CustomValue])
My intend is to clear the "old" Wave_Point_Origin[x] and set its position by 25 units further from what it was before. But when I clear Wave_Point_Origin[x] and then set it to "= Temp_Point+25" it breaks.

My thought was, that by having Temp_Point refer to Wave_Point_Origin, and then clearing Wave_Point_Origin, Temp_Point will refer to null/nothing/(0,0), because Wave_Point_Origin is empty/null. So, I'm not sure how to avoid this leak.


  • Shockwave
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to TESTWAVE
    • Actions
      • -------- -------- --------
      • -------- allow multiple instances --------
      • -------- -------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Wave_CustomValue Less than 100
        • Then - Actions
          • Set Wave_CustomValue = (Wave_CustomValue + 1)
        • Else - Actions
          • Set Wave_CustomValue = 1
      • -------- -------- --------
      • -------- set CASTER and its current POSITION --------
      • -------- -------- --------
      • Set Wave_Caster[Wave_CustomValue] = (Triggering unit)
      • Set Temp_Point = (Position of Wave_Caster[Wave_CustomValue])
      • -------- -------- --------
      • -------- set spell ANGLE (moving direction) --------
      • -------- -------- --------
      • Set Temp_Point2 = (Target point of ability being cast)
      • Set Wave_Moving_Angle[Wave_CustomValue] = (Angle from Temp_Point to Temp_Point2)
      • -------- -------- --------
      • -------- set the spell STARTING POINT and DESTINATION --------
      • -------- -------- --------
      • Set Wave_Point_Origin[Wave_CustomValue] = (Temp_Point offset by 128.00 towards Wave_Moving_Angle[Wave_CustomValue] degrees)
      • Set Wave_Point_Destination[Wave_CustomValue] = (Wave_Point_Origin[Wave_CustomValue] offset by Wave_Max_Range towards Wave_Moving_Angle[Wave_CustomValue] degrees)
      • -------- -------- --------
      • -------- create the DUMMY (includes the effect) --------
      • -------- setting it up and adding to DUMMY_GROUP --------
      • -------- -------- --------
      • Unit - Create 1 DUMMY SHOCKWAVE for (Owner of Wave_Caster[Wave_CustomValue]) at Wave_Point_Origin[Wave_CustomValue] facing Wave_Moving_Angle[Wave_CustomValue] degrees
      • Unit - Set the custom value of (Last created unit) to Wave_CustomValue
      • Unit Group - Add (Last created unit) to Wave_DummyGroup
      • Set Wave_Projectile[Wave_CustomValue] = (Last created unit)
      • -------- -------- --------
      • -------- sets the base periodic loops --------
      • -------- -------- --------
      • Set Wave_Repeats[Wave_CustomValue] = 0
      • -------- -------- --------
      • -------- create TargetGroup Array --------
      • -------- -------- --------
      • Custom script: set udg_Wave_TargetGroup[udg_Wave_CustomValue] = CreateGroup()
      • -------- -------- --------
      • -------- clear LEAKS --------
      • -------- -------- --------
      • Custom script: call RemoveLocation (udg_Temp_Point)
      • Custom script: call RemoveLocation (udg_Temp_Point2)
      • -------- --------------------------------------------------------------- --------
      • -------- start periodic trigger --------
      • Trigger - Turn on Shockwave Periodic Final <gen>
  • Shockwave Periodic
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • -------- ------- --------
      • -------- checks if a spell is still running --------
      • -------- if not ( no dummies left ) then turn off --------
      • -------- ------- --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in Wave_DummyGroup) Less than or equal to 0
        • Then - Actions
          • Trigger - Turn off (This trigger)
        • Else - Actions
          • -------- ------- --------
          • -------- for each instance of this spell running, do... --------
          • -------- ------- --------
          • Unit Group - Pick every unit in Wave_DummyGroup and do (Actions)
            • Loop - Actions
              • -------- ------- --------
              • -------- set the custom value --------
              • -------- ------- --------
              • Set Wave_CustomValue = (Custom value of (Picked unit))
              • -------- ------- --------
              • -------- checks if the unit has still distance to go --------
              • -------- 32 times 25.00 = 800 --------
              • -------- if less then 32: the unit hasn't reached its destination --------
              • -------- ------- --------
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Wave_Repeats[Wave_CustomValue] Less than or equal to 32
                • Then - Actions
                  • -------- ------- --------
                  • -------- sets the NEW POINT and clears the old ones --------
                  • -------- ------- --------
                  • Set Temp_Point = Wave_Point_Origin[Wave_CustomValue]
                  • Custom script: call RemoveLocation (udg_Wave_Point_Origin[udg_Wave_CustomValue])
                  • Set Wave_Point_Origin[Wave_CustomValue] = (Temp_Point offset by 25.00 towards Wave_Moving_Angle[Wave_CustomValue] degrees)
                  • Custom script: call RemoveLocation (udg_Temp_Point)
                  • -------- ------- --------
                  • -------- moves the projectile forward --------
                  • -------- ------- --------
                  • Unit - Move Wave_Projectile[Wave_CustomValue] instantly to Wave_Point_Origin[Wave_CustomValue]
                  • -------- ------- --------
                  • -------- the projectile has moved ONE, so the REPEAT COUNTER --------
                  • -------- gets increased --------
                  • -------- ------- --------
                  • Set Wave_Repeats[Wave_CustomValue] = (Wave_Repeats[Wave_CustomValue] + 1)
                  • -------- ------- --------
                  • -------- DAMAGE HERE --------
                  • -------- picks all units withing range of the projectile --------
                  • -------- to determine if they get damaged --------
                  • -------- clear leak instantly --------
                  • -------- ------- --------
                  • Custom script: set bj_wantDestroyGroup = true
                  • Unit Group - Pick every unit in (Units within Wave_Projectile_Size of Wave_Point_Origin[Wave_CustomValue]) and do (Actions)
                    • Loop - Actions
                      • -------- ------- --------
                      • -------- if the unit has already been damaged, IGNORE THIS UNIT --------
                      • -------- else.... --------
                      • -------- ------- --------
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • ((Picked unit) is in Wave_TargetGroup[Wave_CustomValue]) Equal to False
                        • Then - Actions
                          • -------- ------- --------
                          • -------- add unit to TARGET GROUP and then apply DMG --------
                          • -------- ------- --------
                          • Unit Group - Add (Picked unit) to Wave_TargetGroup[Wave_CustomValue]
                          • Unit - Cause Wave_Caster[Wave_CustomValue] to damage (Picked unit), dealing Wave_DMG damage of attack type Spells and damage type Normal
                        • Else - Actions
                • Else - Actions
                  • -------- ------- --------
                  • -------- projectile reached its destination --------
                  • -------- clear leaks --------
                  • -------- ------- --------
                  • Custom script: call RemoveLocation (udg_Wave_Point_Destination[udg_Wave_CustomValue])
                  • Custom script: call RemoveLocation (udg_Wave_Point_Origin[udg_Wave_CustomValue])
                  • Unit Group - Remove all units from Wave_TargetGroup[Wave_CustomValue]
                  • Custom script: call DestroyGroup (udg_Wave_TargetGroup[udg_Wave_CustomValue])
                  • -------- ------- --------
                  • -------- and remove projectile --------
                  • -------- ------- --------
                  • Unit Group - Remove Wave_Projectile[Wave_CustomValue] from Wave_DummyGroup
                  • Unit - Remove Wave_Projectile[Wave_CustomValue] from the game
 
Level 37
Joined
Mar 6, 2006
Messages
9,240

  • Set Temp_Point = Wave_Point_Origin[Wave_CustomValue]
  • Custom script: call RemoveLocation (udg_Wave_Point_Origin[udg_Wave_CustomValue])
  • Set Wave_Point_Origin[Wave_CustomValue] = (Temp_Point offset by 25.00 towards Wave_Moving_Angle[Wave_CustomValue] degrees)
  • Custom script: call RemoveLocation (udg_Temp_Point)

Temp_Point will be null when you try to set the offset point. Variables are pointers, they point to an object in memory.


  • Set Temp_Point = Wave_Point_Origin[Wave_CustomValue]
^Now both the variables point to the same object.


  • Custom script: call RemoveLocation (udg_Wave_Point_Origin[udg_Wave_CustomValue])
^Now you destroy the object from memory that the variable points to. Both the variables point to a null object now.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,202
in spells i rather an array than a group loop. array with integer loop is faster. also since ur indexing you need to de-index which is a lot easier than using a group. and multiple groups for every instance of the spell is very inefficient. (never tested this b4, just going by the code i see generated.)
I am pretty sure finding a unit in a group is faster than finding a unit in an array. Tests done on groups show they use some kind of hash system that is run natively. The JASS overhead of the array approach is so large it renders it not a viable alternative (1 native call VS JASS linear search).

Arrays are good when you want O(1) access of a specific unit. He wants to check if a unit has been seen before which clearly does not need that.
 
Level 3
Joined
Jan 7, 2010
Messages
37
Temp_Point will be null when you try to set the offset point. Variables are pointers, they point to an object in memory.


  • Set Temp_Point = Wave_Point_Origin[Wave_CustomValue]
^Now both the variables point to the same object.


  • Custom script: call RemoveLocation (udg_Wave_Point_Origin[udg_Wave_CustomValue])
^Now you destroy the object from memory that the variable points to. Both the variables point to a null object now.


I see. Thanks a lot!
 
Status
Not open for further replies.
Top