library Tracking_System
//Config - do NOT change the names of the variables
globals
real minlossincrement = 1.00 //this the minimum amount of mana a unit stands to lose before the system actually destroys the mana
real trackingtimeout = 0.04 //this is how often the timer that tracks all of the units will fire
endglobals
//End Config
//Private Data
struct distancedata
unit u
real x
real y
real d = 0.00
real lossfactor = 0.00
real destroydelay = 0.00
boolean dead = false
boolean destroyplease = false
method onDestroy takes nothing returns nothing
call SetUnitUserData( .u, 0 )
endmethod
endstruct
globals
private timer distancetimer = CreateTimer()
private distancedata array distancearray
private integer distancetotal = 0
endglobals
private function Distance_Update takes nothing returns nothing
local distancedata data
local real newx
local real newy
local real dx
local real dy
local real mana
local integer counter = 0
loop
exitwhen ( counter >= distancetotal )
set data = distancearray[counter]
if ( data.destroyplease ) then
//struct (tracking) is slated for destruction, so rearrange array members so you don't get gaps in the array and then destroy struct
set distancearray[counter] = distancearray[distancetotal - 1]
set distancetotal = distancetotal - 1
call data.destroy()
set counter = counter - 1 //because of the way we rearranged the array members, we need to make sure ALL members get checked
else
if ( data.dead ) then
//if unit is dead, we check to see if delay time is 0; if it is we slate struct for destruction, else we countdown the delay
if ( data.destroydelay <= 0.00 ) then
set data.destroyplease = true
else
set data.destroydelay = data.destroydelay - trackingtimeout
endif
else
set newx = GetUnitX( data.u )
set newy = GetUnitY( data.u )
set dx = newx - data.x
set dy = newy - data.y
set data.d = data.d + SquareRoot( dx * dx + dy * dy ) //update distance
if ( ( data.d * data.lossfactor ) >= minlossincrement ) then
//time to destroy mana
set mana = GetUnitState( data.u, UNIT_STATE_MANA )
if ( ( mana - data.d * data.lossfactor ) <= 0.00 ) then
call SetUnitState( data.u, UNIT_STATE_MANA, 0.00 )
else
call SetUnitState( data.u, UNIT_STATE_MANA, mana - data.d * data.lossfactor )
endif
set data.d = 0.00
endif
//update your unit coordinates
set data.x = newx
set data.y = newy
if ( GetWidgetLife( data.u ) < 0.405 ) then
//if unit is dead, it obviously can't move anymore, so we slate the struct (tracking) for destruction after the delay time
set data.dead = true
endif
endif
endif
set counter = counter + 1
endloop
if ( distancetotal == 0 ) then
//if no units are being tracked, running timer is useless and wastes memory, so pause timer
call PauseTimer( distancetimer )
endif
endfunction
//End Private Data
//Control Functions
function Distance_AddUnitTracking takes unit u, real lossfactor, real destroydelay returns nothing
local distancedata data = distancedata.create()
set data.u = u
set data.x = GetUnitX( u )
set data.y = GetUnitY( u )
set data.lossfactor = lossfactor
set data.destroydelay = destroydelay
call SetUnitUserData( u, data ) //since structs are integer arrays, we can save them in unit's Custom Value
if ( distancetotal == 0 ) then
call TimerStart( distancetimer, trackingtimeout, true, function Distance_Update )
//if there were no other units being tracked (i.e. timer was paused), start the timer
endif
//update your array variables
set distancearray[distancetotal] = data
set distancetotal = distancetotal + 1
endfunction
function Distance_ModifyLossFactor takes unit u, real lossfactor returns boolean
local distancedata data = GetUnitUserData( u )
if ( data == 0 ) then
return false //if no tracking exists on that unit, return false
endif
set data.lossfactor = lossfactor
return ( data.lossfactor == lossfactor ) //will return true if it successfully resets distance
endfunction
function Distance_DestroyTracking takes unit u returns boolean
local distancedata data = GetUnitUserData( u )
if ( data == 0 ) then
return false //if no tracking exists on that unit, return false
endif
set data.destroyplease = true
return ( data.destroyplease ) //will return true if it sucessfully sets up tracking to be destroyed
endfunction
//End Control Functions
endlibrary