• 🏆 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!

[General] What is the limit time a global variable can store a variable after get overwritten?

Status
Not open for further replies.
Level 24
Joined
Jun 26, 2020
Messages
1,850
Let me explain, if I have a global variable then I call a function that not takes it but uses that variable, then do it again and again, but as is a global variable so it can be overwritten by other function that runs in "the exact time" what is the risk of that?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,509
An example of what could go wrong. I have these two triggers:

Trigger 1:
  • Events;
  • A unit dies
  • Actions:
  • Set variable TempUnit = triggering unit
Trigger 2:
  • Events:
  • A unit enters map
  • Conditions:
  • Unit-type not equal to Chicken
  • Actions:
  • Set variable TempUnit = triggering unit
  • Create 1 Chicken at center of map
  • Kill last created unit
  • Display name of TempUnit
The issue:
So my goal was to display the name of the Entering Unit (TempUnit), but TempUnit is getting overwritten to be equal to the dying Chicken. This is because when I Kill last created unit I'm causing the "A unit dies" trigger to run, which happens inside of my "Enters map" trigger, or at the "exact same time" as you put it.

This is what's actually happening in my second trigger:
  • Events:
  • A unit enters map
  • Conditions:
  • Unit-type not equal to Chicken
  • Actions:
  • Set variable TempUnit = triggering unit
  • Create 1 Chicken at center of map
  • Kill last created unit
  • Set variable TempUnit = dying unit (the Actions from the "A unit dies" trigger get added onto this trigger)
  • Display name of TempUnit
So you can see here what can go wrong when using a Global Variable that is shared between multiple triggers or functions. However, if you're aware of this issue then you can work around it.

For instance, you could use entirely different global variables in these cases. Or you could set local variables to be equal to your global variables at the start of your trigger/function, then reference the locals instead. For example:
  • Custom script: local unit u = udg_TempUnit
  • Wait 1.00 second
  • Custom script: KillUnit(u)
^ This is probably what you want to do, since even if TempUnit changes after the Wait, or say after another Function call, you'll still have reference to the original TempUnit (u).
 
Last edited:
Level 24
Joined
Jun 26, 2020
Messages
1,850
An example of what could go wrong:

  • Events;
  • A unit dies
  • Actions:
  • Set variable TempUnit = triggering unit
  • Events:
  • A unit enters map
  • Conditions:
  • Unit-type not equal to Chicken
  • Actions:
  • Set variable TempUnit = triggering unit
  • Create 1 Chicken at center of map
  • Kill last created unit
  • Display name of TempUnit
The issue:
So my goal was to display the name of the Entering Unit (TempUnit), but TempUnit is getting overwritten to be equal to the dying Chicken. This is because when I Kill last created unit I'm causing the "A unit dies" trigger to run, which happens inside of my "Enters map" trigger, or at the "exact same time" as you put it.

This is what's actually happening in my second trigger:
  • Events:
  • A unit enters map
  • Conditions:
  • Unit-type not equal to Chicken
  • Actions:
  • Set variable TempUnit = triggering unit
  • Create 1 Chicken at center of map
  • Kill last created unit
  • Set variable TempUnit = dying unit (the Actions from the "A unit dies" trigger get added onto this trigger)
  • Display name of TempUnit
So you can see here what can go wrong when using a Global Variable that is shared between multiple triggers or functions. However, if you're aware of this issue then you can work around it.

For instance, you could use entirely different global variables in these cases. Or you could set local variables to be equal to your global variables at the start of your trigger/function, then reference the locals instead of the global. For example:
  • Custom script: local unit u = udg_TempUnit
  • Wait 1.00 second
  • Custom script: KillUnit(u)
^ This is probably what you want to do, since even if TempUnit changes after the Wait, or say after another Function call, you'll still have reference to the original TempUnit (u).
I guess the solution to this was the most obvious, but I reffered to overwritting by another function that has no relation I mean somthing like this:
  • Trigger1
    • Events
    • Conditions
    • Actions
      • Trigger - Run Trigger 2
      • Trigger - Run Trigger 3
  • Trigger2
    • Events
    • Conditions
    • Actions
      • Set TempUnit = "Something"
      • more stuff
      • Unit - Somethig with TempUnit
      • Trigger - Run Trigger 4
  • Trigger3
    • Events
    • Conditions
    • Actions
      • Set TempUnit = "Another thing"
      • more stuff
      • Unit - Somethig with TempUnit
  • Trigger4
    • Events
    • Conditions
    • Actions
      • Does the value of TempUnit is equal to the value in Trigger2?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,509
TempUnit would still be the same value from Trigger2 because Trigger 3 happens after both Trigger2/4.

