A simple but useful library to retrieve the source of a UnitInRange event when there are multiple units registered to one trigger. Credits to Cheezman for the idea, but his original code didn't work right, so I hereby present my version of:
GetSourceUnit
Requires:
TimerUtils by Vexorian
Table by Vexorian
Jass:
//===========================================================================//==//== GetSourceUnit()//==//== This library lets you store and retrive the source//== unit of a TriggerRegisterUnitInRange() event.//== Especially useful for Auras.//== ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯//==//== How to use//== ¯¯¯¯¯¯¯¯¯¯//== function TriggerRegisterUnitInRangeWithSource takes trigger whichTrigger, unit whichUnit, real range, boolexpr filter returns event//== - Just like the normal one, but saves whichUnit//==//== function GetSourceUnit takes nothing returns unit//== - Returns the source unit of the event//==//== function GetSourceUnitFromTrigger takes trigger whichTrigger, unit triggerUnit returns unit//== - The same as GetSourceUnit, but works outside of a functions events and needs to be passed the triggering trigger and unit//==//== function ClearSource takes trigger whichTrigger returns nothing//== - Nullifies the source (just for cleanup)//==//==//== Requirements//== ¯¯¯¯¯¯¯¯¯¯¯¯//== - WarCraft III 1.24 by Blizzard (duh)//== - JassHelper by Vexorian//== - TimerUtils by Vexorian//== - Table by Vexorian//==//==//== Important Notes//== ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯//== - If two units (who are registered to the same trigger) are close together//== when a unit triggers the event, it may return the wrong source.//==//== - If you want the GetSourceUnit() to null the source automatically//== set ClearSourceTime larger than 0.//==//==//== Version 2.1//== ¯¯¯¯¯¯¯¯¯¯¯//== Coded by Elements of Water//== Inspired by Cheezeman//==//===========================================================================library InRangeWithSource initializer Init requires Table, TimerUtils
globalsprivateconstantinteger MAX_INSTANCES =408000privateconstantinteger MAX_UNITS =100privateconstantreal OFFSET =20.00publicreal ClearSourceTime =2.00private HandleTable ht
endglobalsprivatestruct Data [MAX_INSTANCES]unitarray registered[MAX_UNITS]realarray registered_dist[MAX_UNITS]integer index =0unit currentSource =nullendstructfunction TriggerRegisterUnitInRangeWithSource takestrigger whichTrigger,unit whichUnit,real range,boolexpr filter returnseventlocal Data d
if ht.exists(whichTrigger)thenset d = ht[whichTrigger]elseset d = Data.create()set ht[whichTrigger]= d
endifif d.index< MAX_UNITS thenset d.registered[d.index]= whichUnit
set d.registered_dist[d.index]= range + OFFSET
set d.index= d.index+1elsedebugcallBJDebugMsg("InRangeWithSource: Number of units registered to trigger exceeds MAX_UNITS. Please increase MAX_UNITS or register fewer units")returnnullendifreturnTriggerRegisterUnitInRange(whichTrigger, whichUnit, range, filter)endfunctionprivatefunction ClearSourceTimed takesnothingreturnsnothinglocaltimer t =GetExpiredTimer()local Data d = GetTimerData(t)set d.currentSource=nullcall ReleaseTimer(t)set t =nullendfunctionfunction ClearSource takestrigger whichTrigger returnsnothinglocal Data d = ht[whichTrigger]set d.currentSource=nullendfunctionfunction GetSourceUnitFromTrigger takestrigger whichTrigger,unit triggerUnit returnsunitlocal Data d
localinteger i =0localunit u
localreal udist
localreal dx
localreal dy
localreal dist
localtimer t
if ht.exists(whichTrigger)thenset d = ht[whichTrigger]elsedebugcallBJDebugMsg("InRangeWithSource: Attempt to call GetSourceUnit on an unregistered trigger. Please register this trigger using TriggerRegisterUnitInRangeWithSource or do not call GetSourceUnit on this trigger.")returnnullendifif d.currentSource!=nullthenreturn d.currentSourceendifloopexitwhen i >= d.indexset u = d.registered[i]set udist = d.registered_dist[i]set dx =GetUnitX(u)-GetUnitX(triggerUnit)set dy =GetUnitY(u)-GetUnitY(triggerUnit)set dist =SquareRoot(dx * dx + dy * dy)exitwhen dist <= udist
set i = i +1endloopif i >= d.indexthendebugcallBJDebugMsg("InRangeWithSource: An unregistered unit fired a registered trigger. Please register this unit in the proper way.")returnnullendifset d.currentSource= u
set u =nullif ClearSourceTime >0thenset t = NewTimer()call SetTimerData(t, d)callTimerStart(t, ClearSourceTime,false,function ClearSourceTimed)endifreturn d.currentSourceendfunctionfunction GetSourceUnit takesnothingreturnsunitreturn GetSourceUnitFromTrigger(GetTriggeringTrigger(),GetTriggerUnit())endfunctionprivatefunction Init takesnothingreturnsnothingset ht = HandleTable.create()endfunctionendlibrary
Last edited by TriggerHappy; 02-06-2010 at 11:01 PM.
Small update that breaks backwards compatibility, you now no longer need to pass the triggering trigger and unit to the function, although GetSourceUnitFromTrigger allows you to do that if the code is not run from the triggering trigger. I included the old version in the test map.