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

[Solved] Help me understand loops and actions per unit in group

Status
Not open for further replies.
Level 3
Joined
Nov 12, 2018
Messages
43
I don't understand:
  • For each (Integer INT) from a to b, do (Actions)
  • Unit Group - Pick every unit in GROUP and do (Actions)
I think, that every action inside a "For each INT from a to b do (Actions)"-loop, is executed for the current value of INT, then INT gets increased by 1 and repeats all actions, until it's equal to b.
And I think that every action in a "Unit Group - Pick every unit in GROUP and do (Actions)"-loop, is executed for the current "PickedUnit", until every unit was picked once. Or is this not even a loop?

But if I put a "Unit Group"-loop inside a "For each INT-loop, and ask for a variable VAR[INT] inside the "Unit Group"-loop, then VAR[INT] is cycled through a to b, despite the current value of INT in the "For each INT"-loop should be set to a fixed value, until the INT gets increased by one, after the Unit Group-loop is cycled through all it's units.

  • My Trigger
    • Events
      • Time - Every x seconds of game time
    • Conditions
    • Actions
      • For each (Integer loop_HumanPlayerA) from 1 to 6, do (Actions)
        • Loop - Actions
          • Set a_HA01_LocCaster[loop_HumanPlayerA] = (Position of player_HERO[loop_HumanPlayerA])
          • Unit Group - Pick every unit in a_HA01_DummyGroup[loop_HumanPlayerA] and do (Actions)
            • Loop - Actions
              • Custom script: set udg_temp_Key = GetHandleId(GetEnumUnit())
              • Set temp_Location = (a_HA01_LocCaster[loop_HumanPlayerA] offset by (Load h_HA01_Data_radius of temp_Key from HT_Ability_Data) towards (8.00 + (Load h_HA01_Data_angle of temp_Key from HT_Ability_Data)) degrees)
              • Unit - Move (Picked unit) instantly to temp_Location, facing a_HA01_LocCaster[loop_HumanPlayerA]
              • Hashtable - Save (8.00 + (Load h_HA01_Data_angle of temp_Key from HT_Ability_Data)) as h_HA01_Data_angle of temp_Key in HT_Ability_Data
              • Custom script: call RemoveLocation(udg_temp_Location)
          • Custom script: call RemoveLocation(udg_a_HA01_LocCaster[udg_loop_HumanPlayerA])
I want to circle dummy units around a hero. I use the "For each Integer loop_HumanplayerA"-loop to get the hero of every player, and the "Unit Group"-loop to get every dummy unit of that hero. The dummy units are inside an array of unit group variables.

Once I set temp_Location inside the "Unit Group"-loop, I ask for a_HA01_LocCaster[loop_HumanPlayerA] (point variable) which was set befor, outside the "Unit Group"loop. So with my understanding, the actual value of that point variable should stay the same, for each PickedUnit inside the "Unit Group"-loop.

But what realy happens is, that a_HA01_LocCaster[loop_HumanPlayerA] gets cycled through per PickedUnit! Therefor, only the point for a_HA01_LocCaster[1] does even exist (if I test it alone, no other player/hero), while all other values of a_HA01_LocCaster[loop_HumanPlayerA] are set to 0;0 - Center of Map, since there is no existing player_HERO[2-6]. Only the first unit in the group circles around my hero. Every other unit does this around the center of my map.

Setting a_HA01_LocCaster[loop_HumanPlayerA] to a_HA01_LocCaster[1] inside the "Unit Group"-loop, fixes my problem, but then it works only for player 1.

I realy hope you understand, what I want to tell you. :vw_unimpressed:
 
Last edited:
Level 3
Joined
Nov 12, 2018
Messages
43
I isolated the spell and now it works just fine. :eek: Should have done this befor...
I'm going to search for the mistake somewhere else.

edit: I found the responsible trigger, by de-activating every unnecessary trigger and activate each trigger one by one, until it idn't worked again. I was able to fix my bug, but I still have zero clue, how those two trigger interfered with each other?
 

Attachments

  • DEMO-Map.w3x
    25.8 KB · Views: 32
Last edited:
Level 3
Joined
Nov 12, 2018
Messages
43
This is a copy of the original map. I removed everything unecassary.
You can active the bug, by activating "PROBLEM TRIGGER" in the trigger editor.

it's not the original trigger though. I know how to force the bug 100%. But I still don't get it...
 

Attachments

  • Titan Siege - Bugged.w3x
    154.3 KB · Views: 33
Last edited:
It's this move order action:
  • ACTION_BLOCK_1
  • ..
  • Unit - Order (Last created unit) to Move To temp_Location
  • ..
  • ACTION_BLOCK_2
