• 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.

Help on making Triggers more Efficient

Status
Not open for further replies.
Level 7
Joined
Feb 13, 2022
Messages
87
Hello to all of the great people on Hive! I'm currently working on making my game run more smoothly and have fewer triggers in it. I feel like there has to be a way to make these triggers in my game into a single trigger opposed to the 32 triggers I have for this fairly simple mechanic in my game. Basically all I want the trigger/s to do in my game is to make it so that if any unit (of a specific criteria) comes into contact with the "Pacman" unit, that unit that has made contact dies. The concept is simple and it seems like an easy thing to trigger in Warcraft. The difficulty arises from certain restraints within my game. Here are all of the restraints:
1)All the units of the type Pac-Man start in the game hidden and are periodically unhidden throughout the game. They can't kill units while they are hidden or dead.
2)Second and final is that the Pac-Man units can only kill very specific unit types of their enemy force.
In my game currently to overcome these challenges and to have this mechanic work in my game I have it setup where there is a trigger for each pacman that turns on when each Pacman gets unhidden. Each trigger is basically identical and the only difference is they are each tied to their own Pacman. Please help me hive community! I need to basically make these many triggers into a single trigger. Thank you to all who help and read this! Any and all suggestions are appreciated
  • Pacman
    • Events
      • Unit - A unit comes within 145.00 of Pac-Man 0005 <gen>
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • ((Owner of (Triggering unit)) Not equal to Player 12 (Brown)) and (((Unit-type of (Triggering unit)) Not equal to Scout Tower) and (((Unit-type of (Triggering unit)) Not equal to Stun Trap) and (((Unit-type of (Triggering unit)) Not equal to DUMMY) and (((Unit-type of (Triggering unit)) Not equal to Slow Tower) and (((Unit-
          • (Pac-Man 0005 <gen> is alive) Equal to True
        • Then - Actions
          • Unit - Kill (Triggering unit)
        • Else - Actions
          • Do nothing
 

Attachments

  • Number of Triggers.png
    Number of Triggers.png
    51.4 KB · Views: 13
  • What the trigger does!.png
    What the trigger does!.png
    92.2 KB · Views: 11
Level 14
Joined
Jan 10, 2023
Messages
247
How about this: three Triggers.

  • PacmanInit
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units of type Pacman) and do (Actions)
        • Loop - Actions
          • Trigger - Add to PacmanKills <gen> the event (Unit - A unit comes within 145.00 of (Picked unit))
          • Trigger - Add to PacmanDies <gen> the event (Unit - (Picked unit) Dies)
  • PacmanDies
    • Events
    • Conditions
    • Actions
      • Unit - Replace (Triggering unit) with a Pacman using The old unit's relative life and mana
  • PacmanKills
    • Events
    • Conditions
      • Or - Any (Conditions) are true
        • Conditions
          • (Unit-type of (Entering unit)) Equal to PacmanTarget1
          • (Unit-type of (Entering unit)) Equal to PacmanTarget2
          • (Unit-type of (Entering unit)) Equal to PacmanTarget3
    • Actions
      • Set VariableSet tmpLoc = (Position of (Entering unit))
      • Custom script: set bj_wantDestroyGroup = true
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in (Units within 145.00 of tmpLoc matching ((Unit-type of (Matching unit)) Equal to Footman).)) Greater than 0
        • Then - Actions
          • Unit - Kill (Entering unit)
        • Else - Actions
      • Custom script: call RemoveLocation( udg_tmpLoc )
  • UnhideTmpUnit
    • Events
    • Conditions
    • Actions
      • Set VariableSet tmpLoc = (Position of tmpUnit)
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 145.00 of tmpLoc.) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Or - Any (Conditions) are true
                • Conditions
                  • (Unit-type of (Picked unit)) Equal to PacmanTarget1
                  • (Unit-type of (Picked unit)) Equal to PacmanTarget2
                  • (Unit-type of (Picked unit)) Equal to PacmanTarget3
            • Then - Actions
              • Unit - Kill (Picked unit)
            • Else - Actions
      • Unit - Unhide tmpUnit
      • Unit - Order tmpUnit to Right-Click tmpLoc
      • Custom script: call RemoveLocation( udg_tmpLoc )
To unhide a Pacman use these actions:
  • Set VariableSet tmpUnit = (Target Pacman)
  • Trigger - Run UnhideTmpUnit <gen> (ignoring conditions)
  • Set VariableSet tmpUnit = No unit
Here's a description of what the trigger UnhideTmpUnit does:
  • When the Pacman is unhidden, if another unit is standing where the Pacman is standing, the Pacman will be bumped over. Solution:
    1. Check if there there are any units where Pacman is standing BEFORE unhiding Pacman, and kill them if they are Targets.
    2. If the Pacman is being blocked by some other unit that it shouldn't kill, then let the Pacman get bumped over.
  • Until the Pacman receives an order, it's location will not be registered for when a Pacman Target comes along. Solution:
    1. Set tmpLoc to the unhiding unit's location (tmpUnit's location).
    2. Order the unhiding unit to Right-Click (order("smart")) at tmpLoc.
      • Ordering the unit to Move, Stop didn't work in testing, and I wasn't sure if Pacman had an Attack, so I used Right-Click.

PacmanInit makes an event for each of the Pacmans, if you make a new Pacman later use these actions after creating it:
  • Trigger - Add to PacmanKills <gen> the event (Unit - A unit comes within 145.00 of (Last created unit))
  • Trigger - Add to PacmanDies <gen> the event (Unit - (Last created unit) Dies)
The reason for replacing a Pacman with a Pacman when it dies is that the new Pacman will not be added to the PacmanKills or PacmanDies trigger events, so when a unit walks over the corpse of a Pacman the unit will be safe, but this way the Pacman's death animation still plays.

EDIT: I made some changes to facilitate hidden Pacmans:
  • In the trigger PacmanKills:
    1. Added the Global Variable tmpLoc.
    2. Set tmpLoc to the position of the PacmanTarget.
    3. Use tmpUnit to check if there are any Pacmans in the same 145.00 range.
      • Hidden Pacmans will not be counted.
  • Added the Global Variable tmpUnit.
  • Added the trigger UnhideTmpUnit.
 
Last edited:

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
I would avoid that Event entirely and just handle it myself. This way you won't have to deal with any weirdness that comes with Event limits, dead units being permanently registered to the Event, and just weird Warcraft 3 behavior.

I think a better approach would be something like this:
  • Pacman Add
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Pacman
    • Actions
      • Unit Group - Add (Triggering unit) to Pacman_Source_Group
      • Trigger - Turn on Pacman Kill Loop <gen>
  • Pacman Remove
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Pacman
    • Actions
      • Unit Group - Remove (Triggering unit) from Pacman_Source_Group.
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in Pacman_Source_Group) Equal to 0
        • Then - Actions
          • Trigger - Turn off Pacman Kill Loop <gen>
        • Else - Actions
  • Pacman Kill Loop
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Pacman_Source_Group and do (Actions)
        • Loop - Actions
          • Set VariableSet Pacman_Source = (Picked unit)
          • Set VariableSet Pacman_Point = (Position of Pacman_Source)
          • Set VariableSet Pacman_Target_Group = (Units within 145.00 of Pacman_Point.)
          • Unit Group - Pick every unit in Pacman_Target_Group and do (Actions)
            • Loop - Actions
              • Set VariableSet Pacman_Target = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Level of Pacman Immunity (Hidden) for Pacman_Target) Equal to 0
                  • (Pacman_Target is alive) Equal to True
                  • (Owner of Pacman_Target) Not equal to Player 12 (Brown)
                • Then - Actions
                  • Unit - Kill Pacman_Target
                • Else - Actions
          • Custom script: call RemoveLocation( udg_Pacman_Point )
          • Custom script: call DestroyGroup( udg_Pacman_Target_Group )
Pacman_Immunity is an ability based on Storm Hammers. It acts as a classification that we can check in our Conditions to efficiently determine who is immune to Pacman's bloodthirsty ways. So you would give this ability to your Scout Towers and other Unit-types that are meant to be immune.

If some of your Pacman units are pre-placed on the map then you should Add them to Pacman_Source_Group at the start of the game:
  • Events
    • Time - Elapsed game time is 0.00 seconds
  • Conditions
  • Actions
    • Set VariableSet Pacman_Source_Group = (Units in playable map area matching (Unit-type of matching unit Equal to Pacman))
Pacman Kill Loop is designed to be Turned Off while no Pacman units are alive since it wouldn't be doing anything.
 

Attachments

  • Pacman 1.w3m
    18.7 KB · Views: 7
Last edited:
Level 14
Joined
Jan 10, 2023
Messages
247
I wasn't sure how fast making groups would be, or a periodic timer, but I suppose it's not an issue for speed then.
If it is still a matter of speed, I updated my suggestion, I'm not sure if it's faster.

@Uncle I'm a bit curious what you mean about "any weirdness that comes with Event limits - This is the method I've used to make triggers for tens of thousands of Destructables (whatever the default map limit is), and I never had a problem.. maybe I wasn't paying attention to the lag at the time?

Also, if the goal is to have Pacman only able to kill very specific targets, for my trigger it makes more sense to check if it is one of the targetable units, instead of all of the exceptions (the scout towers, et c.).
If going with Uncle's solution, it matters less I think/ not at all which way you slice it - the ability check is going to happen regardless, but for my solution it made more sense to check if the target one of the few targetable types instead of one of the many untargetable - to explain why I differed here.

One last thing, I'm not sure how important the "hidden Pacman" part of the request is, but if so, this would be a potential quick solution if you made this change to "Pacman Kill Loop":
  • Pacman Kill Loop
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Pacman_Source_Group and do (Actions)
        • Loop - Actions
          • Set VariableSet Pacman_Source = (Picked unit)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Pacman_Source is hidden) Equal to False
            • Then - Actions
              • Set VariableSet Pacman_Point = (Position of Pacman_Source)
              • Custom script: set bj_wantDestroyGroup = true
              • Unit Group - Pick every unit in (Units within 145.00 of Pacman_Point.) and do (Actions)
                • Loop - Actions
                  • Set VariableSet Pacman_Target = (Picked unit)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (Level of Pacman Immunity (Hidden) for Pacman_Target) Equal to 0
                      • (Pacman_Target is alive) Equal to True
                      • (Owner of Pacman_Target) Not equal to Player 12 (Brown)
                    • Then - Actions
                      • Unit - Kill Pacman_Target
                    • Else - Actions
              • Custom script: call RemoveLocation( udg_Pacman_Point )
            • Else - Actions

In addition to this, I'm now wondering how "Pacman Kill Loop" would work when the unit is unhidden. Would it need to have its location refreshed after being unhidden?
Your trigger is different enough that I wasn't sure, since I used TriggerRegisterUnitInRange at times but yours uses unit groups exclusively to find units in range.
I'm more curious for personal reasons at this point, I think yours is simpler at this point unless the hidden units became a problem somehow, but I think the suggestion I made to it solves that anyway, unless the unhidden unit does need to be given an order or something to refresh it.
(hopefully I explained that well enough).

Not sure if there's a reason to have a target group, but I figured I'd instead use the bj_wantDestroyGroup method as a plug to ask if it's just a preferential thing or if there is a reason (I get it if it's a simplicity thing).

Also, I updated my previous reply because I was already emotionally invested lol
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
I don't trust Warcraft 3's Events to all play the same way since this game likes to be inconsistent. Also, I'm unsure of how "A unit comes within range" is handled behind the scenes so I'd prefer an approach that I have full control over and do understand. It could be more efficient to use the "within Range" Event, I really can't say for certain. I do know that dead Pacman units will basically become memory leaks since their "within range" Events will never be unregistered from the trigger. With enough new Pacmen/dead Pacmen the trigger could become rather bloated and inefficient (and maybe reach some kind of limit?). But that could also be such a miniscule problem that it's not worth worrying about.

