globals
location dummyLoc = Location(0, 0)
endglobals
function GetUnitZ takes unit u returns real
call MoveLocation(dummyLoc, GetUnitX(u), GetUnitY(u))
return (GetLocationZ(dummyLoc) + GetUnitFlyHeight(u))
endfunction
function SetUnitXYZ takes unit u, real x, real y, real z returns nothing
call SetUnitX(u, x)
call SetUnitY(u, y)
call MoveLocation(dummyLoc, x, y)
call SetUnitFlyHeight(u, z - GetLocationZ(dummyLoc), 0)
endfunction
struct Missile
static hashtable ht=InitHashtable()
static constant real INTERVAL=0.03125
unit dummy
timer moveTimer
real x
real y
real z
real moveLen
real moveLenSqr
unit target
method destroy takes nothing returns nothing
call RemoveSavedInteger(ht, GetHandleId(this.moveTimer), 0)
call PauseTimer(this.moveTimer)
call DestroyTimer(this.moveTimer)
call RemoveUnit(this.dummy)
call this.deallocate()
endmethod
method move takes nothing returns nothing
local real targetX = GetUnitX(this.target)
local real targetY = GetUnitY(this.target)
local real targetZ = GetUnitZ(this.target)
local real dX = targetX - this.x
local real dY = targetY - this.y
local real dZ = targetZ - this.z
local real dSqr = dX*dX+dY*dY+dZ*dZ
local real d
if (dSqr < this.moveLenSqr) then
call this.destroy()
else
set d = SquareRoot(dSqr)
set this.x = this.x + dX / d * this.moveLen
set this.y = this.y + dY / d * this.moveLen
set this.z = this.z + dZ / d * this.moveLen
call SetUnitXYZ(this.dummy, this.x, this.y, this.z)
endif
endmethod
static method moveByTimer takes nothing returns nothing
call thistype(LoadInteger(ht, GetHandleId(GetExpiredTimer()), 0)).move()
endmethod
static method create takes integer id, real x, real y, real z, unit target, real speed returns thistype
local thistype this = thistype.allocate()
set this.dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), id, 0, 0, 0)
set this.x = x
set this.y = y
set this.z = z
set this.moveLen = speed*INTERVAL
set this.moveLenSqr = speed*speed*INTERVAL*INTERVAL
set this.target = target
set this.moveTimer = CreateTimer()
call SaveInteger(ht, GetHandleId(this.moveTimer), 0, this)
call UnitAddAbility(this.dummy, 'Amrf')
call UnitRemoveAbility(this.dummy, 'Amrf')
call UnitAddAbility(this.dummy, 'Aloc')
call SetUnitXYZ(this.dummy, x, y, z)
call TimerStart(this.moveTimer, INTERVAL, true, function thistype.moveByTimer)
return this
endmethod
endstruct