scope DelayedTeleport initializer init
private struct DummyDat
real delX
real delY
real distLeft
unit dummy
unit caster
endstruct
globals
// raw code of the ability cast
private constant integer DELAY_TELEPORT_ID = 'A000'
// how far the projectile should start, offset from the caster
private constant real OFFSET = 64.
// specification calls for 100/3 frames per second
private constant real CLOCK_PERIOD = .03
// specification calls for 65 units per 0.03 seconds, but velocities
// should be in units per second - this does both
private constant real VELOCITY = 65. / CLOCK_PERIOD
// stack variables
private DummyDat array stack
private integer stackIndex = -1
// static timer
private timer clock = CreateTimer()
endglobals
private function periodic takes nothing returns nothing
local DummyDat d
local integer index = 0
local real dumX
local real dumY
loop
exitwhen index > stackIndex
set d = stack[index]
set dumX = GetUnitX(d.dummy)
set dumY = GetUnitY(d.dummy)
call SetUnitX(d.dummy, dumX + d.delX)
call SetUnitY(d.dummy, dumY + d.delY)
set d.distLeft = d.distLeft - VELOCITY * CLOCK_PERIOD
// re-use OFFSET value as a collision buffer because why not
if d.distLeft <= OFFSET then
call DummyUnitStack.release(d.dummy)
call SetUnitX(d.caster, dumX)
call SetUnitY(d.caster, dumY)
// now de-index the instance
call d.destroy()
set stack[index] = stack[stackIndex]
set index = index - 1
set stackIndex = stackIndex - 1
// check for termination
if stackIndex == -1 then
call PauseTimer(clock)
endif
endif
set index = index + 1
endloop
endfunction
private function act takes nothing returns nothing
local DummyDat d
local real targetX
local real targetY
local real ang
local real uX
local real uY
if GetSpellAbilityId() == DELAY_TELEPORT_ID then
set targetX = GetSpellTargetX()
set targetY = GetSpellTargetY()
set d = DummyDat.create()
set d.dummy = DummyUnitStack.get()
set d.caster = GetTriggerUnit()
set uX = GetUnitX(d.caster)
set uY = GetUnitY(d.caster)
set ang = Atan2(targetY - uY, targetX - uX)
call SetUnitX(d.dummy, uX + OFFSET * Cos(ang))
call SetUnitY(d.dummy, uY + OFFSET * Sin(ang))
set d.delX = VELOCITY * CLOCK_PERIOD * Cos(ang)
set d.delY = VELOCITY * CLOCK_PERIOD * Sin(ang)
set d.distLeft = SquareRoot((targetX - uX) * (targetX - uX) + (targetY - uY) * (targetY - uY)) - OFFSET
set stackIndex = stackIndex + 1
set stack[stackIndex] = d
if stackIndex == 0 then
call TimerStart(clock, CLOCK_PERIOD, true, function periodic)
endif
endif
endfunction
private function init takes nothing returns nothing
call RegisterAnyUnitEvent(EVENT_PLAYER_UNIT_SPELL_EFFECT, function act)
endfunction
endscope