Regarding the Conditions, since there's like 4 Unit-Types to check I think it makes the most sense to just give those 4 Unit-types something in common that you can check for once. That's why I use an ability to create what's essentially a custom Unit classification. That shrinks your Condition count down from N where N is the number of different Unit-types to 1. Another neat bonus of the ability is that you can temporarily Remove it or change it's level to "unimmune" a unit, giving you some extra control over when something can and can't die.

Regarding the Unit Group, I prefer to use a variable over bj_wantDestroyGroup because there are cases where bj_ can fail or cause problems. I forget what those cases are, and perhaps it's just superstition from reading misinformation/outdated info in the past, but since I can't remember I prefer to stick with what I know works. It's also just a habit :p
 
Last edited:
Level 14
Joined
Jan 10, 2023
Messages
247
I don't trust Warcraft 3's Events to all play the same way since this game likes to be inconsistent. Also, I'm unsure of how "A unit comes within range" is handled behind the scenes so I'd prefer an approach that I have full control over and do understand.
Makes total sense, I know that feeling, in this case I knew to little to have a preference.

I do know that dead Pacman units will basically become memory leaks since their "within range" Events will never be unregistered from the trigger.
I overlooked the fact that they are leaks, but I guess that's in part because I expected a lot but not a huge number of Pacmans (I was thinking like 50+ just based on the picture)

