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

Effortless and Efficient Unit Group functions for GUI Triggers

Effortless and Efficient Unit Group functions for GUI Triggers


Background

This is a tutorial for GUI users to learn how to use the new natives for Unit Group functions while mapmaking. A lot of people, I assume, are still using GUI triggers because they don't have more time to devote to learning a script. As someone who started off using GUI for years and relying on systems written for GUI, I know that people stick with GUI because it is intuitive and faster for doing simple things. If you have time to learn about the JASS script, I don't support staying with GUI, but I understand the decision nonetheless. Hopefully, after this tutorial, GUI users will be able to benefit from the new natives given to us all, and further stay away from the hilariously inefficient Unit Group actions that are provided by WE.

Requirements & Notes before Reading

  • I assume you know how to use the "Custom Script" action in GUI
  • In this tutorial I will use the variable names with and without the udg_ prefix interchangeably. That is because variables created in GUI are global, and hence have the udg_ prefix in "Custom Script".

Doing Unit Group functions

  1. Natives you need:
    • BlzGroupGetSize takes group whichGroup returns integer => its syntax is BlzGroupGetSize(group)
    • BlzGroupUnitAt takes group whichGroup, integer index returns unit => its syntax is BlzGroupUnitAt(group,integer)
  2. Variables you need:
    • A group variable: TempGroup - of course
    • 2 integer variables: TempCount - the number of units in the unit group; TempIndex - the indexing element inside the group
    • A unit variable: TempEnum - equivalent to (Picked unit) in the unit group
  3. How to:
    1641484371738.png
    • Set the first variable: set udg_TempCount = BlzGroupGetSize(udg_TempGroup)
    • Create a For "each TempIndex variable" loop
    • Set the number of loops to TempCount
    • Inside the For loop: set udg_TempEnum = BlzGroupUnitAt(udg_TempGroup,udg_TempIndex-1)
    • It is done. Now inside each loop, udg_TempEnum will be the (udg_TempIndex-1)th unit from udg_TempGroup. You can do the same things to udg_TempEnum as you would with (Picked unit) inside a "Pick Every Unit And..." loop
  4. Explanation:
    • BlzGroupGetSize is the faster way to count a unit group than the GUI function (which is actually a For loop function that counts units in the group one by one)
    • BlzGroupUnitAt picks out the Xth unit from a unit group. This function is zero-indexed, however, so the first unit will use index 0, the second unit will use index 1, and so on.

Removing Units from the Unit Group?

  1. Before proceeding, bear in mind: If you do Unit Group functions this way, removing units will not be as straightforward as the case with the other GUI function. You shouldn't attempt to remove udg_TempEnum from the group mid-loop, because it will shift the indices of the remaining units backwards, causing some units to be missed in the loop.
  2. Accessory natives you have:
    • BlzGroupRemoveGroupFast takes group whichGroup, group removeGroup returns integer => its syntax is BlzGroupRemoveGroupFast(group1,group2)
  3. How to:
    bSt96pa.png
    1641485540468.png
    • An accessory group variable: GroupToRemove
    • Inside the For loop: Add TempEnum to GroupToRemove
    • After the For loop is finished: call BlzGroupRemoveGroupFast(udg_GroupToRemove,udg_TempGroup)
    • Clear the GroupToRemove group.
  4. Explanation:
    • BlzGroupRemoveGroupFast excludes all units from group2 that belong in group1. group1 is the one that remains the same and group2 is the one that loses the units. This function, as the name suggests, is faster than the GUI counterpart (which is also a loop that removes units one by one).

Random Unit from Unit Group

  1. Using the new natives, it's also very simple to make a more efficient "Random Unit from Unit Group" function.
    • Basically, after setting the variable for the group's number of units, get a random number between 1 and that variable.
    • Then, use BlzGroupUnitAt to get the unit with that number in the unit group. And of course, since the function is zero-indexed, we move the number back by one.
  2. How to:
    1642606273899.png

Additional remarks

  • The opposite of BlzGroupRemoveGroupFast, BlzGroupAddGroupFast also exists, using the same syntax.
 
Last edited:

Chaosy

Tutorial Reviewer
Level 40
Joined
Jun 9, 2011
Messages
13,183
Variables you need image can be cropped down into 1 5th of the height.
Or just display in text form, I think it's fair to say that anyone who is looking for this information knows how to create a variable.

Another suggestion, but not a demand/requirement
Given that you'd probably use this many times in a project, it might be worth making a 'system' for this.
Something along the lines of:

set tempGroup = whatever group
run trigger "TriggerThatContainsTheCustomScript"
GUI loop here

This would reduce the amount of custom scripts which might be desired.

Otherwise.. seems good to me.
 
Top