library Knockback initializer Init uses IsPathable
struct Knockback_Data
unit u
real d1
real d2
real sin
real cos
real r
string s = ""
effect e = null
endstruct
globals
private timer Tim = CreateTimer()
private Knockback_Data array KnockAr[100]
private integer KnockTotal = 0
private item I = CreateItem('ciri', 0, 0)
boolexpr filter
endglobals
private function Knockback_TreeFilter takes nothing returns boolean
local integer d = GetDestructableTypeId(GetFilterDestructable())
return d == 'ATtr' or d == 'BTtw' or d == 'KTtw' or d == 'YTft' or d == 'JTct' or d == 'YTst' or d == 'YTct' or d == 'YTwt' or d == 'JTwt' or d == 'JTwt' or d == 'FTtw' or d == 'CTtr' or d == 'ITtw' or d == 'NTtw' or d == 'OTtw' or d == 'ZTtw' or d == 'WTst' or d == 'LTlt' or d == 'GTsh' or d == 'Xtlt' or d == 'WTtw' or d == 'Attc' or d == 'BTtc' or d == 'CTtc' or d == 'ITtc' or d == 'NTtc' or d == 'ZTtc'
endfunction
function Knockback_KillTree takes nothing returns nothing
call KillDestructable(GetEnumDestructable())
endfunction
private constant function Interval takes nothing returns real
return 0.04
endfunction
private function Knockback_Execute takes nothing returns nothing
local Knockback_Data kd
local integer i = 0
local real x
local real y
local integer X
local integer Y
local rect r
local boolexpr b
loop
exitwhen(i >= KnockTotal)
set kd = KnockAr[i]
if(kd.s != null and kd.s != null) then
set x = GetUnitX(kd.u)
set y = GetUnitY(kd.u)
call DestroyEffect(AddSpecialEffect(kd.s, x, y))
set x = x + kd.d1 * kd.cos
set y = y + kd.d1 * kd.sin
else
set x = GetUnitX(kd.u) + kd.d1 * kd.cos
set y = GetUnitY(kd.u) + kd.d1 * kd.sin
endif
set X = R2I(x)
set Y = R2I(y)
if(kd.r != 0) then
set r = Rect(x - kd.r, y - kd.r, x + kd.r, y + kd.r)
set b = Filter(function Knockback_TreeFilter)
call EnumDestructablesInRect(r, b, function Knockback_KillTree)
call RemoveRect(r)
call DestroyBoolExpr(b)
endif
if(IsPathable(X, Y, 5)) then
call SetUnitX(kd.u, x)
call SetUnitY(kd.u, y)
endif
set kd.d1 = kd.d1 - kd.d2
if(kd.d1 <= 0 or not IsPathable(X, Y, 5)) then
if kd.e != null then
call DestroyEffect(kd.e)
endif
call PauseUnit(kd.u, false)
call SetUnitPathing( kd.u, true )
set KnockAr[i] = KnockAr[KnockTotal - 1]
set KnockTotal = KnockTotal - 1
call kd.destroy()
endif
set i = i + 1
endloop
if KnockTotal == 0 then
call PauseTimer(Tim)
endif
endfunction
function KnockbackEx takes unit u, real d, real a, real w, real r, integer t, string s, string p returns Knockback_Data
local Knockback_Data kd = Knockback_Data.create()
local integer q = R2I(w / Interval())
set kd.u = u
set kd.d1 = 2 * d / (q + 1)
set kd.d2 = kd.d1 / q
set kd.sin = Sin(a)
set kd.cos = Cos(a)
set kd.r = r
if(s != "" and s != null) then
if(t == 2) then
if(p != "" and p != null) then
set kd.e = AddSpecialEffectTarget(s, u, p)
else
set kd.e = AddSpecialEffectTarget(s, u, "chest")
endif
elseif t == 1 then
set kd.s = s
endif
endif
call SetUnitPosition(u, GetUnitX(u), GetUnitY(u))
call PauseUnit(u, true)
call UnitAddAbility(u, 'Arav')
call UnitRemoveAbility(u, 'Arav')
call SetUnitPathing( u, false )
if(KnockTotal <= 0) then
call TimerStart(Tim, Interval(), true, function Knockback_Execute)
endif
set KnockTotal = KnockTotal + 1
set KnockAr[KnockTotal - 1] = kd
return kd
endfunction
function Knockback takes unit u, real d, real a, real w returns Knockback_Data
return KnockbackEx(u, d, a, w, 0, 0, "", "")
endfunction
private function Init takes nothing returns nothing
set filter = Filter(function Knockback_TreeFilter)
endfunction
endlibrary