- Joined
- Jun 23, 2009
- Messages
- 299
A small snippet I made a long time ago to find a nearest/furthest unit that I cleaned up a bunch recently, it might be too simple as a submission or may not be as good as the current alternative but I'd like to hear your opinion on this:
Comparing it to the closest alternative that's present here on the Hive (GetClosestWidget):
Pros:
Cons:
vJASS:
library FindUnits
//* ============================================================================= *
//* by Michael Peppers (v1.2 11/01/2022) *
//* *
//* To find units in a given area. *
//* *
//* 4 functions avaiable: *
//* ----------------------------------------------------------------------------- *
//* 1.0: *
//* FindNearestUnit(real srcX, real srcY, real range, UnitSearchCond condition) *
//* FindFarthestUnit(real srcX, real srcY, real range, UnitSearchCond condition) *
//* ----------------------------------------------------------------------------- *
//* 1.2: *
//* FindAnyNearestUnit(real srcX, real srcY, real range) *
//* FindAnyFarthestUnit(real srcX, real srcY, real range) *
//* ----------------------------------------------------------------------------- *
//* *
//* 1.0 needs three real values and a condition: X, Y and range are the reals, *
//* where X and Y are the point defining the center of the unit search *
//* and range... well, is the range of the area in which we do the search. *
//* The condition is used for... conditions, such as checking if a unit is alive, *
//* is owned by a particular player etc., the condition has to be a function and *
//* can be private. 1.2 finds units without conditions. They return a unit value. *
//* ============================================================================= *
//Quick examples on how to use it:
//
// 1) With conditions:
//
//condition: unit we search for is alive and is a peasant
//private function Cond takes unit u returns boolean
//return (GetUnitTypeId(u) == 'hpea') and (GetUnitState(u, UNIT_STATE_LIFE) > 0.405)
//endfunction
//
//call IssueTargetOrder(Pig, "attack", FindNearestUnit(GetUnitX(Pig), GetUnitY(Pig), 1000, Cond))
//
// 2) Without conditions:
//
//call IssueTargetOrder(Pig, "attack", FindAnyNearestUnit(GetUnitX(Pig), GetUnitY(Pig), 1000))
public function interface UnitSearchCond takes unit u returns boolean
globals
private UnitSearchCond func
private unit Unit
private real Dist
private real unitX
private real unitY
private group ENUM = CreateGroup()
private boolean nearest
endglobals
private function AnyUnitSearch takes nothing returns boolean
local real dx = unitX - GetUnitX(GetFilterUnit())
local real dy = unitY - GetUnitY(GetFilterUnit())
local real dist = (dx * dx + dy * dy)
if nearest then
if (Dist < 0) or (dist < Dist) then
set Unit = GetFilterUnit()
set Dist = dist
endif
else
if (Dist < 0) or (dist > Dist) then
set Unit = GetFilterUnit()
set Dist = dist
endif
endif
return false
endfunction
private function UnitSearch takes nothing returns boolean
local real dx
local real dy
local real dist
if func != 0 then
if func.evaluate(GetFilterUnit()) == true then
set dx = unitX - GetUnitX(GetFilterUnit())
set dy = unitY - GetUnitY(GetFilterUnit())
set dist = (dx * dx + dy * dy)
if nearest then
if (Dist < 0) or (dist < Dist) then
set Unit = GetFilterUnit()
set Dist = dist
endif
else
if (Dist < 0) or (dist > Dist) then
set Unit = GetFilterUnit()
set Dist = dist
endif
endif
endif
endif
return false
endfunction
function FindNearestUnit takes real srcX, real srcY, real range, UnitSearchCond condition returns unit
set unitX = srcX
set unitY = srcY
set Dist = -1
set Unit = null
set nearest = true
set func = condition
call GroupEnumUnitsInRange(ENUM, unitX, unitY, range, Condition(function UnitSearch))
return Unit
endfunction
function FindFarthestUnit takes real srcX, real srcY, real range, UnitSearchCond condition returns unit
set unitX = srcX
set unitY = srcY
set Dist = -1
set Unit = null
set nearest = false
set func = condition
call GroupEnumUnitsInRange(ENUM, unitX, unitY, range, Condition(function UnitSearch))
return Unit
endfunction
function FindAnyNearestUnit takes real srcX, real srcY, real range returns unit
set unitX = srcX
set unitY = srcY
set Dist = -1
set Unit = null
set nearest = true
call GroupEnumUnitsInRange(ENUM, unitX, unitY, range, Condition(function AnyUnitSearch))
return Unit
endfunction
function FindAnyFarthestUnit takes real srcX, real srcY, real range returns unit
set unitX = srcX
set unitY = srcY
set Dist = -1
set Unit = null
set nearest = false
call GroupEnumUnitsInRange(ENUM, unitX, unitY, range, Condition(function AnyUnitSearch))
return Unit
endfunction
endlibrary
Comparing it to the closest alternative that's present here on the Hive (GetClosestWidget):
Pros:
- More efficient as it uses a bunch less globals, the group used for the actual calculation never gets populated and it avoids any unnecessary calculations (like dividing the distance by 10000)
- Can search for the farthest unit in range if anybody ever needs to do that
Cons:
- Limited to just single units (although I have similar snippets around for Destructible and Tree searches, the latter of which used PitzerMike's version of IsDestructableTree)
Last edited: