• Check out the results of the Techtree Contest #19!
  • 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.
  • Create a void inspired texture for Warcraft 3 and enter Hive's 34th Texturing Contest: Void! Click here to enter!
  • The Hive's 22nd Icon Contest: Creep Abilities is now concluded, time to vote for your favourite set of icons! Click here to vote!

Issues with Unit Group

Level 2
Joined
Mar 18, 2020
Messages
6
Hello, hoping someone can shed some light on this as I am out of my wits here. I have a basic checkpoint trigger "Checkpoint 4" that revives all heroes in an indexed UnitGroup Group[0] which, on random playthroughs, is only reviving some of the heroes instead of all. I would think that maybe they're decaying and being removed from the UnitGroup; however, there are longer levels where people are dead for longer and there is no issue there. And anyway, the movement of the unit heroes are set to "Fly" so they don't decay, right?

After this happens once, the "Revive" trigger will now fail to fire when the subset of remaining heroes that were revived then die.

The units are added to the group at the beginning of the game from units placed on the map. The only time units are removed from the group is when the player leaves the game in the triggers "[Color] Leaves".

I can reproduce the issue with computer players, sometimes. In my last playthrough, blue entered the checkpoint while everyone else was dead, and only red failed to revive. However, the checkpoint prints out each player id that is in the unit group and it included red (1) as if it was in the group. I also print out something if all units in Group[0] are dead and it did not print after I killed the remaining heroes.. !@#$

Cheers.

  • Checkpoint 4
    • Events
      • Unit - A unit enters Level 4 <gen>
    • Conditions
    • Actions
      • Trigger - Turn off (This trigger)
      • Unit Group - Pick every unit in Group[0] and do (Unit - Pause (Picked unit))
      • Unit Group - Pick every unit in Group[0] and do (If (((Picked unit) is alive) Equal to True) then do (Unit - Move (Picked unit) instantly to (Center of Checkpoint)) else do (Hero - Instantly revive (Picked unit) at (Center of Checkpoint), Hide revival graphics))
      • Unit Group - Pick every unit in Group[3] and do (Unit - Remove (Picked unit) from the game)
      • Wait 5.00 seconds
      • Unit Group - Pick every unit in Group[0] and do (Unit - Unpause (Picked unit))
  • Revive
    • Events
      • Unit - A unit Dies
    • Conditions
      • (All units of Group[0] are dead) Equal to True
    • Actions
      • Unit Group - Pick every unit in Group[0] and do (Unit - Pause (Picked unit))
      • Unit Group - Pick every unit in Group[0] and do (Hero - Instantly revive (Picked unit) at (Center of Checkpoint), Show revival graphics)
      • Unit Group - Pick every unit in Group[0] and do (Unit - Unpause (Picked unit))
  • Red Leaves
    • Events
      • Player - Player 1 (Red) leaves the game
      • Player - Player 1 (Red) leaves the game with a defeat
    • Conditions
    • Actions
      • Trigger - Turn off (This trigger)
      • Game - Display to (All players) the text: ((Name of (Triggering player)) + |cffffff00 has left the game.|r)
      • Unit Group - Remove PlayerChar 0045 <gen> from Group[0].
      • Unit - Remove PlayerChar 0045 <gen> from the game
 
Last edited:
The hero resurrection functions have a hidden buffer that can hold up to 7 dead heroes.
You can see this on this map, the [Esc] button resurrects all heroes on the map, kill more than 7 and see what happens.
The first hero to die disappears from the list and makes way for a new one.
Note: Each player has own buffer, 7 dead heroes for each player.
 

Attachments

Last edited:
1. Heroes don't decay, otherwise in a ladder game you'd lose your hero permanently if you waited too long to Revive them. Setting their Movement Type to "Fly" won't change this fact.

2. It's likely not a buffer issue since you're dealing with 1 Hero per Player (assumedly).

3. The (Pause) action causes all sorts of unwanted side effects and issues. There's a chance that it's the reason things are breaking here. I avoid it like the plague.

4. When a Hero dies, they don't immediately become Revivable. They have to officially "die" (death animation, death time, etc) before that happens. Although, maybe the "Revive Instantly" action bypasses this...

With that in mind, I attached a map with what appears to be a working setup. I think the main takeaway is that I stopped using the Pause action and replaced it with an alternative that Stuns the Heroes instead. I also tried to better organize things, and added some more Conditions to guarantee safe trigger executions.

Regarding organization, your "Red Leaves" trigger implies that you've created one trigger per Player. Often times a single trigger is all that's needed to manage your logic. You'll see in my map that I'm tracking Players in a Player Group, their Heroes in a Unit Group, and each individual Hero using a Unit-Array variable. This design gives me access to a Player and their Hero at any given moment, which allows me to have one "Player Leaves The Game" trigger that works for everyone. See my "Setup Game" trigger for more info, it ensures that all of my other triggers have a solid foundation to build upon.
 

Attachments

Last edited:
Found the issue in another trigger.. Apologies as I should have included it but it did NOT seem relevant at all.

It was in the Wisp trigger (below). If you remove "Pick every unit in Group[0] and set the Hero level to Hero level of Picked Unit + 1", then the issue never occurs.
  • Wisp
    • Events
      • Unit - A unit comes within 75.00 of Wisp 0299 <gen>
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to PlayerChar
    • Actions
      • Unit Group - Pick every unit in Group[0] and do (Hero - Set (Picked unit) Hero-level to ((Hero level of (Picked unit)) + 1), Show level-up graphics)
