library Sliding requires Destructables
globals
constant real Tick = 0.06
private timer NormalTimer = CreateTimer()
private boolean NormalRuning = false
private timer ToUnitTimer = CreateTimer()
private boolean ToUnitRuning = false
private timer ToCoordinatesTimer = CreateTimer()
private boolean ToCoordinatesRuning = false
endglobals
private struct Normal
unit u
real ang
real distance
real time
boolean rough
readonly thistype next
readonly thistype prev
static method operator first takes nothing returns thistype
return thistype(0).next
endmethod
static method operator last takes nothing returns thistype
return thistype(0).prev
endmethod
static method create takes unit u, real ang, real speed, real time, boolean rough returns thistype
local thistype this = thistype.allocate()
set thistype(0).next.prev = this
set this.next = thistype(0).next
set this.prev = thistype(0)
set thistype(0).next = this
set this.u = u
set this.ang = ang*bj_DEGTORAD
set this.distance = speed*Tick
set this.time = time
set this.rough = rough
return this
endmethod
method onDestroy takes nothing returns nothing
if this.first == this.last then
set NormalRuning = false
call PauseTimer(NormalTimer)
endif
set this.next.prev = this.prev
set this.prev.next = this.next
endmethod
static method slide takes nothing returns nothing
local thistype this = thistype.first
local real x
local real y
loop
exitwhen this == 0
set x = GetUnitX(this.u) + this.distance*Cos(this.ang)
set y = GetUnitY(this.u) + this.distance*Sin(this.ang)
if this.rough then
if IsUnitType(this.u , UNIT_TYPE_GROUND) then
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Human\\FlakCannons\\FlakTarget.mdl",x,y))
call EnumDestructablesInCircle( x, y, 150, function KillTrees)
endif
call SetUnitPosition( this.u , x , y )
else
call SetUnitX(this.u, x)
call SetUnitY(this.u, y)
endif
set this.time = this.time - Tick
if this.time <= 0 then
call Normal.destroy(this)
endif
set this = this.next
endloop
endmethod
endstruct
private function NormalLoop takes nothing returns nothing
call Normal.slide()
endfunction
function Slide takes unit u, real ang, real time, real speed, boolean s_type returns nothing
local Normal list = Normal.create(u, ang, speed, time, s_type)
if not NormalRuning then
set NormalRuning = true
call TimerStart(NormalTimer, Tick, true, function NormalLoop)
endif
endfunction
private struct ToUnit
unit u
unit t
real distance
real end
trigger tr
readonly thistype next
readonly thistype prev
static method operator first takes nothing returns thistype
return thistype(0).next
endmethod
static method operator last takes nothing returns thistype
return thistype(0).prev
endmethod
static method create takes unit u, unit t, real speed, real end, trigger tr returns thistype
local thistype this = thistype.allocate()
set thistype(0).next.prev = this
set this.next = thistype(0).next
set this.prev = thistype(0)
set thistype(0).next = this
set this.u = u
set this.t = t
set this.distance = speed*Tick
set this.end = end
set this.tr = tr
return this
endmethod
method onDestroy takes nothing returns nothing
if this.first == this.last then
set ToUnitRuning = false
call PauseTimer(ToUnitTimer)
endif
set this.next.prev = this.prev
set this.prev.next = this.next
endmethod
static method slide takes nothing returns nothing
local thistype this = thistype.first
local real x
local real y
local real xt
local real yt
local real h
local real w
local real a
local integer id
loop
exitwhen this == 0
set x = GetUnitX(this.u)
set y = GetUnitY(this.u)
set xt = GetUnitX(this.t)
set yt = GetUnitY(this.t)
set a = Atan2(yt - y, xt - x)
set x = x + this.distance*Cos(a)
set y = y + this.distance*Sin(a)
set h = yt - y
set w = xt - x
call SetUnitX(this.u, x)
call SetUnitY(this.u, y)
if this.tr != null then
set id = GetHandleId(this.tr)
call SaveUnitHandle(udg_Table, id, 'unit', this.u)
call SaveUnitHandle(udg_Table, id, 'targ', this.t)
call SaveReal(udg_Table, id, 'dist', SquareRoot(h*h+w*w))
call TriggerEvaluate(this.tr)
call FlushChildHashtable(udg_Table, id)
endif
if h*h + w*w <= this.end*this.end or IsUnitDeadBJ(this.u) or IsUnitDeadBJ(this.t) then
call ToUnit.destroy(this)
endif
set this = this.next
endloop
endmethod
endstruct
function ToUnitLoop takes nothing returns nothing
call ToUnit.slide()
endfunction
function SlideToUnit takes unit u, unit d, real speed, real end, trigger tr returns nothing
local ToUnit list = ToUnit.create(u, d, speed, end, tr)
if not ToUnitRuning then
set ToUnitRuning = true
call TimerStart(ToUnitTimer, Tick, true, function ToUnitLoop)
endif
endfunction
private struct ToCoordinates
unit u
real x
real y
real distance
trigger tr
readonly thistype next
readonly thistype prev
static method operator first takes nothing returns thistype
return thistype(0).next
endmethod
static method operator last takes nothing returns thistype
return thistype(0).prev
endmethod
static method create takes unit u, real x, real y, real speed, trigger tr returns thistype
local thistype this = thistype.allocate()
set thistype(0).next.prev = this
set this.next = thistype(0).next
set this.prev = thistype(0)
set thistype(0).next = this
set this.u = u
set this.x = x
set this.y = y
set this.distance = speed*Tick
set this.tr = tr
return this
endmethod
method onDestroy takes nothing returns nothing
if this.first == this.last then
set ToCoordinatesRuning = false
call PauseTimer(ToCoordinatesTimer)
endif
set this.next.prev = this.prev
set this.prev.next = this.next
endmethod
static method slide takes nothing returns nothing
local thistype this = thistype.first
local real x
local real y
local real a
local integer id
loop
exitwhen this == 0
set x = GetUnitX(this.u)
set y = GetUnitY(this.u)
set a = Atan2(this.y - y, this.x -x)
if IsUnitDeadBJ(this.u) then
call ToCoordinates.destroy(this)
elseif (this.x - x)*(this.x - x) + (this.y - y)*(this.y - y) >= this.distance*this.distance then
call SetUnitX(this.u, x + Cos(a)*this.distance)
call SetUnitY(this.u, y + Sin(a)*this.distance)
if this.tr != null then
set id = GetHandleId(this.tr)
call SaveUnitHandle(udg_Table, id, 'unit', this.u)
call SaveReal(udg_Table, id, 'desx', this.x)
call SaveReal(udg_Table, id, 'desy', this.y)
call TriggerEvaluate(this.tr)
call FlushChildHashtable(udg_Table, id)
endif
else
call SetUnitX(this.u, this.x)
call SetUnitY(this.u, this.y)
if this.tr != null then
set id = GetHandleId(this.tr)
call SaveUnitHandle(udg_Table, id, 'unit', this.u)
call SaveReal(udg_Table, id, 'desx', this.x)
call SaveReal(udg_Table, id, 'desy', this.y)
call TriggerEvaluate(this.tr)
call FlushChildHashtable(udg_Table, id)
endif
call ToCoordinates.destroy(this)
endif
set this = this.next
endloop
endmethod
endstruct
function ToCoordinatesLoop takes nothing returns nothing
call ToCoordinates.slide()
endfunction
function SlideTo takes unit u, real x, real y, real speed, trigger tr returns nothing
local ToCoordinates list = ToCoordinates.create(u, x, y, speed, tr)
if not ToCoordinatesRuning then
set ToCoordinatesRuning = true
call TimerStart(ToCoordinatesTimer, Tick, true, function ToCoordinatesLoop)
endif
endfunction
endlibrary