• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.
  • Vote for the theme of Hive's HD Modeling Contest #7! Click here to vote! - Please only vote if you plan on participating❗️

[Trigger] Trigger problem with recognizing units in region

Level 12
Joined
Jul 5, 2014
Messages
546
I've tried a number of things but I still don't know the issue of the trigger. Doesn't work with periodic time or separate conditions either.

  • Trigger
    • Events
      • Time - Elapsed game time is 0.01 seconds
    • Conditions
    • Actions
      • Trigger - Turn off (This trigger)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Peasant1 <gen> contains Reanimated Peasant 0273 <gen>) Equal to True) and ((Peasant2 <gen> contains Reanimated Peasant 0274 <gen>) Equal to True)
        • Then - Actions
          • Unit - Make Reanimated Peasant 0273 <gen> face 0.00 over 0.00 seconds
          • Unit - Make Reanimated Peasant 0274 <gen> face 90.00 over 0.00 seconds
          • Wait 0.50 seconds
          • Cinematic - Send transmission to (All players) from Reanimated Peasant 0273 <gen> blabla Modify duration: Set to 5.00 seconds and Don't wait
          • Wait 6.00 seconds
          • Cinematic - Send transmission to (All players) from Reanimated Peasant 0274 <gen> blabla Modify duration: Set to 2.00 seconds and Don't wait
        • Else - Actions
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
Delete this:
  • Trigger - Turn off (This trigger)
Delete the Conditions:
  • ((Peasant1 <gen> contains Reanimated Peasant 0273 <gen>) Equal to True) and ((Peasant2 <gen> contains Reanimated Peasant 0274 <gen>) Equal to True)
Then add a Text Message to the Then - Actions:
  • Then - Actions
    • Text Message - Display "It works!"
Also, make sure the trigger is Enabled/Initially On.
 
Level 12
Joined
Jul 5, 2014
Messages
546
Delete this:
  • Trigger - Turn off (This trigger)
Delete the Conditions:
  • ((Peasant1 <gen> contains Reanimated Peasant 0273 <gen>) Equal to True) and ((Peasant2 <gen> contains Reanimated Peasant 0274 <gen>) Equal to True)
Then add a Text Message to the Then - Actions:
  • Then - Actions
    • Text Message - Display "It works!"
Also, make sure the trigger is Enabled/Initially On.
It works without the condition. But I don't know what's the problem with the conditions. The two peasants are ordered to go to their location and when they're both in their region, it should go on.
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
But it didn't work even when I set a periodic check. The trigger should activate once the 2 units are inside.
Did you forget to delete the "Turn Off Trigger" action? That would turn it off after the first time it runs and prevent it from running again.

Maybe you meant to turn it off AFTER the two Peasants are within the Region. In that case, move it to the "Then - Actions" section.
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
Without turning off, won't the periodic event just keep repeating it while they're in their region? It should only go off once.
Think about the logic, Actions execute from top to bottom.

Your first Action says "Turn off this trigger".

Your second Action says "If the Peasants are in the Regions then proceed with blah blah blah".

The first Action is going to run regardless of the second Action. In other words, this trigger will only ever run once since you immediately turn it off.
 
Level 12
Joined
Jul 5, 2014
Messages
546
Think about the logic, Actions execute from top to bottom.

Your first Action says "Turn off this trigger".

Your second Action says "If the Peasants are in the Regions then proceed with blah blah blah".

The first Action is going to run regardless of the second Action. In other words, this trigger will only ever run once since you immediately turn it off.
Ah, thanks, periodic made it work when I put the turn off into the the "then" section. Doesn't periodic check bogs down the game though? My layman instinct says that checking every 0.5 second for over an hour can weigh things down.
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
Ah, thanks, periodic made it work when I put the turn off into the the "then" section. Doesn't periodic check bogs down the game though? My layman instinct says that checking every 0.5 second for over an hour can weigh things down.
The total amount of time spent running shouldn't matter, just make sure that the trigger doesn't have any memory leaks as those are what could pile up over time. (There are none as of now)

There's also the idea of having too many expensive processes happening at once. For example, say you have 100 triggers that all rely on "Periodic interval of 0.50 seconds", it might be worthwhile to space them out to happen at different intervals. Games often have "lag spikes", which are really dips in framerate, because the game is processing a ton of code all at once. IE: A gas station explodes in GTA and sends cars and debris flying everywhere. This lowers the framerate dramatically at first because lots of expensive physics calculations are all happening at once. It's quite literally a BOOM and that's the problem. If it was spaced out over time it could handle it better and have a smoother experience.

