Group API
From WarCraft3
The Group API lets you manage collection of units, the handle to a collection of units is called a group. IsUnitInGroup checks if a unit is in the group, but isn't part of the Group API according to blizzard.
Contents |
Code
//============================================================================
// Group API
//
native CreateGroup takes nothing returns group
native DestroyGroup takes group whichGroup returns nothing
native GroupAddUnit takes group whichGroup, unit whichUnit returns nothing
native GroupRemoveUnit takes group whichGroup, unit whichUnit returns nothing
native GroupClear takes group whichGroup returns nothing
native GroupEnumUnitsOfType takes group whichGroup, string unitname, boolexpr filter returns nothing
native GroupEnumUnitsOfPlayer takes group whichGroup, player whichPlayer, boolexpr filter returns nothing
native GroupEnumUnitsOfTypeCounted takes group whichGroup, string unitname, boolexpr filter, integer countLimit returns nothing
native GroupEnumUnitsInRect takes group whichGroup, rect r, boolexpr filter returns nothing
native GroupEnumUnitsInRectCounted takes group whichGroup, rect r, boolexpr filter, integer countLimit returns nothing
native GroupEnumUnitsInRange takes group whichGroup, real x, real y, real radius, boolexpr filter returns nothing
native GroupEnumUnitsInRangeOfLoc takes group whichGroup, location whichLocation, real radius, boolexpr filter returns nothing
native GroupEnumUnitsInRangeCounted takes group whichGroup, real x, real y, real radius, boolexpr filter, integer countLimit returns nothing
native GroupEnumUnitsInRangeOfLocCounted takes group whichGroup, location whichLocation, real radius, boolexpr filter, integer countLimit returns nothing
native GroupEnumUnitsSelected takes group whichGroup, player whichPlayer, boolexpr filter returns nothing
native GroupImmediateOrder takes group whichGroup, string order returns boolean
native GroupImmediateOrderById takes group whichGroup, integer order returns boolean
native GroupPointOrder takes group whichGroup, string order, real x, real y returns boolean
native GroupPointOrderLoc takes group whichGroup, string order, location whichLocation returns boolean
native GroupPointOrderById takes group whichGroup, integer order, real x, real y returns boolean
native GroupPointOrderByIdLoc takes group whichGroup, integer order, location whichLocation returns boolean
native GroupTargetOrder takes group whichGroup, string order, widget targetWidget returns boolean
native GroupTargetOrderById takes group whichGroup, integer order, widget targetWidget returns boolean
// This will be difficult to support with potentially disjoint, cell-based regions
// as it would involve enumerating all the cells that are covered by a particularregion
// a better implementation would be a trigger that adds relevant units as they enter
// and removes them if they leave...
native ForGroup takes group whichGroup, code callback returns nothing
native FirstOfGroup takes group whichGroup returns unitConfused? Jass help forum!Adding units
Units can be added to a group one by one with GroupAddUnit or many at the same time with one of the GroupEnumUnits natives. All GroupEnumUnits natives takes a boolexpr arguments that is the condition specifying if the unit will be added to the group or not. Inside the boolexpr you use GetFilterUnit to get the unit that is currently considered.
Example
// Filters out all units who have more than 100 life
function IsWeak takes nothing returns boolean
return GetUnitState(GetFilterUnit(), UNIT_STATE_LIFE) <= 100
endfunction
//...
call GroupEnumUnitsOfPlayer(someGroup, Player(0), Filter(function IsWeak))
Enumerating
There are two different ways to enumerate the units in a group, the first one is to use ForGroup, the second one is to use FirstOfGroup. There is also a third way to enumerate units, without storing them in a group.
FirstOfGroup
local unit current
loop
set current = FirstOfGroup(someGroup)
exitwhen current == null
// do stuff with current
call GroupRemoveUnit(someGroup, current)
endloop
Pros
- Can use local variables declared in the current function
- Easy to break out of the loop before all units are processed
Cons
- Easier to get wrong, forgetting the GroupRemoveUnit is a common source of errors.
- A lower level construct than ForGroup, meaning more syntax and less intent.
- Empties the group.
ForGroup
function DoStuff takes nothing returns nothing
local unit current = GetEnumUnit()
// do stuff with current
endfunction
//...
call ForGroup(someGroup, function DoStuff)
Pros
- Hard to get wrong
- Easier to introduce explaining functions
Cons
- Passing parameters to the callback requires using globals
- No easy way to break out prematurely
boolexpr as callback
This type of enumeration works well when we have code like this:
function EnumCondition takes nothing returns boolean
return someCondition(GetFilterUnit())
endfunction
function EnumAction takes nothing returns nothing
local unit u = GetEnumUnit()
// do something with the unit
endfunction
function Actions takes nothing returns nothing
local group g = CreateGroup()
call GroupEnumUnits*(g, ..., Condition(function EnumCondition))
call ForGroup(g, function EnumAction)
call DestroyGroup(g)
set g = null
endfunction
As you can see, we are creating a group just to destroy it after we've enumerated it. We can use a dummy group together with with a "condition" that makes the actions on the filter unit to remove the need of creating/destroying a group all the time.
function EnumAction takes nothing returns boolean
local unit u = GetFilterUnit()
if someCondition(u) then
// do something with the unit
endif
return false
endfunction
function Actions takes nothing returns nothing
call GroupEnumUnits*(DUMMYGROUP, ..., Condition(function EnumAction))
endfunction
Note that the condition always returns false so the dummy group will always be empty.
Pros
- Faster than ForGroup
- Almost as easy to get right as ForGroup
Cons
- Only works when the enumeration happens at the same place as the selection
- Can't use combined boolexprs