• 🏆 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] Clashing triggers

Status
Not open for further replies.
Level 21
Joined
Mar 29, 2020
Messages
1,237
Hey all,

I accidentally found a clash between two triggers in my map that should not be happening. each of these triggers should be instantaneous, but for some reason they seem to be overwriting the variables that I used for both.

the first one is the initialization trigger of a spell, that is otherwise working. by using messages I pinpointed where the spell is activating up to. normally it works all the way through, but after I kill a tree it only gives me the messages "activated", "unit X added", "group was empty". (there are more message checker things in the loop and none of them activate) this is that first trigger:

  • Carried init
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • (Ability being cast) Equal to Carried
    • Actions
      • Game - Display to (All players) the text: activated
      • Set ID = (Custom value of (Triggering unit))
      • Set TempPoint1 = (Position of (Triggering unit))
      • Set X[1] = (X of TempPoint1)
      • Set Y[1] = (Y of TempPoint1)
      • Set Z[1] = ((Position - Z of (Triggering unit)) + 60.00)
      • Set CarriedLevel[ID] = (0.30 + (0.20 x (Real((Level of Carried for (Triggering unit))))))
      • Unit Group - Remove all units from Temp_Group
      • Unit Group - Pick every unit in (Units within 600.00 of TempPoint1) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Picked unit) Not equal to (Triggering unit)
              • ((Picked unit) is A structure) Equal to False
              • ((Picked unit) is An Ancient) Equal to False
              • ((Picked unit) is Mechanical) Equal to False
              • ((Picked unit) is Magic Immune) Equal to False
              • ((Picked unit) is an illusion) Equal to False
              • ((Picked unit) is dead) Equal to False
              • (Supply used by (Picked unit)) Greater than 0
              • ((Picked unit) belongs to an ally of (Triggering player)) Equal to True
            • Then - Actions
              • Unit Group - Add (Picked unit) to Temp_Group
              • Game - Display to (All players) the text: ((Name of (Picked unit)) + added)
            • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Temp_Group is empty) Equal to True
        • Then - Actions
          • Custom script: call RemoveLocation (udg_TempPoint1)
          • Game - Display to (All players) the text: group was empty
        • Else - Actions
          • Game - Display to (All players) the text: initiated
          • Set TempInteger = (Number of units in Temp_Group)
          • Set CarriedFraction[ID] = (1.00 / (Real(TempInteger)))
          • Custom script: set udg_CarriedDummyGroup[udg_ID] = CreateGroup()
          • Unit Group - Pick every unit in Temp_Group and do (Actions)
            • Loop - Actions
              • Set TempPoint = (Position of (Picked unit))
              • Unit - Create 1 dummywinventory for (Triggering player) at TempPoint facing Default building facing degrees
              • Unit Group - Add (Last created unit) to CarriedDummyGroup[ID]
              • Set CV = (Custom value of (Last created unit))
              • Set X[2] = (X of TempPoint)
              • Set Y[2] = (Y of TempPoint)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • ((Picked unit) is A flying unit) Equal to True
                • Then - Actions
                  • Set Z[2] = ((Position - Z of (Picked unit)) + 250.00)
                • Else - Actions
                  • Set Z[2] = ((Position - Z of (Picked unit)) + 40.00)
              • Set CarriedTarget[CV] = (Picked unit)
              • Custom script: set udg_CarriedLightning[udg_CV] = AddLightningEx("SPLK", true , udg_X[1], udg_Y[1], udg_Z[1], udg_X[2], udg_Y[2], udg_Z[2])
              • Lightning - Change color of CarriedLightning[CV] to (1.00 0.00 1.00) with 0.30 alpha
              • Custom script: call RemoveLocation (udg_TempPoint)
          • Unit Group - Add (Triggering unit) to CarriedCasterGroup
          • Custom script: call RemoveLocation (udg_TempPoint1)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Carried periodic <gen> is on) Equal to False
            • Then - Actions
              • Trigger - Turn on Carried periodic <gen>
            • Else - Actions
