library IdleWorkersSystem initializer Init
/**
* Baradé's Idle Workers System 1.0
*
* Allows detecting idle workers for every player. This can be useful for custom UI systems.
* There is no idle order event. Hence, it can be checked periodically or on request.
* Note that idle workers which have been revived by "Animate Dead" won't be counted as idle workers
* in the standard button and neither by this system by default.
* Besides, transported workers are not included by the standard button.
* You can customize these settings by changing the constants' values.
*
* API:
*
* function GetIdleWorkers takes player whichPlayer returns group
*
* Returns all idle workers for the given player.
*
* function GetIdleWorkersSize takes player whichPlayer returns integer
*
* Returns the number of all idle workers for the given player.
*
* function IsUnitIdleWorker takes unit whichUnit returns boolean
*
* Returns if the given unit is an idle worker of its owner.
*
* function IsOrderIdle takes integer orderId returns boolean
*
* Returns if the given order is an idle order.
*
* function IsUnitAnimateDead takes unit whichUnit returns boolean
*
* Returns if the given unit is a target of "Animate Dead" abilities.
*
* function RefreshIdleWorkers takes player whichPlayer returns nothing
*
* Manually refreshes the idle workers for the given player.
*
* function RefreshAllIdleWorkers takes nothing returns nothing
*
* Manually refreshes the idle workers for all players.
*
* function PauseIdleWorkerDetection takes nothing returns nothing
*
* Pauses the idle worker detection.
*
* function ResumeIdleWorkerDetection takes nothing returns nothing
*
* Resumes the idle worker detection.
*
* function StartIdleWorkerDetection takes nothing returns nothing
*
* Starts the timer for idle worker detection.
*/
native UnitAlive takes unit id returns boolean
globals
// Automatically starts the order detection timer in the beginning of the game if this value is true.
public constant boolean USE_ORDER_DETECTION_TIMER = false
// The interval in which the order detection timer will update the idle worker groups.
public constant real ORDER_DETECTION_TIMEOUT = 0.03
public constant integer ORDER_NONE = 0
public constant integer ORDER_HOLD_POSITION = 851993
// Does not included idle workers which have been revived with "Animate Dead" abilities if this value is true.
// This is the standard behaviour of Warcraft.
public constant boolean EXCLUDE_ANIMATE_DEAD_TARGETS = true
// Does not included idle workers which are loaded in transports if this value is true.
// This is the standard behaviour of Warcraft.
public constant boolean EXCLUDE_LOADED_TARGETS = true
// Removes idle workers from the idle worker groups automatically when they are removed from the game.
public constant boolean HOOK_REMOVE_UNIT = true
private timer orderDetectionTimer = CreateTimer()
private group array idleWorkers
endglobals
function IsUnitAnimateDead takes unit whichUnit returns boolean
return (UnitHasBuffBJ(whichUnit, 'BUan') or UnitHasBuffBJ(whichUnit, 'BUad'))
endfunction
function IsOrderIdle takes integer orderId returns boolean
return orderId == ORDER_NONE or orderId == ORDER_HOLD_POSITION
endfunction
private function FilterIsIdleLivingWorker takes nothing returns boolean
local unit filterUnit = GetFilterUnit()
local boolean result = IsUnitType(filterUnit, UNIT_TYPE_PEON) and UnitAlive(filterUnit) and IsOrderIdle(GetUnitCurrentOrder(filterUnit))
static if (EXCLUDE_ANIMATE_DEAD_TARGETS) then
if (result) then
set result = not IsUnitAnimateDead(filterUnit)
endif
endif
static if (EXCLUDE_LOADED_TARGETS) then
if (result) then
set result = not IsUnitLoaded(filterUnit)
endif
endif
set filterUnit = null
return result
endfunction
function RefreshIdleWorkers takes player whichPlayer returns nothing
local integer playerId = GetPlayerId(whichPlayer)
call GroupClear(idleWorkers[playerId])
call GroupEnumUnitsOfPlayer(idleWorkers[playerId], whichPlayer, Filter(function FilterIsIdleLivingWorker))
endfunction
function RefreshAllIdleWorkers takes nothing returns nothing
local integer i = 0
loop
call RefreshIdleWorkers(Player(i))
set i = i + 1
exitwhen (i >= bj_MAX_PLAYERS)
endloop
endfunction
function GetIdleWorkers takes player whichPlayer returns group
return idleWorkers[GetPlayerId(whichPlayer)]
endfunction
function GetIdleWorkersSize takes player whichPlayer returns integer
return BlzGroupGetSize(idleWorkers[GetPlayerId(whichPlayer)])
endfunction
function IsUnitIdleWorker takes unit whichUnit returns boolean
return IsUnitInGroup(whichUnit, idleWorkers[GetPlayerId(GetOwningPlayer(whichUnit))])
endfunction
function PauseIdleWorkerDetection takes nothing returns nothing
call PauseTimer(orderDetectionTimer)
endfunction
function ResumeIdleWorkerDetection takes nothing returns nothing
call ResumeTimer(orderDetectionTimer)
endfunction
function StartIdleWorkerDetection takes nothing returns nothing
call TimerStart(orderDetectionTimer, ORDER_DETECTION_TIMEOUT, true, function RefreshAllIdleWorkers)
endfunction
private function Init takes nothing returns nothing
local integer i = 0
loop
set idleWorkers[i] = CreateGroup()
set i = i + 1
exitwhen (i >= bj_MAX_PLAYERS)
endloop
static if (USE_ORDER_DETECTION_TIMER) then
call StartIdleWorkerDetection()
endif
endfunction
private function RemoveUnitHook takes unit whichUnit returns nothing
static if (HOOK_REMOVE_UNIT) then
if (IsUnitIdleWorker(whichUnit)) then
call GroupRemoveUnit(idleWorkers[GetPlayerId(GetOwningPlayer(whichUnit))], whichUnit)
endif
endif
endfunction
static if (HOOK_REMOVE_UNIT) then
hook RemoveUnit RemoveUnitHook
endif
endlibrary