But anyway, this is a pretty cheap trigger. The "Is unit in Region" condition checks if the Peasant's X coordinate is >= the Region's minimum X coordinate and <= the Region's maximum X coordinate and does the same logic for the Y axis. So it's some simple math and doesn't need to create anything new.

Also, you could use a more Event based approach where you rely on "A unit Enters region" to determine if they're both inside. There's also "A unit Dies" to turn off the trigger if one of the two Peasants dies. Depending on how your map works, you may even want the trigger to be off by default and turn on when something important happens.
 
Last edited:
Level 12
Joined
Jul 5, 2014
Messages
546
The total amount of time shouldn't matter, just make sure it doesn't have memory leaks as those are what could pile up over time.

There's also the idea of having too many expensive processes happening all at once. For example say you have 100 triggers that all rely on "Periodic interval of 0.50 seconds", it'd be better to space them out to happen at different offsets. But this is a pretty cheap trigger since you're just comparing some X/Y values.

Also, you could use a more Event based approach where you rely on "A unit Enters region" to determine if they're both inside. There's also "A unit Dies" to turn off the trigger if one of the two Peasants dies.
You mean the periodic generates the trigger over and over as memory leak? I once accidentally use periodic instead of time elapsed for making a floating text and I was wondering why I lag so badly, lol.

You could try the Wait (for condition) action instead of an if/then to see if that helps

  • zzz.gif
    Wait until Region1 contains Unit1 Equal to True and Region2 contains Unit2 Equal to True, checking every 1.00 seconds
Ah, thanks, man! I somehow overlooked other wait options like this, that would solve some ducktape triggers.
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
You mean the periodic generates the trigger over and over as memory leak? I once accidentally use periodic instead of time elapsed for making a floating text and I was wondering why I lag so badly, lol.
I updated my last comment, I have a bad habit of sending my reply too early, then proofreading and fixing it up, and then coming back again to add more info...

But no, I meant that a trigger with a memory leak is far worse if you're running it periodically. The more times it runs then the more times the memory leak is created. You have to actually be creating memory leaks in your trigger for it to matter, though. For example, leaking a Point, Unit Group, Player Group, or Special Effect.

The reason your floating text trigger had "lag" was likely just an expensive task happening too frequently and not a memory leak problem.
 
Level 12
Joined
Jul 5, 2014
Messages
546
I updated my last comment, I have a bad habit of sending my reply too early, then proofreading and fixing it up, and then coming back again to add more info...

But no, I meant that a trigger with a memory leak is far worse if you're running it periodically. The more times it runs then the more times the memory leak is created. You have to actually be creating memory leaks in your trigger for it to matter, though. For example, leaking a Point, Unit Group, Player Group, or Special Effect.

The reason your floating text trigger had "lag" was likely not due to memory leaks and more so just an expensive task happening too frequently.
Oh, got it. Yeah, that would be nasty but fortunately, I rarely use periodic events. Loosely related question to leak: does bj_wantdestroygroup = true immediately destroys group once the "pick all and do this" action performed? I just noticed a bunch of groups without variables and wonder if that would save me the effort to put them into variables.
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
Oh, got it. Yeah, that would be nasty but fortunately, I rarely use periodic events.
Note that there's nothing wrong with Periodic events, so don't leave with that idea. You just need to stay on top of expensive tasks/memory leaks.

Loosely related question to leak: does bj_wantdestroygroup = true immediately destroys group once the "pick all and do this" action performed? I just noticed a bunch of groups without variables and wonder if that would save me the effort to put them into variables.
Yes, bj_wantDestroyGroup tells the next Unit Group to "destroy itself" once it's done running all of it's actions. It's safe to use in most cases but do be careful with it, it will quite literally destroy the NEXT Unit Group that runs, wherever or whenever that may be. You shouldn't experience any issues assuming that you immediately follow it up with the actual Unit Group that you want destroyed.
 
Last edited:
Level 12
Joined
Jul 5, 2014
Messages
546
Note that there's nothing wrong with Periodic events, so don't leave with that idea. You just need to stay on top of expensive tasks/memory leaks.


