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

Leak with random region spawn?

Status
Not open for further replies.
Level 3
Joined
Mar 10, 2019
Messages
32
Hey guys,

I use always unit groubs instead of "get every unit in region" since in my experience this is more reliable. But here is a strange thing. When I spawn my units at random position in a Region sometimes. 1 unit will be spawned in a neighbour region. There is enough space between the region and everything around it!

  • CreepSpawnTrigger
    • Events
    • Conditions
    • Actions
      • For each (Integer B) from 1 to TEAMS_STILL_PLAYING_COUNT, do (Actions)
        • Loop - Actions
          • Player Group - Pick every player in TEAMS_STILL_PLAYING_FILLED[(Integer B)] and do (Actions)
            • Loop - Actions
              • For each (Integer A) from 1 to CreepWaveUnitsCount[CURRENT_ROUND], do (Actions)
                • Loop - Actions
                  • Unit - Create 1 CreepWaveUnits[CURRENT_ROUND] for Neutral Hostile at (Random point in playerToRegionArray[(Player number of (Picked player))]) facing (Center of playerToRegionArray[(Player number of (Picked player))])
                  • Unit Group - Add (Last created unit) to roundUnitGroupsToKill[playerToTeamInteger[(Player number of (Picked player))]]
                  • Unit - Change color of (Last created unit) to (Color of (Picked player))
Example:

I spawn 5 creeps in 10 regions. And 49 spawn right and 1 wrong. This happens rare like in every 50 to 100 spawns or so... I have a "-unstuck" command to teleport all non Hero creeps back but it is annoying.

Has anyone experienced something similar?
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,570
I believe you want to set that "Random point in Region" to a Point variable and clean it up afterwards, otherwise it will leak.

Also, I've always experienced weird interactions when using multiple Loops like this. I was told not to use Integer A and Integer B, but i'm not sure if that's the issue. What I noticed in my experience was that when I cut out one of the loops my triggers would tend to work again. So maybe try doing this with just one Loop. I imagine you don't really need the first Integer B Loop, you could probably track the teams that are still playing with a non-arrayed player group.
 
Level 3
Joined
Mar 10, 2019
Messages
32
Thanks for your reply! I searched for your suggestion and found this.

Changed to code to this:

  • CreepSpawnTrigger
    • Events
    • Conditions
    • Actions
      • For each (Integer __0008) from 1 to TEAMS_STILL_PLAYING_COUNT, do (Actions)
        • Loop - Actions
          • Player Group - Pick every player in TEAMS_STILL_PLAYING_FILLED[__0008] and do (Actions)
            • Loop - Actions
              • For each (Integer __0009) from 1 to CreepWaveUnitsCount[CURRENT_ROUND], do (Actions)
                • Loop - Actions
                  • Set creepRandSpawnPoint = (Random point in playerToRegionArray[(Player number of (Picked player))])
                  • Unit - Create 1 CreepWaveUnits[CURRENT_ROUND] for Neutral Hostile at creepRandSpawnPoint facing (Center of playerToRegionArray[(Player number of (Picked player))])
                  • Unit Group - Add (Last created unit) to roundUnitGroupsToKill[playerToTeamInteger[(Player number of (Picked player))]]
                  • Unit - Change color of (Last created unit) to (Color of (Picked player))
                  • Custom script: call RemoveLocation ( udg_creepRandSpawnPoint )
      • Set __0008 = 1
      • Set __0009 = 1
Hope this fixes the issue.

PS: If I use the "central points" thing like for heroes spawn in other regions do I have to clear them as well?
 
Level 3
Joined
Mar 10, 2019
Messages
32
Damn... problem still occuring... I try to workaround a "hack" for now...

  • CreepSpawnTrigger
    • Events
    • Conditions
    • Actions
      • For each (Integer __0008) from 1 to TEAMS_STILL_PLAYING_COUNT, do (Actions)
        • Loop - Actions
          • Player Group - Pick every player in TEAMS_STILL_PLAYING_FILLED[__0008] and do (Actions)
            • Loop - Actions
              • For each (Integer __0009) from 1 to CreepWaveUnitsCount[CURRENT_ROUND], do (Actions)
                • Loop - Actions
                  • Set creepRandSpawnPoint = (Random point in playerToRegionArray[(Player number of (Picked player))])
                  • Unit - Create 1 CreepWaveUnits[CURRENT_ROUND] for Neutral Hostile at creepRandSpawnPoint facing (Center of playerToRegionArray[(Player number of (Picked player))])
                  • Unit Group - Add (Last created unit) to roundUnitGroupsToKill[playerToTeamInteger[(Player number of (Picked player))]]
                  • Unit - Change color of (Last created unit) to (Color of (Picked player))
                  • Custom script: call RemoveLocation ( udg_creepRandSpawnPoint )
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • (playerToRegionArray[(Player number of (Picked player))] contains (Last created unit)) Equal to False
                    • Then - Actions
                      • Game - Display to (All players) the text: (|cffff00ffFound a creep leak!!!!!|r - + (Name of (Picked player)))
                      • Game - Display to (All players) the text: (Region : + (String((Player number of (Picked player)))))
                      • Set creepRandSpawnPoint = (Random point in playerToRegionArray[(Player number of (Picked player))])
                      • Unit - Move (Last created unit) instantly to creepRandSpawnPoint
                      • Custom script: call RemoveLocation ( udg_creepRandSpawnPoint )
                    • Else - Actions
                      • Do nothing
      • Set __0008 = 1
      • Set __0009 = 1
 