^it will fire all trigger with point order events, before ACTION_BLOCK_2 starts, like this problem trigger:
  • PROBLEM TRIGGER
    • Events
      • Unit - A unit Is issued an order targeting a point
    • Conditions
    • Actions
      • For each (Integer loop_HumanPlayerA) from 1 to 6, do (Actions)
        • Loop - Actions
And when the problem trigger runs, the loop will run from 1 to 6 with loop_HumanPlayerA. So when this "problem trigger" ends loop_HumanPlayerA will be "6".
Now when ACTION_BLOCK_2 is executed, the loop_HumanPlayerA is still "6" and so it does bug.

The only solution to this is to use unique integer, exclusively for the loop that is not used by other triggers.
 
Level 3
Joined
Nov 12, 2018
Messages
43
Oh... so each cycle inside a loop is a unique thread. Each trigger, that gets fired by a function inside that cycle, will be executed before the next cycle starts. And if there is a new loop, using the same Integer, then it's messing up my previous loop. Em I understanding that right?

Tank you very much. Now I can prevent this from happening again.

/edit: just realising, that I made a huge mistake in my map... :rolleyes:
 
Last edited:
Yes, you're correct! : )

This unwilling trigger-interfering with each is often a burden, especially in GUI, where only global variables do exist.

There are also much more possible scenarios that may run other triggers when doing actions:
  1. Unit creation -> Event "A Unit Enters Region (Playable Map Area)"
  2. Kill Unit -> Event "A Unit Dies"
  3. Order unit cast -> Event "A unit casts"
  4. ...
 
Level 3
Joined
Nov 12, 2018
Messages
43
Can I use local integers in order to prevent, that loops with the same integer variable do interfere, if cycled through in between?

  • Local loop
    • Events
      • Any Event
    • Conditions
    • Actions
      • Custom script: local integer loop_HumanPlayerA
      • Custom script: set loop_HumanPlayerA = 1
      • Custom script: loop
      • Custom script: exitwhen loop_HumanPlayerA > 6
      • -------- actions... --------
      • -------- actions... --------
      • -------- actions... --------
      • Custom script: set loop_HumanPlayerA = loop_HumanPlayerA + 1
      • Custom script: endloop
I know, that I still have to change every udg_loop_HumanPlayerA index to the local variable.
If this works, I definitely start learning proper jass.

/edit1:
  • Custom script: set udg_loop_HumanPlayerA = loop_HumanPlayerA
Can I add this inside a block and use udg_loop_HumanPlayerA as index in GUI? So I still can use GUI with a local integer variable?


/edit2:
I just tested it, and it seems to work!
Log:


  • Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set unit[3] = Soldat 0001 <gen>
  • Local loop 1
    • Events
      • Player - Player 1 (Red) skips a cinematic sequence
    • Conditions
    • Actions
      • Custom script: local integer loop_HumanPlayerA
      • Game - Display to (All players) the text: Loop 1 starts:
      • Custom script: set loop_HumanPlayerA = 1
      • Custom script: loop
      • Custom script: exitwhen loop_HumanPlayerA > 6
      • -------- ---------------------------------------------------------------------------------- --------
      • Custom script: call DisplayTextToForce( GetPlayersAll(), ( "Loop1 - Cycle: " + I2S(loop_HumanPlayerA) ) )
      • Custom script: set udg_loop_HumanPlayerA = loop_HumanPlayerA
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • loop_HumanPlayerA Equal to 3
        • Then - Actions
          • Game - Display to (All players) the text: Soldier gets move o...
          • Unit - Order unit[loop_HumanPlayerA] to Bewegen nach (Center of (Playable map area))
        • Else - Actions
      • -------- ---------------------------------------------------------------------------------- --------
      • Custom script: set loop_HumanPlayerA = loop_HumanPlayerA + 1
      • Custom script: endloop
      • Game - Display to (All players) the text: Loop 1 ends:
  • Local loop 2
    • Events
      • Unit - A unit Is issued an order targeting a point
    • Conditions
    • Actions
      • Custom script: local integer loop_HumanPlayerA
      • Game - Display to (All players) the text: Loop 2 starts:
      • Custom script: set loop_HumanPlayerA = 1
      • Custom script: loop
      • Custom script: exitwhen loop_HumanPlayerA > 6
      • -------- ---------------------------------------------------------------------------------- --------
      • Custom script: call DisplayTextToForce( GetPlayersAll(), ( "Loop2 - Cycle: " + I2S(loop_HumanPlayerA) ) )
      • -------- ---------------------------------------------------------------------------------- --------
      • Custom script: set loop_HumanPlayerA = loop_HumanPlayerA + 1
      • Custom script: endloop
      • Game - Display to (All players) the text: Loop 2 ends:
 
Last edited:
Status
Not open for further replies.
Top