the second trigger group is a tree death detector. also, this should be instantaneous as far as I can tell so I used my temporary variables, and for some reason it seems to be emptying Temp_group:

  • tree death setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Destructible - Pick every destructible in (Playable map area) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Destructible-type of (Picked destructible)) Equal to Summer Tree Wall
            • Then - Actions
              • Trigger - Add to treevision <gen> the event (Destructible - (Picked destructible) dies)
            • Else - Actions
  • treevision
    • Events
    • Conditions
    • Actions
      • Set TempPoint = (Position of (Dying destructible))
      • Set TempRegion = (Region centered at TempPoint with size (150.00, 150.00))
      • Set Temp_Group = (Units within 1401.00 of TempPoint matching ((Level of Artillery Range for (Matching unit)) Greater than 0))
      • Unit Group - Pick every unit in Temp_Group and do (Actions)
        • Loop - Actions
          • Visibility - Create an initially Enabled visibility modifier for (Owner of (Picked unit)) emitting Visibility across TempRegion
          • Visibility - Destroy (Last created visibility modifier)
      • Custom script: call RemoveLocation (udg_TempPoint)
      • Custom script: call DestroyGroup (udg_Temp_Group)
      • Custom script: call RemoveRect(udg_TempRegion)
any idea why these are (seemingly) clashing?
would be happy for any help. thanks!

Edit: oh, seeing it here kind of clarified it. the problem is that I am destroying Temp_Group instead of emptying it. right?

the more I think about it the more this confuses me - when I use temporary unit group like this - should I always be doing "set" and destroy, and never "add"? is my first trigger leaking a group even though I am essentially not creating one? any clarification on the matter would be blissful...
 
Last edited:
the problem is that I am destroying Temp_Group instead of emptying it. right?

Yes, that would be the main problem, in the treevision trigger.

Based on the first trigger, Temp_Group appears to be a static object, which conflicts with its' behavior in the treevision trigger, as a dynamic object.

So, a possible solution for the treevision trigger is to do the following:
  • treevision
    • Events
    • Conditions
    • Actions
      • Set TempPoint = (Position of (Dying destructible))
      • Set TempRegion = (Region centered at TempPoint with size (150.00, 150.00))
      • -------- Adding bj_wantDestroyGroup will destroy the group object below after a ForGroup call --------
      • -------- which in GUI is Pick every unit in group ad do (Loop - Actions) --------
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 1401.00 of TempPoint matching ((Level of Artillery Range for (Matching unit)) Greater than 0)) and do (Actions)
        • Loop - Actions
          • Visibility - Create an initially Enabled visibility modifier for (Owner of (Picked unit)) emitting Visibility across TempRegion
          • Visibility - Destroy (Last created visibility modifier)
      • Custom script: call RemoveLocation (udg_TempPoint)
      • Custom script: call RemoveRect(udg_TempRegion)
 
Level 21
Joined
Mar 29, 2020
Messages
1,237
Based on the first trigger, Temp_Group appears to be a static object, which conflicts with its' behavior in the treevision trigger, as a dynamic object.
where can I find out more about static and dynamic objects?

if i understand correctly - unit group variables should be either - created and destroyed, or added to and emptied, but doing both with the same variable makes problems. is that correct?
 
Last edited:
Level 13
Joined
May 10, 2009
Messages
868
if i understand correctly - unit group variables should be either - created and destroyed, or added to and emptied, but doing both with the same variable makes problems. is that correct?
Correct. Unless you waste your time storing the static object somewhere else and reassign it back to the variable after you're finished with dynamic way.

Regarding GUI unit group functions:
  • Set group = (Random X units from (Units in (Playable map area)))
  • Set group = (Units in (Playable map area))
  • Set group = (Units in (Playable map area) owned by Player X (?))
  • Set group = (Units in (Playable map area) matching ((?) Equal to True))
  • Set group = (Units within 512.00 of (Center of (Playable map area)))
  • Set group = (Units within 512.00 of (Center of (Playable map area)) matching ((?) Equal to True))
  • Set group = (Units owned by Player X (?))
  • Set group = (Units owned by Player X (?) of type unitType)
  • Set group = (Units owned by Player X (?) matching ((?) Equal to True))
  • Set group = (Units of type unitType)
  • Set group = (Units currently selected by Player X (?))
Assigning any of those to a temp group variable will make it dynamic; Each function creates and returns a new group object. That means if a group variable is already referencing another group object, and you assign any of those functions above to it, the old object becomes now a leak because you can't reference it anymore.

If you want to keep Temp_Group var as a constant group, don't assign any of those functions to it. You might as well declare a separate unit group variable and use it exclusively for Carried Unit trigger.
 
if i understand correctly - unit group variables should be either - created and destroyed, or added to and emptied, but doing both with the same variable makes problems. is that correct?

If not handled properly, it will cause problems.

Apologies for my laziness to post a link, but try the following keywords in the Tutorial Section:
  • Memory Leak
  • Unit Groups
 
Status
Not open for further replies.
Top