Yes, bj_wantDestroyGroup alerts the very next Unit Group to be destroyed once it's done running all of it's actions. It's safe to use in most cases but do be careful with it, it will quite literally destroy the NEXT Unit Group, wherever or whenever that may be. You shouldn't run into any issues assuming that you immediately follow it up with the actual Unit Group that you want destroyed.
So in this example trigger, the second group trigger would not work, right? Because the group is already destroyed.

  • Untitled Trigger 001
    • Events
    • Conditions
    • Actions
      • Custom script: bj_wantdestroygroup = true
      • Unit Group - Pick every unit in (Sleepers) and do (Actions)
        • Loop - Actions
          • Unit - Pause (Picked unit)
      • Environment - Set sky to None
      • Wait 2.00 seconds
      • Item - Create Tome of Experience at (Center of (Playable map area))
      • Unit Group - Pick every unit in (Sleepers) and do (Actions)
        • Loop - Actions
          • Unit - Wake up (Picked unit)
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
If (Sleepers) was a Unit Group variable that you had created yourself beforehand it would be destroyed and unusable after the Wait.

For example, the second Pick Every Unit In Unit Group wouldn't work here:
  • THIS IS BAD
    • Events
    • Conditions
    • Actions
      • Set Variable Sleepers = (Units in playable map area matching (Matching unit) is Sleeping Equal to True)
      • Custom script: bj_wantdestroygroup = true
      • Unit Group - Pick every unit in Sleepers and do (Actions)
        • Loop - Actions
          • Unit - Pause (Picked unit)
      • Wait 2.00 seconds
      • Unit Group - Pick every unit in Sleepers and do (Actions)
        • Loop - Actions
          • Unit - Wake up (Picked unit)
But something like this would be fine:
  • Actions
    • Custom script: bj_wantdestroygroup = true
    • Unit Group - Pick every unit in (Units in playable map area matching (Matching unit) is Sleeping Equal to True) and do (Actions)
      • Loop - Actions
        • Unit - Pause (Picked unit)
    • Wait 2.00 seconds
    • Unit Group - Pick every unit in (Units in playable map area matching (Matching unit) is Sleeping Equal to True) and do (Actions)
      • Loop - Actions
        • Unit - Wake up (Picked unit)
^ Both Unit Groups would work as expected.

Although, you would leak the second one since it never gets destroyed. This is because the game is creating a brand new Unit Group each time you don't provide your own.
 
Last edited:
Level 12
Joined
Jul 5, 2014
Messages
546
If (Sleepers) was a Unit Group variable that you had created yourself beforehand it would be destroyed and unusable after the Wait.

For example, the second Unit Group wouldn't work here:
  • THIS IS BAD
    • Events
    • Conditions
    • Actions
      • Set Variable Sleepers = (Units in playable map area matching (Matching unit) is Sleeping Equal to True)
      • Custom script: bj_wantdestroygroup = true
      • Unit Group - Pick every unit in Sleepers and do (Actions)
        • Loop - Actions
          • Unit - Pause (Picked unit)
      • Wait 2.00 seconds
      • Unit Group - Pick every unit in Sleepers and do (Actions)
        • Loop - Actions
          • Unit - Wake up (Picked unit)
But something like this would be fine:
  • Actions
    • Custom script: bj_wantdestroygroup = true
    • Unit Group - Pick every unit in (Units in playable map area matching (Matching unit) is Sleeping Equal to True) and do (Actions)
      • Loop - Actions
        • Unit - Pause (Picked unit)
    • Wait 2.00 seconds
    • Unit Group - Pick every unit in (Units in playable map area matching (Matching unit) is Sleeping Equal to True) and do (Actions)
      • Loop - Actions
        • Unit - Wake up (Picked unit)
^ Both Unit Groups would work as expected.

Although, you would leak the second one since it never gets destroyed. This is because the game is creating a brand new Unit Group each time you don't provide your own.
So, if I understand correctly, "bj_wantdestroygroup = true" is for groups without variables while "call DestroyGroup(udg_Groupname)" is for variable groups.
 

Uncle

Warcraft Moderator
Level 71
Joined
Aug 10, 2018
Messages
7,600
So, if I understand correctly, "bj_wantdestroygroup = true" is for groups without variables while "call DestroyGroup(udg_Groupname)" is for variable groups.
They both achieve the same goal, to clear a Unit Group memory leak.

The "bj_" informs the next Unit Group to destroy itself.

Alternatively, if you have a reference to the Unit Group in your own variable then you can use "call DestroyGroup(my variable name)".

You have to use one or the other to avoid the memory leak.
 
Top