library TorchSystem
//***************************************************************************
// Torch Light
// ¯¯¯¯¯¯¯¯¯¯¯
// Provides a light radius for any given unit based on that unit's facing
// rotation. Each torch is created by "torchlight.create()":
//
// torchlight.create() --> takes a unit parameter
// @subject > the unit that will acquire the light
//
// It will also be necessary to be able to acquire a specific unit's torch
// in case special actions are to be performed, such as "kill" and "pause".
//
// torchlight[] --> takes a unit parameter
// @subject > unit data used to obtain the appropriate
// torch
//
// local torchlight torch
// call torchlight.create(udg_TempUnit)
//
// //even though we do not have direct reference now, we can obtain it
// //by using the static method operator
// set torch = torchlight[udg_TempUnit]
//
// The static method operator uses a loop that iterates through the entire
// stack until finding the correct one. The more torches there are the slower
// this will respond, obviously.
//
// Each unit is only capable of acquiring one torch. If torches are created
// multiple times for each unit, only the first that is added will remain the
// other constructors will be ignored.
//
struct torchlight
private unit subject = null
private unit torch = null
private static timer looptmr = CreateTimer()
private static constant real looptmrRef = 0.033
private boolean mkill = false
private boolean mpause = false
private static thistype array stack
private static unit array stackref
private static integer stacksize = 0
private integer stackindex
private static constant real torchOffset = 300
private static constant integer torchUnitId = 'hfoo'
//this will allow torches to be referenced per unit. each unit will
//not be able to have multiple torches, and as such this can only
//return the unit-specific torch or a null struct (0).
static method operator [] takes unit subject returns thistype
local integer i=0
loop
exitwhen(i==stacksize)
if(stackref[i]==subject) then
return stack[i]
endif
set i=i+1
endloop
return 0 //returns 0 if the unit has no torch.
endmethod
private method onDestroy takes nothing returns nothing
set thistype.stacksize=thistype.stacksize-1
set thistype.stack[stackindex]=thistype.stack[thistype.stacksize]
set thistype.stack[stackindex].stackindex=stackindex
call RemoveUnit(torch)
if(thistype.stacksize==0) then
call PauseTimer(thistype.looptmr)
endif
endmethod
method kill takes nothing returns nothing
set mkill=true
endmethod
method pause takes boolean flag returns nothing
set mpause=flag
endmethod
static method loopFunc takes nothing returns nothing
local integer i=stacksize-1
local thistype data
local real x
local real y
local real f
loop
exitwhen(i<=0)
set data=stack[i]
if(data!=0) then
if(data.mkill) then
//if the torch is to be destroyed then kill it before
//updating it's position.
call data.destroy()
elseif not(data.mpause) then
set f=GetUnitFacing(data.subject)
set x=GetUnitX(data.subject) +Cos(f*bj_RADTODEG)
set y=GetUnitY(data.subject) +Sin(f*bj_RADTODEG)
//the only thing necessary to adjust for the torch is the
//position of the light emitter.
call SetUnitX(data.torch, x)
call SetUnitY(data.torch, y)
endif
endif
set i=i-1
endloop
endmethod
static method create takes unit subject returns thistype
local thistype data
local real x
local real y
local real f
if(thistype[subject]!=0) then
return 0
endif
set data=allocate()
set x=GetUnitX(subject)
set y=GetUnitY(subject)
set f=GetUnitFacing(subject)
if(stacksize==0) then
call TimerStart(looptmr, looptmrRef, true, function thistype.loopFunc)
endif
set data.stackindex=stacksize
set stackref[stacksize]=subject
set stack[stacksize]=data
set stacksize=stacksize+1
set data.subject=subject
set x=x+torchOffset*Cos(f*bj_DEGTORAD)
set y=y+torchOffset*Sin(f*bj_DEGTORAD)
set data.torch=CreateUnit(GetOwningPlayer(subject), torchUnitId, x, y, 0)
return data
endmethod
endstruct
endlibrary