- Joined
- Aug 3, 2008
- Messages
- 2,345
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:
Requires:
TimerUtils by Vexorian
Table by Vexorian
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
globals
private constant integer MAX_INSTANCES = 408000
private constant integer MAX_UNITS = 100
private constant real OFFSET = 20.00
public real ClearSourceTime = 2.00
private HandleTable ht
endglobals
private struct Data [MAX_INSTANCES]
unit array registered[MAX_UNITS]
real array registered_dist[MAX_UNITS]
integer index = 0
unit currentSource = null
endstruct
function TriggerRegisterUnitInRangeWithSource takes trigger whichTrigger, unit whichUnit, real range, boolexpr filter returns event
local Data d
if ht.exists(whichTrigger) then
set d = ht[whichTrigger]
else
set d = Data.create()
set ht[whichTrigger] = d
endif
if d.index < MAX_UNITS then
set d.registered[d.index] = whichUnit
set d.registered_dist[d.index] = range + OFFSET
set d.index = d.index + 1
else
debug call BJDebugMsg("InRangeWithSource: Number of units registered to trigger exceeds MAX_UNITS. Please increase MAX_UNITS or register fewer units")
return null
endif
return TriggerRegisterUnitInRange(whichTrigger, whichUnit, range, filter)
endfunction
private function ClearSourceTimed takes nothing returns nothing
local timer t = GetExpiredTimer()
local Data d = GetTimerData(t)
set d.currentSource = null
call ReleaseTimer(t)
set t = null
endfunction
function ClearSource takes trigger whichTrigger returns nothing
local Data d = ht[whichTrigger]
set d.currentSource = null
endfunction
function GetSourceUnitFromTrigger takes trigger whichTrigger, unit triggerUnit returns unit
local Data d
local integer i = 0
local unit u
local real udist
local real dx
local real dy
local real dist
local timer t
if ht.exists(whichTrigger) then
set d = ht[whichTrigger]
else
debug call BJDebugMsg("InRangeWithSource: Attempt to call GetSourceUnit on an unregistered trigger. Please register this trigger using TriggerRegisterUnitInRangeWithSource or do not call GetSourceUnit on this trigger.")
return null
endif
if d.currentSource != null then
return d.currentSource
endif
loop
exitwhen i >= d.index
set 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 + 1
endloop
if i >= d.index then
debug call BJDebugMsg("InRangeWithSource: An unregistered unit fired a registered trigger. Please register this unit in the proper way.")
return null
endif
set d.currentSource = u
set u = null
if ClearSourceTime > 0 then
set t = NewTimer()
call SetTimerData(t, d)
call TimerStart(t, ClearSourceTime, false, function ClearSourceTimed)
endif
return d.currentSource
endfunction
function GetSourceUnit takes nothing returns unit
return GetSourceUnitFromTrigger(GetTriggeringTrigger(), GetTriggerUnit())
endfunction
private function Init takes nothing returns nothing
set ht = HandleTable.create()
endfunction
endlibrary
Attachments
Last edited by a moderator: