library MoveUnitFacingLib initializer init requires Table
globals
//this is the aproximation this system will use, if you set to 0 it is the most
//precice it can be, I think 16 should be fine
private constant real aproximation = 16
//order of the move command
private constant integer order_move = 851986
//set this to w/e you want
//it will flush the command for unit in case it cannot access the point in
//"this number" times
//be aware that the checking happens once every 0.1 seconds, so this is for 2.5 second
private constant integer tofailtries = 25
private Table uToMove
private Table toface
private Table toWait
private Table point
private Table unitCoords
endglobals
/*
This is debug feature, remove it if you dont want it
But it shouldnt matter anyway cause its debug only feature
*/
static if DEBUG_MODE then
private struct ddata extends array
static Table tries
private static method onInit takes nothing returns nothing
set tries = Table.create()
endmethod
endstruct
endif
private function IsAprox takes real a, real b returns boolean
return a <= (b + aproximation) or a >= (b + aproximation)
endfunction
private function UpdateFacing takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
call SetUnitFacing(uToMove.unit[i], toface.real[i])
call DestroyTimer(t)
set t = null
endfunction
private function IsMoving takes nothing returns nothing
local timer t = GetExpiredTimer()
local integer i = GetHandleId(t)
local unit u = uToMove.unit[i]
local real ux = GetUnitX(u)
local real uy = GetUnitY(u)
local integer newi = 0
//last unit x/y
local real lux = unitCoords.real[i]
local real luy = unitCoords.real[-i]
//if the distance from current units position is different then it was before:
//btw, this is a lot faster then square rooting those numbers
if ux*ux + uy*uy == lux*lux + luy*luy then
//if the unit is near the position it should be:
if IsAprox(ux, point.real[i]) and IsAprox(uy, point.real[-i]) then
call PauseTimer(t)
call DestroyTimer(t)
set t = CreateTimer()
set newi = GetHandleId(t)
set toface.real[newi] = toface.real[i]
set uToMove.unit[newi] = uToMove.unit[i]
call TimerStart(t, toWait.real[i], false, function UpdateFacing)
else //if not, issue the unit to move further
//debug safety:
//if the unit is unable to get to the point in certain number of tries, it will
//destroy this stuff
static if DEBUG_MODE then
set ddata.tries[i] = ddata.tries[i] + 1
if ddata.tries[i] >= tofailtries then
call PauseTimer(t)
call DestroyTimer(t)
endif
endif
//didnt test this, but It should work well
//unless there is unit already standing there, in which there is debug safety
//which will destroy the timers etc after certain time(above, its debug safety actually)
//in case you are using debug mode, this will prevent the unit to move the location
//another time if the timer is already destroyed(from above in the debug_mode peace of code)
debug if t != null then
call IssuePointOrderById(u, order_move, point.real[i], point.real[-i])
debug endif
endif
else //if not
//update the units positions
set unitCoords.real[i] = ux
set unitCoords.real[-i] = uy
endif
set t = null
set u = null
endfunction
function MoveUnitWaitFacing takes unit tomove, real locx, real locy, real facing, real wait returns nothing
local timer t
local integer i
if tomove != null then
set t = CreateTimer()
set i = GetHandleId(t)
call IssuePointOrderById(tomove, order_move, locx, locy)
set toface.real[i] = facing
set uToMove.unit[i] = tomove
set toWait.real[i] = wait
set point.real[i] = locx
//I have test it, it should work
set point.real[-i] = locy
set ddata.tries[i] = 0
//units current coordinates
set unitCoords.real[i] = GetUnitX(tomove)
set unitCoords.real[-i] = GetUnitY(tomove)
//we are going to check every 0.1 seconds, dont want it ot be too heavy and
//it should give unit enough time when it comes to pathing blocker to realize
//there is some other way around
call TimerStart(t, 0.1, true, function IsMoving)
endif
set t = null
endfunction
//remove this if you are not testing it
private function test takes nothing returns nothing
local unit u1 = CreateUnit(Player(0), 'hfoo', -100, -100, 0)
local unit u2 = CreateUnit(Player(0), 'hfoo', -200, -100, 0)
local unit u3 = CreateUnit(Player(0), 'hfoo', -300, -100, 0)
local unit u4 = CreateUnit(Player(0), 'hfoo', -400, -100, 0)
call MoveUnitWaitFacing(u1, -100, GetUnitY(u1) + 100, 270., 1)
call MoveUnitWaitFacing(u2, -200, GetUnitY(u2) + 100, 270., 1)
call MoveUnitWaitFacing(u3, -300, GetUnitY(u3) + 100, 270., 1)
call MoveUnitWaitFacing(u4, -400, GetUnitY(u4) + 100, 270., 1)
endfunction
private function init takes nothing returns nothing
set uToMove = Table.create()
set toface = Table.create()
set toWait = Table.create()
set point = Table.create()
set unitCoords = Table.create()
//also remove this call
call test()
endfunction
endlibrary