• 🏆 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] Temporary variables patterns in the trigger editor

Status
Not open for further replies.
Level 25
Joined
Feb 2, 2006
Messages
1,689
Hi,

recently I have been using GUI triggers a lot in maps instead of the scripting languages and it helped me a lot to use two patterns: The first is to use temporary global variables to emulate trigger parameters and the second is to use temporary global variables as local variables inside of triggers.

For example in the following trigger:
  • Spawn From Barracks
    • Events
      • Time - SpawnTimer expires
    • Conditions
    • Actions
      • Unit Group - Pick every unit in AllBarracks and do (Actions)
        • Loop - Actions
          • Set VariableSet TmpUnit = (Picked unit)
          • Set VariableSet TmpPlayer = (Owner of TmpUnit)
          • Trigger - Run Spawn Unit Types from Barrack <gen> (checking conditions)
I use the two global variables TmpUnit and TmpPlayer as the expected parameters. In the comment of the trigger Spwan Unit Types from Barrack it says that the trigger requires these two variables to be set to run. I was wondering why the trigger editor does not simply have such Tmp variables for every type and like 1-5 of them to easily allow using the pattern.
It could go even further and allow you to run a trigger only with its required parameters. I hope this does not cause data races since the trigger should be executed immediately and I use no waits inside.

Another thing which helped me using such tmp variables was to concatenate long strings over multiple lines or calculating complicated integer/real values over multiple lines. Sometimes I just set the temporary variables in the beginning of the trigger like the TmpPlayer to use it in the whole trigger which makes the actions much cleaner.

Didn't the Starcraft editor have triggers with parameters or local variables inside of triggers? Is there any reason why Warcraft 3 doesn't have this. I have never looked at the triggers from the original campaign but I could imagine that they use the same pattern. It allows you to call the same trigger from different other triggers changing the parameters, so basically like functions in JASS.

Do you have any idea why there are no default temporary global variables for every type? They only did this for something like the loop integers A and B :(
It would really help to have these default global variables for almost every type or to define local variables inside of triggers in the beginning, especially for standard types like strings, ints etc. it can be useful.

I guess it could only be achieved with a custom trigger editor GUI?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,544
GUI triggers are Jass functions, so they do have parameters. Also, they have Event Responses which are global/local variables.

You speak of "data races" and this method being safe but even without Waits you can overwrite a variable.

For example:
  • Events:
  • Unit - A unit starts the effect of an ability
  • Actions:
  • Set Variable TmpUnit = Casting unit
  • Trigger - Run KillTrigger <gen> (ignoring conditions)

KillTrigger:
  • Actions:
  • Unit - Kill TmpUnit
  • Player - Add 100 Gold to (Owner of TmpUnit)

DieTrigger:
  • Events:
  • Unit - A unit dies
  • Actions:
  • Set Variable TmpUnit = Killing unit

The issue here is that KillTrigger is going to cause DieTrigger to run, which then Sets TmpUnit to something else. This means that the added Gold will not go to the desired player:
  • Player - Add 100 Gold to (Owner of TmpUnit)
However, if you're aware of this then you can avoid these issues and still benefit from these global variables. You just need to be on top of it, a good strategy is to have unique variables that you use exclusively for certain Events.

Some of the most common Events that are easy to run inside of another trigger are: A unit dies, A unit enters/leaves region, A unit spawns a summoned unit, and others like these...
 
Last edited:
Level 29
Joined
Jul 29, 2007
Messages
5,174
Do you know upfront the maximum amount of units that can use this ability? if so you can have the same amount of globals.
If you don't know the amount, how many globals are you going to create? 2? 5? 20? how do you know?
Many of the built-in globals that Blizzard.j does offer are slight conveniences at the cost of you not controlling the data, which comes to bite many people, especially mentioning the built-in loop variables which - if you are using with any kind of wait/timer/whatever - prepare to have inconsistent hard to track bugs across the entire map in any trigger using these variables.

I also don't see what this gives you.
Making code support any N instances of an ability isn't particularly harder than making it support 1, or 2, or 5, or 20.
Whether you use an array, a hashtable, or whatever you want, it's the same as you declaring all of these globals, except in a proper storage container, and in a way you can map consistently regardless of waits or how many "triggers" (which you seem to use as functions) are involved, it's up to you.

This pattern might look nice in a simple case, but I doubt you will think so if you make a decently complex ability, or really anything that is not instantaneous.
 
Last edited:
Level 25
Joined
Feb 2, 2006
Messages
1,689
Hmm, true I never thought much about the nested calls which will overwrite the global variables. The same can happen if I call a trigger nested which requires the unit parameter again.

However, local variables in triggers would be useful and still save. There could be a trigger action which declares a local variable and the trigger editor just has to know it. This would work with a custom trigger editor which parses the local variable actions differently.

Besides, with a custom trigger editor it would be possible to create parameterized triggers which are simply trigger actions (JASS functions) with parameters and no event. Then I wouldn't need my pattern but this would require a custom trigger editor :(

I guess a safe pattern would be to create global variables for parameters for every trigger. In this case only nested calls of the same trigger would be a problem which do not happen often (I hope).
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
Local variables solve things that are not instantaneous, but also don't need tracking.
For example you shoot a fireball ability, wait 2 seconds, and then do something to the caster. A local here is perfect.
But if you were to shoot a fireball ability, and then you need in real-time to move this fireball for 2 seconds, and maybe check for collisions to see if it explodes before reaching the target, and so on...well, locals alone ain't gonna give you much, you need to store this data somewhere, have it accessible somewhere else where you are updating it, and you need to always know how to get to this data for this specific fireball since maybe there are 10 fireballs being shot right now at the same time.

I agree with Uncle.
If you are at the point of "hacking" GUI's design and using triggers as function calls, it's probably time to move on to code that actually supports functions (and tons of other things), rather than fighting GUI just for the sake of staying on GUI.
The concept of graphical programming could obviously be much more powerful, as shown by UE4's blueprints for example, but WC3's GUI isn't very good, and it will never be improved in any significant way.
 
Status
Not open for further replies.
Top