The issue occurs reliably (about every ~4 in 5 playthroughs) if you trigger the Wisp trigger WHILE 1 or more heroes are dead, thus leveling up a dead hero in a pick every unit call, and then attempt to revive all heroes in the unit group by entering the checkpoint. All heroes that were dead at the point of triggering the Wisp trigger are then not revived at the checkpoint trigger.

And as said in my initial post, the Revive trigger then fails to trigger even if you kill all the remaining heroes. It would seem that the heroes that fail to revive are being treated as alive somehow, which is why "All units of Group[0] are dead" is being treated as false? And for some reason, when I print out all the player ids in Group[0], it still includes the un-revived hero player ids, so it's not as if they're being removed from the unit group..

I do not understand why this would mess with reviving heroes in a unit group.. I suppose I can just set a flag and level every hero up once they are revived.. This shouldn't be happening, right? Don't get it.

The hero resurrection functions have a hidden buffer that can hold up to 7 dead heroes.
You can see this on this map, the [Esc] button resurrects all heroes on the map, kill more than 7 and see what happens.
The first hero to die disappears from the list and makes way for a new one.
Note: Each player has own buffer, 7 dead heroes for each player.
Thanks for the reply, I'll keep this in mind for the future. However Uncle here says hero buffers don't apply since I only have one hero per player.

1. Heroes don't decay, otherwise in a ladder game you'd lose your hero permanently if you waited too long to Revive them. Setting their Movement Type to "Fly" won't change this fact.

2. It's likely not a buffer issue since you're dealing with 1 Hero per Player (assumedly).

3. The (Pause) action causes all sorts of unwanted side effects and issues. There's a chance that it's the reason things are breaking here. I avoid it like the plague.

4. When a Hero dies, they don't immediately become Revivable. They have to officially "die" (death animation, death time, etc) before that happens. Although, maybe the "Revive Instantly" action bypasses this...

With that in mind, I attached a map with what appears to be a working setup. I think the main takeaway is that I stopped using the Pause action and replaced it with an alternative that Stuns the Heroes instead. I also tried to better organize things and added more Conditions to guarantee safe trigger executions.
Thank you very much for the map, I am still learning basic wc3 design patterns and memory leak handling and this has been extremely informative.

After many more late night hours I found the issue in a seemingly unrelated trigger (explained at the top), but it might still somehow be related to pausing the units.. However, the problem is resolved by removing a hero level up call within a Pick every unit call.

1. I should have realized I've never seen a hero corpse..
2. Good to know.
3. I do a lottt of pausing.. I will transition to stunning though in the other map I'm just starting.
4. So I should have a wait call before reviving heroes in case they've just recently died. Will throw that in.

Regarding organization, your "Red Leaves" trigger implies that you've created one trigger per Player. Often times a single trigger is all that's needed to manage things. You'll see in my map that I'm tracking Players in a Player Group, their Heroes in a Unit Group, and each individual Hero using a Unit-Array variable. This design gives me access to a Player and their Hero at any given moment, and allows me to have one "Player Leaves The Game" trigger that works for everyone. See my "Setup Game" trigger for more info, it ensures that all of my other triggers have a solid foundation to build upon.
Didn't know you could add events via another trigger. That is wild but so much easier than duping triggers everywhere.

In the following fragment of your Setup Game trigger, are you using variable PN because there would be a memory leak otherwise, or just because it's cleaner?
  • Setup Game Fragment
    • Events
      • Time - Elapsed game time is 0.01 seconds
    • Conditions
    • Actions
      • Unit Group - Pick every unit in (Units in Level1 <gen>) and do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Picked unit) is A Hero) Equal to True
            • Then - Actions
              • Set VariableSet PN = (Player number of (Owner of (Picked unit)))
              • Set VariableSet Player_Hero[PN] = (Picked unit)
              • Unit Group - Add Player_Hero[PN] to Unit_Group_Heroes
            • Else - Actions
Standardizing revives in the Checkpoint Update trigger is so much cleaner. Thanks for that.
 
Last edited:
Good, glad you figured it out.

In the following fragment of your Setup Game trigger, are you using variable PN because there would be a memory leak otherwise, or just because it's cleaner?
Just because it's cleaner.

You'll often be copying multiple Actions from one trigger and pasting them into another to be reused. So for example, let's say that your new trigger uses (Entering unit) as a Unit reference. All you would have to do is adjust PN to reference (Owner of (Entering unit)) and the rest of the Actions beneath it would continue to work. So it's a great pattern to follow for speeding up and simplifying development.

Regarding memory leaks. Unless you see the words "Destroy", "Remove", or "null", it's safe to assume that there is no "memory leak removal" going on. You'll see those terms used throughout the Trigger Editor. But "null" doesn't really come up unless you're working with local variables which are exclusive to Custom Script. However, "Destroy" for example is very common even among GUI actions:
  • Special Effect - Destroy (Last created special effect)
  • Floating Text - Destroy (Last created floating text)
4. So I should have a wait call before reviving heroes in case they've just recently died. Will throw that in.
Yes, but that's assuming that "Revive Hero Instantly" doesn't have special behavior to get around this.
 
Last edited:
Back
Top