luorax
Invasion in Duskwood
- Reaction score
- 67
I decided to write my own group system to replace GroupUtils. GroupUtils is a nice system, but:
-contains two useless hashtable;
-does not support data attaching;
-plus I've already made some little functions that I wanted to implement into my snippet.
So, the question is: what do you think about it? What should I improve, and how? Should I create empty groups at init as TimerUtils does?
Basically I want to hear some response.
Here is the code:
Note that this is for personal uses. I don't want to share it, or anything like that.
Thanks in advance!
-contains two useless hashtable;
-does not support data attaching;
-plus I've already made some little functions that I wanted to implement into my snippet.
So, the question is: what do you think about it? What should I improve, and how? Should I create empty groups at init as TimerUtils does?
Basically I want to hear some response.
Here is the code:
JASS:
library GroupTools initializer init uses Table
//:==========================================================================
//:========================== Configurables =================================
//:==========================================================================
globals
//This value corresponds to the max collision size of a unit in your map.
private constant real MAX_COLLISION_SIZE=197.
private constant boolean HOOK_FORGROUP=false
endglobals
//:==========================================================================
//:============================ The System ==================================
//:==========================================================================
globals
//---== Enumerations ==---
private group TempGroup=CreateGroup()
private group EnumGroup
private boolexpr EnumFilter
private boolexpr ConeFilter
private real EnumX=0.
private real EnumY=0.
private real EnumMinRadius=0.
private real EnumMaxRadius=0.
private real EnumConeRadius=0.
private real EnumConeAngle=0.
private real EnumConeViewAngle=0.
private Table RingTable
private Table ConeTable
//---== Group Refresh ==---
private group RefreshGroup
//---== GetClosestUnit() ==---
private unit ClosestUnit
private real ClosestDistance=0.
private real ClosestX=0.
private real ClosestY=0.
//---== Recycling ==---
private integer OFFSET=0x100000
private integer NO_DOUBLEFREE=0x65378463
private integer Count=0
private group array Groups
private integer array Datas
//---== Boolexpr Utils ==---
boolexpr BOOLEXPR_TRUE
boolexpr BOOLEXPR_FALSE
endglobals
//:===================================================
//: GroupRefresh()
//:===================================================
private function RefreshEnum takes nothing returns nothing
call GroupAddUnit(RefreshGroup,GetEnumUnit())
endfunction
function GroupRefresh takes group g returns nothing
set RefreshGroup=g
call GroupClear(RefreshGroup)
call ForGroup(RefreshGroup,function RefreshEnum)
endfunction
//:===================================================
//: GroupRecycling()
//:===================================================
function SetGroupData takes group g,integer value returns nothing
set Datas[GetHandleId(g)-OFFSET]=value
endfunction
function GetGroupData takes group g returns integer
return Datas[GetHandleId(g)-OFFSET]
endfunction
function NewGroup takes nothing returns group
if Count==0 then
set Groups[0]=CreateGroup()
else
set Count=Count - 1
endif
set Datas[GetHandleId(Groups[Count])-OFFSET]=0
return Groups[Count]
endfunction
function ReleaseGroup takes group g returns boolean
local integer id = GetHandleId(g)
if g==null then
return false
elseif Count==8191 then
call DestroyGroup(g)
return false
elseif Datas[id-OFFSET]==NO_DOUBLEFREE then
return false
endif
call GroupClear(g)
set Datas[id-OFFSET]=NO_DOUBLEFREE
set Groups[Count]=g
set Count=Count+1
return true
endfunction
//:===================================================
//: Hooks
//:===================================================
private function HookDestroyBoolExpr takes boolexpr b returns nothing
local integer id=GetHandleId(b)
if RingTable.boolexpr.has(id) then
call DestroyBoolExpr(RingTable.boolexpr[id])
call RingTable.boolexpr.remove(id)
elseif ConeTable.boolexpr.has(id) then
call DestroyBoolExpr(ConeTable.boolexpr[id])
call ConeTable.boolexpr.remove(id)
endif
endfunction
private function HookForGroup takes group g,code c returns nothing
set EnumGroup=g
endfunction
hook DestroyBoolExpr HookDestroyBoolExpr
static if HOOK_FORGROUP then
hook ForGroup HookForGroup
endif
//:===================================================
//: Enumerations
//:===================================================
function GetEnumGroup takes nothing returns group
return EnumGroup
endfunction
function ForGroupEx takes group g,code c returns nothing
static if not HOOK_FORGROUP then
set EnumGroup=g
endif
call ForGroup(g,c)
endfunction
private function FilterFunc takes nothing returns boolean
return not IsUnitInRangeXY(GetFilterUnit(),EnumX,EnumY,EnumMinRadius) and IsUnitInRangeXY(GetFilterUnit(),EnumX,EnumY,EnumMaxRadius)
endfunction
function GroupEnumUnitsInRing takes group g,real x,real y,real minRadius,real maxRadius,boolexpr filter returns nothing
local integer id=0
local real prevX=EnumX
local real prevY=EnumY
local real prevMinRadius=EnumMinRadius
local real prevMaxRadius=EnumMaxRadius
set EnumX=x
set EnumY=y
set EnumMinRadius=minRadius
set EnumMaxRadius=maxRadius
if filter==null then
set filter=EnumFilter
else
set id=GetHandleId(filter)
if RingTable.boolexpr.has(id) then
set filter=RingTable.boolexpr[id]
else
set filter=And(EnumFilter,filter)
set RingTable.boolexpr[id]=filter
endif
endif
call GroupEnumUnitsInRange(g,x,y,maxRadius+MAX_COLLISION_SIZE,filter)
set EnumX=prevX
set EnumY=prevY
set EnumMinRadius=prevMinRadius
set EnumMaxRadius=prevMaxRadius
endfunction
function GroupEnumUnitsInRangeEx takes group g,real x,real y,real radius,boolexpr filter returns nothing
call GroupEnumUnitsInRing(g,x,y,0.,radius,filter)
endfunction
private function ConeFilterFunc takes nothing returns boolean
local real angle=bj_RADTODEG*Atan2(GetUnitY(GetFilterUnit())-EnumY,GetUnitX(GetFilterUnit())-EnumX)
return IsUnitInRangeXY(GetFilterUnit(),EnumX,EnumY,EnumConeRadius) and/*
*/ angle<=EnumConeViewAngle+EnumConeAngle and/*
*/ angle>=EnumConeViewAngle-EnumConeAngle
endfunction
function GroupEnumUnitsCone takes group g,real x,real y,real radius,real currentAngle,real angle,boolexpr filter returns nothing
local integer id=0
local real prevX=EnumX
local real prevY=EnumY
local real prevConeRadius=EnumConeRadius
local real prevConeAngle=EnumConeAngle
local real prevConeViewAngle=EnumConeViewAngle
set EnumX=x
set EnumY=y
set EnumConeRadius=radius
set EnumConeAngle=angle/2
set EnumConeViewAngle=currentAngle
if filter==null then
set filter=ConeFilter
else
set id=GetHandleId(filter)
if ConeTable.boolexpr.has(id) then
set filter=ConeTable.boolexpr[id]
else
set filter=And(ConeFilter,filter)
set ConeTable.boolexpr[id]=filter
endif
endif
call GroupEnumUnitsInRange(g,x,y,radius+MAX_COLLISION_SIZE,filter)
set EnumX=prevX
set EnumY=prevY
set EnumConeRadius=prevConeRadius
set EnumConeAngle=prevConeAngle
set EnumConeViewAngle=prevConeViewAngle
endfunction
//:===================================================
//: GetClosestUnit
//:===================================================
private function ClosestEnum takes nothing returns nothing
local real x=GetUnitX(GetEnumUnit())-ClosestX
local real y=GetUnitY(GetEnumUnit())-ClosestY
local real d=SquareRoot(x*x+y*y)
if d < ClosestDistance then
set ClosestDistance=d
set ClosestUnit=GetEnumUnit()
endif
endfunction
function GetClosestUnitInRange takes real x, real y, real radius, boolexpr filter returns unit
set ClosestX=x
set ClosestY=y
set ClosestUnit=null
set ClosestDistance=999999.
call GroupEnumUnitsInRangeEx(TempGroup,x,y,radius,filter)
call ForGroup(TempGroup,function ClosestEnum)
return ClosestUnit
endfunction
function GetClosestUnitInGroup takes group g,real x,real y returns unit
set ClosestX=x
set ClosestY=y
set ClosestUnit=null
set ClosestDistance=999999.
call ForGroup(g,function ClosestEnum)
return ClosestUnit
endfunction
private function BoolTrue takes nothing returns boolean
return true
endfunction
private function BoolFalse takes nothing returns boolean
return false
endfunction
private function init takes nothing returns nothing
set BOOLEXPR_TRUE=Condition(function BoolTrue)
set BOOLEXPR_FALSE=Condition(function BoolFalse)
set EnumFilter=Filter(function FilterFunc)
set ConeFilter=Filter(function ConeFilterFunc)
set RingTable=Table.create()
set ConeTable=Table.create()
endfunction
endlibrary
Note that this is for personal uses. I don't want to share it, or anything like that.
Thanks in advance!