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

[Trigger] Is it okay to leave leaks in GUI triggers?

Level 5
Joined
May 27, 2020
Messages
22
Is it okay to leave this trigger like this if it's going to be used for the whole duration of the map?
  • Events
    • Time - Elapsed game time is 0.03 seconds
  • Conditions
  • Actions
    • Set Monster_TimerIndex = (Monster_TimerIndex + 1)
    • Countdown Timer - Create a timer window for Monster_Timer with title Lv.1 Creeps Spawnin...
    • Set Monster_TimerWindow = (Last created timer window)
    • Countdown Timer - Start Monster_Timer as a One-shot timer that will expire in 15.00 seconds
    • Countdown Timer - Show Monster_TimerWindow
    • Set MonsterSpawner_Loc[1] = (Center of Monster Spawner Inner 1 <gen>)
    • Set MonsterSpawner_Loc[2] = (Center of Monster Spawner Inner 2 <gen>)
    • Set MonsterSpawner_Loc[3] = (Center of Monster Spawner Inner 3 <gen>)
    • Set MonsterSpawner_Loc[4] = (Center of Monster Spawner Inner 4 <gen>)
    • Set MonsterSpawner_Loc[5] = (Center of Monster Spawner Inner 5 <gen>)
    • Set MonsterSpawner_Loc[6] = (Center of Monster Spawner Inner 6 <gen>)
    • Set MonsterSpawner_Loc[7] = (Center of Monster Spawner Inner 7 <gen>)
    • Set MonsterSpawner_Loc[8] = (Center of Monster Spawner Inner 8 <gen>)
    • ...
These locations are where the creeps are going to spawn for the whole duration of the map. I know points and regions leak but should I fix them if I'm going to use it anyway?

And if I'm going to fix them, what is the best possible way to do it?
 
Level 5
Joined
May 27, 2020
Messages
22
If you are never going to make a new timer, and those points are not ever going to change, then it isn't a leak!

If you are going to make new timer windows, I'm not sure on that but I would assume you have to do some clean-up.
I actually have two more triggers that are connected to this. In which, the index increases every certain duration.

  • MonsterTimerInterval
    • Events
    • Conditions
    • Actions
      • Set Monster_TimerIndex = (Monster_TimerIndex + 1)
      • Countdown Timer - Create a timer window for Monster_Timer with title ((Lv. + (String(Monster_TimerIndex))) + monsters in: )
      • Set Monster_TimerWindow = (Last created timer window)
      • Countdown Timer - Start Monster_Timer as a One-shot timer that will expire in 180.00 seconds
      • Countdown Timer - Show Monster_TimerWindow

And this trigger where it spawns the monsters:
  • MonsterTimerLoop
    • Events
      • Time - Monster_Timer expires
    • Conditions
    • Actions
      • Countdown Timer - Destroy Monster_TimerWindow
      • Countdown Timer - Hide Monster_TimerWindow
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Monster_TimerIndex Equal to 1
        • Then - Actions
          • Game - Display to (All players) for 10.00 seconds the text: |c00FF9696Level 1 m...
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Monster_TimerIndex Equal to 2
            • Then - Actions
              • Game - Display to (All players) for 10.00 seconds the text: |c00FF9696Level 2 m...
              • For each (Integer A) from 1 to 8, do (Actions)
                • Loop - Actions
                  • Unit - Create 1 Necromancer Spirit (Lv.2) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
              • For each (Integer A) from 9 to 20, do (Actions)
                • Loop - Actions
                  • Unit - Create 1 River Elemental (Lv.2) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
              • For each (Integer A) from 21 to 40, do (Actions)
                • Loop - Actions
                  • Unit - Create 2 Archer (Lv.2) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • Monster_TimerIndex Equal to 3
                • Then - Actions
                  • Game - Display to (All players) for 10.00 seconds the text: |c00FF9696Level 3 m...
                  • For each (Integer A) from 1 to 8, do (Actions)
                    • Loop - Actions
                      • Unit - Create 1 Tentacle (Lv.3) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
                  • For each (Integer A) from 9 to 20, do (Actions)
                    • Loop - Actions
                      • Unit - Create 1 Toxic Lava Spawn (Lv.3) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
                  • For each (Integer A) from 21 to 40, do (Actions)
                    • Loop - Actions
                      • Unit - Create 1 Swamp Monster (Lv.3) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • Monster_TimerIndex Equal to 4
                    • Then - Actions
                      • Set Monster_Late = True
                      • Set Monsters_RespawnTime = 45.00
                      • Game - Display to (All players) for 10.00 seconds the text: |c00FF0000This is t...
                      • For each (Integer A) from 1 to 8, do (Actions)
                        • Loop - Actions
                          • Unit - Create 1 Oddworld Scorpion (Lv.4) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
                      • For each (Integer A) from 9 to 20, do (Actions)
                        • Loop - Actions
                          • Unit - Create 1 Mur'gul Creeper (Lv.4) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
                      • For each (Integer A) from 21 to 40, do (Actions)
                        • Loop - Actions
                          • Unit - Create 1 Fel Orc Grunt (Lv.4) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
                    • Else - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • Monster_TimerIndex Equal to 5
                        • Then - Actions
                          • Set Monsters_RespawnTime = 60.00
                          • Game - Display to (All players) for 10.00 seconds the text: |c00FF0000The hound...
                          • For each (Integer A) from 1 to 8, do (Actions)
                            • Loop - Actions
                              • Unit - Create 1 Voidwalker (Lv.5) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
                          • For each (Integer A) from 9 to 20, do (Actions)
                            • Loop - Actions
                              • Unit - Create 1 Faeri Dragon (Lv.5) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
                          • For each (Integer A) from 21 to 40, do (Actions)
                            • Loop - Actions
                              • Unit - Create 2 Black Drake (Lv.5) for Player 10 (Light Blue) at MonsterSpawner_Loc[(Integer A)] facing Default building facing degrees
                          • Skip remaining actions
                        • Else - Actions
      • Trigger - Run MonsterTimerInterval <gen> (ignoring conditions)
I've also read that using Integer A is slower than using own variable, is it much better if I use a different variable here rather than Integer A?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
I wouldn't try to hide a destroyed timer window. Destroyed windows should be removed from the screen since they no longer exist:
  • Countdown Timer - Destroy Monster_TimerWindow
  • Countdown Timer - Hide Monster_TimerWindow
I've also read that using Integer A is slower than using own variable
You should use a different variable than (Integer A) for the sake of preventing global variable clashes. (Integer A) is just an Integer variable that Blizzard has provided for you, however, it comes with the catch of needing to run a function to retrieve it.

So yes, it runs faster when using your own Integer variable, but more importantly it's a good idea to use a unique Integer variable to avoid any outside interference.

Also, if you're interesting in optimizations, I recommend using more Arrays. For example look how clean we can make this trigger:
  • MonsterTimerLoop
    • Events
      • Time - Monster_Timer expires
    • Conditions
    • Actions
      • Countdown Timer - Destroy Monster_TimerWindow
      • For each (Monster_Loop) from 1 to 5, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • Monster_TimerIndex Equal to Monster_Loop
            • Then - Actions
              • Game - Display to (All players) for 10.00 seconds the text: Monster_Text[Monster_Loop]
              • For each (Monster_Index) from 1 to 8, do (Actions)
                • Loop - Actions
                  • Unit - Create 1 Monster_Unit_A[Monster_Index] for Player 10 (Light Blue) at MonsterSpawner_Loc[Monster_Loop] facing Default building facing degrees
              • For each (Monster_Index) from 9 to 20, do (Actions)
                • Loop - Actions
                  • Unit - Create 1 Monster_Unit_B[Monster_Index] for Player 10 (Light Blue) at MonsterSpawner_Loc[Monster_Loop] facing Default building facing degrees
              • For each (Monster_Index) from 21 to 40, do (Actions)
                • Loop - Actions
                  • Unit - Create 1 Monster_Unit_C[Monster_Index] for Player 10 (Light Blue) at MonsterSpawner_Loc[Monster_Loop] facing Default building facing degrees
            • Else - Actions
      • Trigger - Run MonsterTimerInterval <gen> (ignoring conditions)
I admit this isn't the BEST trigger for this sort of optimization, but hopefully you see my point. (I left out some important Actions)
 
Last edited:
Level 14
Joined
Jan 10, 2023
Messages
248
...needing to run a function to retrieve it.
Forgive me for being nit-picky, but I figured I'd take the opportunity to make sure I understand/ have my terminology correct.
Would it be more accurate to say that using Integer A/B loops has the extra tasks of:
  1. Sharing a global instead of having a unique enumerating variable
  2. Using 1 extra global variable for the end-point instead of using a constant value
  3. Comparing 2 globals every loop instead of 1 global and 1 constant for the exit condition
Like this:
JASS:
function TwoLoopsActions takes nothing returns nothing
    // Loop for Integer A
    set bj_forLoopAIndex = 1
    set bj_forLoopAIndexEnd = 10
    loop
        exitwhen bj_forLoopAIndex > bj_forLoopAIndexEnd
        set bj_forLoopAIndex = bj_forLoopAIndex + 1
    endloop
    // Loop for udg_Int
    set udg_Int = 1
    loop
        exitwhen udg_Int > 10
        set udg_Int = udg_Int + 1
    endloop
endfunction

I absolutely agree that the #1 above is the most important, especially since this concept only really applies to GUI users.

Part of the reason I want clarity on this is because when performance is the priority, if my loop uses a global variable for the end-point (for example, the stored size of the array), I will set that endpoint to a local variable and use that in the 'exitwhen' condition, rather than repeatedly getting the the global variable from memory.

Basically, I've assumed that local variables are a faster data-pull than globals, is that true?
Or in other words, is this following list in order of fastest to slowest?
  1. set i = x + 1
  2. set i = udg_x + 1
  3. set i = udg_x[0] + 1
 
Level 5
Joined
May 27, 2020
Messages
22
I wouldn't try to hide a destroyed timer window. Destroyed windows should be removed from the screen since they no longer exist:
Thanks for pointing this out, I didn't really noticed it before.

So yes, it runs faster when using your own Integer variable...
If you are never going to make a new timer, and those points are not ever going to change, then it isn't a leak!
Thanks for clarifying and answering these questions, really helped a lot.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Forgive me for being nit-picky, but I figured I'd take the opportunity to make sure I understand/ have my terminology correct.
Would it be more accurate to say that using Integer A/B loops has the extra tasks of:
  1. Sharing a global instead of having a unique enumerating variable
  2. Using 1 extra global variable for the end-point instead of using a constant value
  3. Comparing 2 globals every loop instead of 1 global and 1 constant for the exit condition1
Actually I was wrong about Integer A/B, it doesn't call a function to return the Integer. I figured it was like GetDyingUnit() which assumedly returns
bj_lastDyingWidget or a variable like that. But I was strictly talking about how GUI handles things.

Basically, I've assumed that local variables are a faster data-pull than globals, is that true?
Locals are definitely faster, although I'm no expert.
 
Top