Last edited:
Level 8
Joined
May 21, 2019
Messages
435
  • Unit - Create 1 CreepWaveUnits[CURRENT_ROUND] for Neutral Hostile at creepRandSpawnPoint facing (Center of playerToRegionArray[(Player number of (Picked player))])
You are still leaking a point here. When you are telling the unit to face the "center of (region)", you are generating a point that leaks.

As for the bug, it kinda sounds like the loop sometimes loses reference to who the picked player is. The game seems to have a lot of issues with running loops inside loops and etc.

Also, I'm wondering why you go through all of this trouble with the 2 loops to find the "picked player".
Wouldn't it be much simpler to just run a single loop on all players and then condition the loop to an "is_playing" boolean array on each player? Then use an integer to keep track of the player by index. It might solve the issue, as it could be a bug stemming from the multiple layered loops getting out of sync somehow.
 
Last edited:
Level 3
Joined
Mar 10, 2019
Messages
32
You are still leaking a point here. When you are telling the unit to face the "center of (region)", you are generating a point that leaks.

As for the bug, it kinda sounds like the loop sometimes loses reference to who the picked player is. The game seems to have a lot of issues with running loops inside loops and etc.

Also, I'm wondering why you go through all of this trouble with the 2 loops to find the "picked player".
Wouldn't it be much simpler to just run a single loop on all players and then condition the loop to an "is_playing" boolean array on each player? Then use an integer to keep track of the player by index. It might solve the issue, as it could be a bug stemming from the multiple layered loops getting out of sync somehow.


The 2 loops where used because I have an array with teams as player groups inside since the teams can be variable. In this example I can go away from this two loop approach to a single loop because the teams are totally ignored... But since this approach has problems other more complex parts of my game will have problems as well....

It really sucks that loops in loops are a problem since this is the core feature of any programming language and I never would have tought that the game has problems with this...

To the leak:
Ah yeah see it gonna remove the look direction^^
 
Level 3
Joined
Mar 10, 2019
Messages
32
Okay after some forum search it seems like my waits that I use to play some timed sounds are the problem (maybe)...

  • -------- CREEP BATTLE START --------
  • Trigger - Run HeroToCreepRegionTrigger <gen> (checking conditions)
  • Wait 0.60 game-time seconds
  • Sound - Play No sound
  • Wait 0.60 game-time seconds
  • Sound - Play BattleNetTick <gen>
  • Wait 0.60 game-time seconds
  • Sound - Play BattleNetTick <gen>
  • Wait 0.60 game-time seconds
  • Sound - Play BattleNetTick <gen>
  • Wait 0.60 game-time seconds
  • Sound - Play UpkeepRing <gen>
  • Trigger - Run CreepSpawnTrigger <gen> (checking conditions)
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,570
I avoid using waits entirely. You can use a repeating timer that lasts 0.60 seconds and then increase some variable by 1 or 0.60 or whatever you want to represent the amount of times it's triggered. Then have an If statement that check if this variable is = to 5 or 3.00 and run CreepSpawnTrigger and then turn off the timer.

Also, if that doesn't work, it's most likely the use of those two loops. I'm sure you can find a better way to track the teams without the need of that. Also, if you didn't already know, "Do Nothing" is a useless function.
 
Level 3
Joined
Mar 10, 2019
Messages
32
I avoid using waits entirely. You can use a repeating timer that lasts 0.60 seconds and then increase some variable by 1 or 0.60 or whatever you want to represent the amount of times it's triggered. Then have an If statement that check if this variable is = to 5 or 3.00 and run CreepSpawnTrigger and then turn off the timer.

Also, if that doesn't work, it's most likely the use of those two loops. I'm sure you can find a better way to track the teams without the need of that. Also, if you didn't already know, "Do Nothing" is a useless function.

After changing to "variables" in all ma A/B loops and removing the waits. It seems stable now. Dnk if this holds need a lot more testing games but for now it is sufficient I think.
Thanks for your help guys. It is my first "real" map. And I try to copy a map I like for practice. Learning a lot about the pitfalls here and there
 
Level 39
Joined
Feb 27, 2007
Messages
5,024
The reason the a/b loops get messed up is because the iterator and loop bounds variables are technically globals. If you are in the middle of an A loop and do something that causes another trigger with an A loop in it to run then those globals will be overwritten and the loop will funk out when it returns to the ‘outer’ A loop.
 
Level 3
Joined
Mar 10, 2019
Messages
32
@Pyrogasm yeah since this is the case it should be no harm to use nested loops if you use variables instead right?
Since the references are not shared anywhere.

PS: Jass can use local variables does anyone know why the A/B loop does not use locals I mean this would make most sense xD
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,024
It should be fine using the variables.

If they used locals you wouldn't be able to refer to them within ForGroup or ForForce, which 'happen' in separate functions. GUI conditions in things like If blocks are also separate functions under the hood. It's dumb but that's the way it does it.
 
Level 3
Joined
Mar 10, 2019
Messages
32
Aww thanks for the clarification. I though that a Trigger is the variable scope but it is a function scope so they would not know from each other.

So there are only global and function scopes.

But this brings me to:

If I have an event for Hero units and in this trigger I use a variable and 2 heroes die the same frame I get a reall problem right? Or are events per trigger queued? Since the game is single threaded.
 
Last edited:
Status
Not open for further replies.
Top