With enough new Pacmen/dead Pacmen the trigger could become rather bloated and inefficient. But that could also be such a miniscule problem that it's not worth worrying about.
I wasn't worried about it, but depending on the number of Pacman I would totally agree.
Sorry for being nit-picky, I like to data-mine the willing :p

Regarding the Conditions, since there's like 4 Unit-Types to check I think it makes the most sense to just give those 4 Unit-types something in common that you can check for once. Hence why I use an ability to create what's essentially a custom Unit classification.
You could also use this to deal with the hidden/unhidden unit aspect, but the main reason I didn't convert my system when I saw your suggestion was laziness. I like having just one condition to check too.

That shrinks your Condition count down from N where N is the number of different Unit-types to 1. Another neat bonus of the ability is that you could temporarily Remove it or change it's level to essentially "unimmune" a unit, giving you some extra control.
Truth. Actually emphasizes that my way is indeed slower with the point about N conditions. And more control = excellent.

Regarding the Unit Group, I prefer to use a variable over bj_wantDestroyGroup because there are cases where bj_ can fail or cause problems. I forget what those cases are, and perhaps it's just superstition from reading misinformation/outdated info in the past, but since I can't remember I prefer to stick with what I know works. It's also just a habit :p
Say no more, I'll probably still use it until one of those bugs bugs me, but still I get it.
Thanks again for being so helpful and appeasing my curiosity!
 
Level 7
Joined
Feb 13, 2022
Messages
87
I would avoid that Event entirely and just handle it myself. This way you won't have to deal with any weirdness that comes with Event limits, dead units being permanently registered to the Event, and just weird Warcraft 3 behavior.

