//******************************************************************************************
//*
//* Airborne by Almia
//*
//******************************************************************************************
//*
//* What is Airborne?
//*
//* Airborne is a kind of Jump System which applies the Crowd Control(obviously Airborne)
//* to units. This also uses Bezier Curves for a better overwriteable airborne.
//*
//* Notes:
//* - Target heigts may not be accurate.
//* - works much better when used with Stun Systems
//*
//******************************************************************************************
//*
//* Requires:
//*
//* Unit Indexer by Bribe
//* - http://www.hiveworkshop.com/forums/spells-569/gui-unit-indexer-1-2-0-2-a-197329/
//*
//******************************************************************************************
//*
//* API
//*
//* constant function AB_STRICTLY_DISABLE_MOVEMENT takes nothing returns boolean
//* - This value dictates whether or not a unit shall be locked on it's position,
//* so that it won't be affected of the function SetUnitX/Y
//*
//* constant function AB_DISABLE_FACING takes nothing returns boolean
//* - Disables the unit's ability to change facing
//*
//* constant function AB_CANCEL_ORDERS takes nothing returns boolean
//* - Cancels orders after applying Airborne(if false, resumes it's previous order "naturally")
//*
//* function IsUnitAirborne takes unit u returns boolean
//* - Checks whether the unit is airborne or not.
//*
//* function UnitAddAirborne takes unit u, real z, real duration returns nothing
//* - Adds airborne to unit, lasts till "duration" ends.
//* - "z" is the target height of the airborne, a.k.a the highest point.
//* - this is overwriteable.
//*
//* function UnitSuspendAirborne takes unit u, boolean flag returns nothing
//* - Suspends the unit, stop it's airborne progress.
//* - "flag" tells whether or not to unsuspend the unit(true = suspend)
//*
//* function IsAirborneUnitSuspended takes unit u returns boolean
//* - Checks whether or not the airborne unit is suspended.
//*
//* function UnitRemoveAirborne takes unit u, boolean resetHeight returns nothing
//* - Removes the unit's airborne status
//* - "resetHeight" set the unit to it's original height
//* setting it to false will leave the unit to it's current height.
//*
//* Events
//*
//* constant function AIRBORNE_ON_LIFT takes nothing returns real
//* - Executes if a unit is lifted
//* constant function AIRBORNE_ON_DROP takes nothing returns real
//* - Executes if a unit is dropped
//* constant function AIRBORNE_ON_AIR takes nothing returns real
//* - Executes if a unit is on air
//*
//* function TriggerRegisterAirborneEvent takes trigger t, real ev returns nothing
//* function RegisterAirborneEvent takes code c, real ev returns nothing
//*
//******************************************************************************************
//*
//* Credits
//* Bribe - Unit Indexer
//* BlinkBoy - Bezier Function
//* <some unknown guy in the internet> - finding the Bezier's control points
//*
//******************************************************************************************
//*
//* Constants
//*
//******************************************************************************************
constant function AB_TIMEOUT takes nothing returns real
return 0.031250000
endfunction
constant function AB_STRICTLY_DISABLE_MOVEMENT takes nothing returns boolean
return true
endfunction
constant function AB_DISABLE_FACING takes nothing returns boolean
return true
endfunction
constant function AB_CANCEL_ORDERS takes nothing returns boolean
return true
endfunction
//******************************************************************************************
//* Event
//******************************************************************************************
constant function AIRBORNE_ON_LIFT takes nothing returns real
return 1.0
endfunction
constant function AIRBORNE_ON_DROP takes nothing returns real
return 2.0
endfunction
constant function AIRBORNE_ON_AIR takes nothing returns real
return 3.0
endfunction
//******************************************************************************************
function Bezier takes real a, real b, real c, real t returns real
return a + 2.*(b-a)*t + (c -2.*b + a)*t*t
endfunction
function GetBezierControlPoint takes real a, real b, real t returns real
return 2*t - a/2 - b/2
endfunction
function AB_UnitCheck takes unit u returns boolean
return u != null
endfunction
//******************************************************************************************
function InitABEvents takes nothing returns nothing
if udg_AB_DropEvent == null then
set udg_AB_DropEvent = CreateTrigger()
call TriggerRegisterVariableEvent(udg_AB_DropEvent, "udg_AB_Event", EQUAL, AIRBORNE_ON_DROP())
endif
if udg_AB_LiftEvent == null then
set udg_AB_LiftEvent = CreateTrigger()
call TriggerRegisterVariableEvent(udg_AB_LiftEvent, "udg_AB_Event", EQUAL, AIRBORNE_ON_LIFT())
endif
if udg_AB_AirEvent == null then
set udg_AB_AirEvent = CreateTrigger()
call TriggerRegisterVariableEvent(udg_AB_AirEvent, "udg_AB_Event", EQUAL, AIRBORNE_ON_AIR())
endif
endfunction
function TriggerRegisterAirborneEvent takes trigger t, real ev returns nothing
call InitABEvents()
call TriggerRegisterVariableEvent(t, "udg_AB_Event", EQUAL, ev)
endfunction
function RegisterAirborneEvent takes code c, real ev returns nothing
call InitABEvents()
if ev == AIRBORNE_ON_DROP() then
call TriggerAddCondition(udg_AB_DropEvent, Condition(c))
elseif ev == AIRBORNE_ON_LIFT() then
call TriggerAddCondition(udg_AB_LiftEvent, Condition(c))
elseif ev == AIRBORNE_ON_AIR() then
call TriggerAddCondition(udg_AB_AirEvent, Condition(c))
endif
endfunction
function IsUnitAirborne takes unit u returns boolean
return udg_AB_Airborned[GetUnitUserData(u)]
endfunction
function UnitRemoveAirborne takes unit u, boolean resetHeight returns nothing
local integer i
if AB_UnitCheck(u) then
set i = GetUnitUserData(u)
if udg_AB_Airborned[i] then
set udg_AB_DroppedUnit = u
set udg_AB_Event = AIRBORNE_ON_DROP()
set udg_AB_Event = 0.0
if resetHeight then
call SetUnitFlyHeight(u, udg_AB_OriginalZ[i], 0)
endif
if AB_STRICTLY_DISABLE_MOVEMENT() then
set udg_AB_X[i] = 0
set udg_AB_Y[i] = 0
endif
if AB_DISABLE_FACING() then
set udg_AB_Facing[i] = 0
endif
set udg_AB_Airborned[i] = false
set udg_AB_OriginalZ[i] = 0
set udg_AB_TargetZ[i] = 0
set udg_AB_SourceZ[i] = 0
set udg_AB_Duration[i] = 0
set udg_AB_MaxDuration[i] = 0
set udg_AB_Paused[i] = false
set udg_AB_N[udg_AB_P[i]] = udg_AB_N[i]
set udg_AB_P[udg_AB_N[i]] = udg_AB_P[i]
call SetUnitPropWindow(u, GetUnitDefaultPropWindow(u)*bj_DEGTORAD)
if udg_AB_N[0] == 0 then
call PauseTimer(udg_AB_Timer)
endif
endif
endif
endfunction
function Airborne_Periodic takes nothing returns nothing
local integer i = udg_AB_N[0]
local unit u
loop
exitwhen i == 0
set u = udg_UDexUnits[i]
if AB_UnitCheck(u) and udg_AB_Duration[i] < udg_AB_MaxDuration[i] then
set udg_AB_AirborneUnit = u
set udg_AB_Event = AIRBORNE_ON_AIR()
set udg_AB_Event = 0.0
if not udg_AB_Paused[i] then
set udg_AB_Duration[i] = udg_AB_Duration[i] + AB_TIMEOUT()
endif
if AB_STRICTLY_DISABLE_MOVEMENT() then
call SetUnitX(u, udg_AB_X[i])
call SetUnitY(u, udg_AB_Y[i])
endif
if AB_DISABLE_FACING() then
call SetUnitFacing(u, udg_AB_Facing[i])
endif
call SetUnitFlyHeight(u, Bezier(udg_AB_SourceZ[i], udg_AB_TargetZ[i], udg_AB_OriginalZ[i], udg_AB_Duration[i]/udg_AB_MaxDuration[i]), 0)
else
call UnitRemoveAirborne(u, true)
endif
set i = udg_AB_N[i]
endloop
set u = null
endfunction
function UnitAddAirborne takes unit u, real z, real duration returns nothing
local integer i
call InitABEvents()
if AB_UnitCheck(u) then
set i = GetUnitUserData(u)
set udg_AB_LiftedUnit = u
set udg_AB_Event = AIRBORNE_ON_LIFT()
set udg_AB_Event = 0.0
if not udg_AB_Airborned[i] then
set udg_AB_Airborned[i] = true
call SetUnitPropWindow(u, 0)
set udg_AB_N[i] = 0
set udg_AB_P[i] = udg_AB_P[0]
set udg_AB_N[udg_AB_P[0]] = i
set udg_AB_P[0] = i
set udg_AB_OriginalZ[i] = GetUnitFlyHeight(u)
if AB_STRICTLY_DISABLE_MOVEMENT() then
set udg_AB_X[i] = GetUnitX(u)
set udg_AB_Y[i] = GetUnitY(u)
endif
if AB_DISABLE_FACING() then
set udg_AB_Facing[i] = GetUnitFacing(u)
endif
if UnitAddAbility(u, 'Amrf') and UnitRemoveAbility(u, 'Amrf') then
endif
if udg_AB_N[0] == udg_AB_P[0] then
call TimerStart(udg_AB_Timer, AB_TIMEOUT(), true, function Airborne_Periodic)
endif
endif
set udg_AB_Duration[i] = 0
set udg_AB_MaxDuration[i] = duration
set udg_AB_SourceZ[i] = GetUnitFlyHeight(u)
set udg_AB_TargetZ[i] = GetBezierControlPoint(udg_AB_SourceZ[i], udg_AB_OriginalZ[i], udg_AB_SourceZ[i] + z)
if AB_CANCEL_ORDERS() then
call IssueImmediateOrderById(u, 851972)
endif
endif
endfunction
function IsAirborneUnitSuspended takes unit u returns boolean
local integer i
if AB_UnitCheck(u) then
set i = GetUnitUserData(u)
return udg_AB_Airborned[i] and udg_AB_Paused[i]
endif
return false
endfunction
function UnitSuspendAirborne takes unit u, boolean flag returns nothing
local integer i
if AB_UnitCheck(u) then
set i = GetUnitUserData(u)
if udg_AB_Airborned[i] then
set udg_AB_Paused[i] = flag
endif
endif
endfunction