library AuraMan requires /*
*/ AIDS, /* http://www.thehelper.net/threads/advanced-indexing-data-storage.116539/
*/ UnitAlloc // https://www.dropbox.com/s/v0rdg9mqnyxeeik/UnitAlloc.j?dl=1
// AuraMan v1.0.0
// by jondrean
// d:05.04.16
// Manages aura abilities.
// ---------------
// USAGE
// ---------------
//! novjass
struct MyStruct extends array
static constant real tickRate=.03125000
// Interval of unit enumeration
method onInsert takes unit u returns nothing
method onErase takes unit u returns nothing
// Catch when unit is added/removed (OPTIONAL)
method getRange takes nothing returns real
static method filter takes nothing returns boolean
// Enumerate how distant units? Also who to add?
implement AuraMan
static method operator filtOwner takes nothing returns player
// Use inside of filter
static method insertHost takes unit u returns nothing
static method insertHostById takes integer u returns nothing
// Registers host (aura wielder)
method eraseHost takes unit u returns nothing
method eraseHostById takes integer u returns nothing
// Unregisters host
endstruct
//! endnovjass
// ---------------
globals
private group G=CreateGroup()
private player P
endglobals
// ---------------
module AuraMan
private thistype n // next node / first allocation node
private thistype p // previous node / rest of allocation nodes
private thistype h // head node
private unit u // node host
private boolean new // relevant node = DON'T deallocate
player pl // owner of host
// ---------------
implement UnitAlloc
private static timer C=CreateTimer()
debug private boolean used
// ---------------
static method operator filtOwner takes nothing returns player
return P
endmethod
// ---------------
private static method onExpire takes nothing returns nothing
local thistype this=thistype(0).next
local unit FoG
local thistype n
loop
if(UnitAlive(unit))then
set P=pl
call GroupEnumUnitsInRange(G,GetUnitX(unit),GetUnitY(unit),getRange(),Filter(function thistype.filter))
loop
set FoG=FirstOfGroup(G)
exitwhen(FoG==null)
set n=h
loop
if(n==0)then
//! runtextmacro AURAMAN_ALLOCN()
exitwhen(true)
endif
exitwhen(n.u==FoG)
set n=n.n
endloop
set n.new=true
call GroupRemoveUnit(G,FoG)
endloop
set n=h
loop
exitwhen(n==0)
if(n.new)then
set n.new=false
else
//! runtextmacro AURAMAN_DEALLOCN()
endif
set n=n.n
endloop
else
set n=h
loop
exitwhen(n==0)
//! runtextmacro AURAMAN_DEALLOCN()
set n=n.n
endloop
set pl=null
set h=0
//! runtextmacro UNITALLOC_DEALLOC("thistype","this")
if(empty)then
call PauseTimer(C)
endif
endif
set this=this.next
exitwhen(this==0)
endloop
endmethod
//! textmacro AURAMAN_ALLOCN
debug if(thistype(0).n==8191)then
debug call BJDebugMsg("|cffff0000"+thistype.onExpire.name+" ERROR: Exceeding node limit")
debug else
static if(thistype.onInsert.exists)then
call this.onInsert(FoG)
endif
set h.p=thistype(0).n
set thistype(0).n.n=h
set h=thistype(0).n
set thistype(0).n=thistype(0).n.p
set h.u=FoG
set h.new=true
debug endif
//! endtextmacro
//! textmacro AURAMAN_DEALLOCN
static if(thistype.onErase.exists)then
call this.onErase(n.u)
endif
set n.u=null
if(n==h)then
set h=n.n
set n.n.p=0
else
set n.p.n=n.n
set n.n.p=n.p
endif
set n.p=thistype(0).n
set thistype(0).n=n
//! endtextmacro
// ---------------
static method insertHostById takes thistype this returns nothing
local unit FoG
debug if(used)then
debug call BJDebugMsg("|cffff0000"+thistype.insertHostById.name+" ERROR: Double allocation")
debug return
debug endif
debug set used=true
if(empty)then
call TimerStart(C,thistype.tickRate,true,function thistype.onExpire)
endif
set pl=GetOwningPlayer(unit)
//! runtextmacro UNITALLOC_ALLOC("thistype","this")
set P=pl
call GroupEnumUnitsInRange(G,GetUnitX(unit),GetUnitY(unit),getRange(),Filter(function thistype.filter))
loop
set FoG=FirstOfGroup(G)
exitwhen(FoG==null)
//! runtextmacro AURAMAN_ALLOCN()
call GroupRemoveUnit(G,FoG)
endloop
endmethod
static method insertHost takes unit u returns nothing
debug if(GetUnitUserData(u)==0)then
debug call BJDebugMsg("|cffff0000"+thistype.insertHost.name+" ERROR: Removed/unindexed unit given")
debug return
debug endif
call insertHostById(GetUnitId(u))
endmethod
// ---------------
static method eraseHostById takes thistype this returns nothing
local thistype n=h
debug if(not used)then
debug call BJDebugMsg("|cffff0000"+thistype.eraseHostById.name+" ERROR: Double free")
debug return
debug endif
debug set used=false
loop
exitwhen(n==0)
//! runtextmacro AURAMAN_DEALLOCN()
set n=n.n
endloop
set h=0
set pl=null
//! runtextmacro UNITALLOC_DEALLOC("thistype","this")
if(empty)then
call PauseTimer(C)
endif
endmethod
static method eraseHost takes unit u returns nothing
debug if(GetUnitUserData(u)==0)then
debug call BJDebugMsg("|cffff0000"+thistype.eraseHost.name+" ERROR: Removed/unindexed unit given")
debug return
debug endif
call eraseHostById(GetUnitId(u))
endmethod
// ---------------
private static method onInit takes nothing returns nothing
local integer n=8190
loop
set thistype(n).p=n+1
exitwhen(n==1)
set n=n-1
endloop
set thistype(0).n=1
endmethod
endmodule
// ---------------
endlibrary