Trigger1 executes like this:
  • Events:
  • Conditions:
  • Actions:
  • (first trigger2 runs)
  • Set TempUnit = "Something"
  • more stuff
  • Unit - Something with TempUnit
  • (then trigger4 runs)
  • Is the value of TempUnit equal to the value in Trigger2? Answer: Yes.
  • (finally trigger3 runs)
  • Set TempUnit = "Another thing"
  • more stuff
  • Unit - Something with TempUnit
 
Level 24
Joined
Jun 26, 2020
Messages
1,850
TempUnit would still be the same value from Trigger2 because Trigger 3 happens after both Trigger2/4.

Trigger1 executes like this:
  • Events:
  • Conditions:
  • Actions:
  • (first trigger2 runs)
  • Set TempUnit = "Something"
  • more stuff
  • Unit - Something with TempUnit
  • (then trigger4 runs)
  • Is the value of TempUnit equal to the value in Trigger2? Answer: Yes.
  • (finally trigger3 runs)
  • Set TempUnit = "Another thing"
  • more stuff
  • Unit - Something with TempUnit
I see, thanks.
 

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
"the exact time" what is the risk of that?
There is no risk of that. There is no concurrent execution.

The only concern is that the value gets changed by another trigger thread that gets scheduled before the current trigger thread finished execution. This is usually caused by an event that responds to one of the actions run, but can also be caused by the trigger thread yielding due to a blocking operation such as TriggerSleepAction. The ordering the threads execute is still well defined.
 
Level 24
Joined
Jun 26, 2020
Messages
1,850
There is no risk of that. There is no concurrent execution.

The only concern is that the value gets changed by another trigger thread that gets scheduled before the current trigger thread finished execution. This is usually caused by an event that responds to one of the actions run, but can also be caused by the trigger thread yielding due to a blocking operation such as TriggerSleepAction. The ordering the threads execute is still well defined.
Well, it was clear to me.
 
Level 24
Joined
Jun 26, 2020
Messages
1,850
I have another question, if I do something like this:
  • Trigger
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
      • Imagine we are in Jass and in the conditions I do something like "set udg_Spell=GetSpellAbilityId()"
    • Actions
      • Or in GUI
      • Set Spell = (Ability being cast)
Will the variable "Spell" replace the function "Ability being cast" for all the triggers that have that same event? I mean like in a trigger:
  • Trigger2
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • Game - Display to (All players) the text: (Name of Spell) //Instead of using (Ability being cast)
Edit, I tested it and Yes it does, but how accurate is this?
 
Last edited:

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
Edit, I tested it and Yes it does, but how accurate is this?
It depends on internal ordering, which is likely related to the order the events get created. If you were to swap the actions between the triggers then you will find that it no longer is correct as the trigger checking the variable gets run before the trigger that sets the variable.
 
Level 24
Joined
Jun 26, 2020
Messages
1,850
It depends on internal ordering, which is likely related to the order the events get created. If you were to swap the actions between the triggers then you will find that it no longer is correct as the trigger checking the variable gets run before the trigger that sets the variable.
I swap the actions and is the same case, even I changed the order of the triggers and equal, so what's happening?, and maybe I can use this in a library to avoid creating local variables to reduce the number of function calls.

Edit: Even I can do this to change the events using a real variable, because, what is better 100 triggers that register if a unit cast an spell or 100 triggers that register if a variable acquires a certain value? Or am I getting too high?
 
Last edited:

Dr Super Good

Spell Reviewer
Level 63
Joined
Jan 18, 2005
Messages
27,188
I swap the actions and is the same case, even I changed the order of the triggers and equal, so what's happening?
One trigger is still run before the other. The global variable will be caching the value from the last run so you can only detect it by alternating casting 2 differently named abilities. Without seeing your exact code or the map I cannot tell for sure if there are not other influences changing the expected outcome.
Edit: Even I can do this to change the events using a real variable, because, what is better 100 triggers that register if a unit cast an spell or 100 triggers that register if a variable acquires a certain value? Or am I getting too high?
This might be mico-optimiztion which makes no difference.

For events like units casting a spell there is a much better optimization that is done by having 1 trigger that handles all spells that then looks up and runs the appropriate code for that spell using a lookup table of sorts like a hashtable. This turns the complexity of custom abilities with respect to the number of such abilities from O(n) to O(1) making it as good as infinitely scaleable.
 
Level 24
Joined
Jun 26, 2020
Messages
1,850
One trigger is still run before the other. The global variable will be caching the value from the last run so you can only detect it by alternating casting 2 differently named abilities. Without seeing your exact code or the map I cannot tell for sure if there are not other influences changing the expected outcome.
I tested it with various spells.
 
Status
Not open for further replies.
Top