I think a better approach would be something like this:
  • Pacman Add
    • Events
      • Unit - A unit enters (Playable map area)
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Pacman
    • Actions
      • Unit Group - Add (Triggering unit) to Pacman_Source_Group
      • Trigger - Turn on Pacman Kill Loop <gen>
  • Pacman Remove
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Pacman
    • Actions
      • Unit Group - Remove (Triggering unit) from Pacman_Source_Group.
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Number of units in Pacman_Source_Group) Equal to 0
        • Then - Actions
          • Trigger - Turn off Pacman Kill Loop <gen>
        • Else - Actions
  • Pacman Kill Loop
    • Events
      • Time - Every 0.10 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in Pacman_Source_Group and do (Actions)
        • Loop - Actions
          • Set VariableSet Pacman_Source = (Picked unit)
          • Set VariableSet Pacman_Point = (Position of Pacman_Source)
          • Set VariableSet Pacman_Target_Group = (Units within 145.00 of Pacman_Point.)
          • Unit Group - Pick every unit in Pacman_Target_Group and do (Actions)
            • Loop - Actions
              • Set VariableSet Pacman_Target = (Picked unit)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Level of Pacman Immunity (Hidden) for Pacman_Target) Equal to 0
                  • (Pacman_Target is alive) Equal to True
                  • (Owner of Pacman_Target) Not equal to Player 12 (Brown)
                • Then - Actions
                  • Unit - Kill Pacman_Target
                • Else - Actions
          • Custom script: call RemoveLocation( udg_Pacman_Point )
          • Custom script: call DestroyGroup( udg_Pacman_Target_Group )
Pacman_Immunity is an ability based on Storm Hammers. It acts as a classification that we can check in our Conditions to efficiently determine who is immune to Pacman's bloodthirsty ways. So you would give this ability to your Scout Towers and other Unit-types that are meant to be immune.

If some of your Pacman units are pre-placed on the map then you should Add them to Pacman_Source_Group at the start of the game:
  • Events
    • Time - Elapsed game time is 0.00 seconds
  • Conditions
  • Actions
    • Set VariableSet Pacman_Source_Group = (Units in playable map area matching (Unit-type of matching unit Equal to Pacman))
Pacman Kill Loop is designed to be Turned Off while no Pacman units are alive since it wouldn't be doing anything.
  • (Level of Pacman Immunity (Hidden) for Pacman_Target) Equal to 0
This is the only part that doesn't work. I have no idea why, does anyone have any suggestions? When I remove it from the conditions the Pac-Man kill again, but when it is included it doesn't work. I need this part so it doesn't kill everyone...
 
Level 20
Joined
Jan 3, 2022
Messages
364
Uncle gave me an idea. Can't you use the Immolate ability? Increase its range, make it only of certain damage type that will only make the targets vulnerable to it. When Pacmans become invisible, you disable the ability on the unit through triggers. Turn on when visible.
This approach with damage types works only if your map isn't gonna be big and rely on damage type mechanics. No expensive distance checks inside triggers.
 
Level 8
Joined
Jul 21, 2015
Messages
143
  • PacmanKILL
    • Events
      • Unit - A unit comes within 155.00 of Pac-Man 0187 <gen>
      • Unit - A unit comes within 155.00 of Pac-Man 0060 <gen>
      • Unit - A unit comes within 155.00 of Pac-Man 0125 <gen>
      • Unit - A unit comes within 155.00 of Pac-Man 0078 <gen>
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Rat
    • Actions
      • Unit - Kill (Triggering unit)
is it not just this way to do it?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
  • PacmanKILL
    • Events
      • Unit - A unit comes within 155.00 of Pac-Man 0187 <gen>
      • Unit - A unit comes within 155.00 of Pac-Man 0060 <gen>
      • Unit - A unit comes within 155.00 of Pac-Man 0125 <gen>
      • Unit - A unit comes within 155.00 of Pac-Man 0078 <gen>
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Rat
    • Actions
      • Unit - Kill (Triggering unit)
is it not just this way to do it?
I don't touch those Register Specific Unit Events as they're prone to issues, but maybe it's an unnecessary fear in this case. That could very well be more performant and issue free, I really can't say.
 
Status
Not open for further replies.
Top