• 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.

[Trigger] Unitgroups and removing them

Status
Not open for further replies.
Level 13
Joined
Jun 22, 2004
Messages
783
Hello there lads,

I have a somewhat akward question,
It's all theory, so no trigger examples.

When I create a unitgroup (x) add 4 units to it, and I would let the game tell me the amount of units in (x) has, it would tell me 4, logically
Then say unitgroup (y) = unitgroup (x) and I would remove unitgroup (y), I recon I would remove unitgroup (x) as well, right?
why?

When I asign another set of units to (x) and try to show the amount of units in (x) it gives me 0.

Would this mean that once I removed (y) I would remove (x) and not allow me to store anything in (x) anymore?

with kind Regards
 
Understand that a unitgroup is a handle -- that is, it's actually an object inside the game.

Imagine it just like a unit. Set (x) = 'unit' and then, set (y) = 'unit' (the same unit of course).
If you remove (x), you'll be removing (y) as well.

It's different with integers, reals, strings and some other types, as they are not handles. Also, you cannot remove these variables as you do with groups (or any kind of handle).
 
Level 13
Joined
Jun 22, 2004
Messages
783
Well I understand that objects are so called Handles, however what I was trying to find out, is that if I would remove Y I would be removing X, cause when I wanted to add something in X after I removed Y, it just didn't register it with the action add unit to unit group.

When I made the variable again, and told it had basically nothing, and then added those 4 units, it did register it again.
But what does it specifically do when I call DestroyGroup, does it destroy the content, or the entire variable? I asume the last one right?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,285
Groups are rather annoying objects, as they are highly complex in the way they function yet incredibly easy to interface.

From what I can tell (could be wrong).
When you create a group object, WC3 asigns a hashtable to it, and a list (linked array).
When you add units to it, it firstly hashes the unit in the hashtable, then it adds the unit to the list at the end. The hashtable is used to quickly tell if a group contains a unit or not while the list is used when doing actions like enuming. Overfilling the hashtable will result in slowdowns when setting and retreving if a unit is in a group (adding and removing units). You can not ever overfill the list, and it maintains a constant efficency (however it becomes slower to enum as there is more objects to loop through).

The problem with groups is that units which are removed (eithor by death or by triggers) still leave data in the group. This results in generally slower opperations (hashtables can become full), prevention of handle index recycling (as the unit handle is still stored in it) and unexpected data (enums suddenly are passed a null unit for every removed unit).

Luckilly there are easy fixes to these problems. Removing the unit from the group before it gets removed will free up its position in the group. Clearing the group with the native will remove all these "shadow" units equivently making it a blank new group. Finally destroying the group will free all resources used by the group, so is not a worry if you commonly do that (this is said to have other problems but I have yet to read them).

Groups are handles, this means that when you asign variables to them, you are giving them a pointer and not the object itself. Each variable in WC3 is 32 bits (each index in the case of arrays). Any object which needs less data like a boolean will waste 31 bits of data (not true as there are many kinds of boolean apparently due to a bug). Any object that needs more than 32 bits of data like strings and handles will use a 32 bit pointer which points to the data of the object.

This means that you can asign any number of handle variables to the same handle without any problem and each will point to the same thing in the game.
Let A be a group.
set B = A
set C = A
Both B and C will refer to exactly the same group as A, so if you destroy the group of A then that will also destroy the group that B and C point to. Also if you set A to another different group object, there is no reference left that A ever had a previous group and thus any actions on A will only be done to the last group you assigned A to.

Be aware that most JASS group actions take groups and change their content, while most GUI equivilents will make new groups which they return. Adding, removing and clearing a group will always need a valid group handle to be passed inorder to work, meaning if you destroy the group held in A, never assign A to a new group and then try using any of those natives on A, nothing productive will occur as there is no group being manipulated. In the case of GUI, remeber than most action pieces which give groups will make new groups, which leak unless caught and then destroyed after they are no longer needed.

As a final note, remeber than every handle variable you set to a handle reference will leave a counter attached to that handle index to prevent it being recycled. Thus inorder to let the game recycle handle indexes, it is important to null or change all handle variables once they are no longer holding an active handle object (this removes their garbage collector counters from that handle index) so as to let the game recycle them. Be warned that local handles can cause handle indexes to leak unless you null them by the end of the function due to a bug with WC3 which causes difined ones to not remove garbage collector counters.

Someone should probably add this 780 word post to some wiki or information page or something lol.
 
This deserves the "Long Post of the Year" award :D

From those 780 words I got that when you destroy a group, you actually destroy the object itself (the list). Therefore, you cannot do anything with the variable that pointed to it before assigning it to a new object.

That's why you got 0 units in (x) :p

[...] if you destroy the group held in A, never assign A to a new group and then try using any of those natives on A, nothing productive will occur as there is no group being manipulated.

Didn't get one thing: if I've already assigned A to a new group, why wouldn't there be any group being manipulated?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,285
Didn't get one thing: if I've already assigned A to a new group, why wouldn't there be any group being manipulated?

There would be a group being manipulated then, so what you said made no sense. However, if you made the group via the CreateGroup() native it will be entirly empty. Be aware that the natives which opperate behind the all units matching X do not make groups. The BJs in GUI do but the natives they use take a group and fill it with all units matching those conditions (I think they may even clear the group automatically).

If you look at the scripts of the BJs you will clearly see how they function.
 
Status
Not open for further replies.
Top