library StarDash
globals
//private integer sd_intA
private integer sd_intB
private integer sd_intC
private unit array SD_SUA_U
private integer array SD_SUA_C
private integer array SD_SUA_A
private integer SD_SUA_N = 0
private timer SD_SUA_T = CreateTimer()
private integer sd_dashCount = 0
private timer sd_dashTicker = CreateTimer()
private boolean sd_isTickerOn = false
private real SD_TICK_TIMEOUT = 0.03
private ability array sd_dashAbility //
private boolean array sd_isPaused //
private boolean array sd_noReturn // *Input
private integer array sd_dashAbilityLevel //
private integer array sd_starType // Input
private integer array sd_dashAbilityId //
private integer array sd_dashOrderId //
private real array sd_dashArc // *Input
private real array sd_dashHover // *Input
private real array sd_dashRadius // *Input
private integer array sd_moveTicks // Input
private integer array sd_turnTicks // Input
private integer array sd_waitTicks // Input
private integer array sd_dashTicks //
private unit array sd_dashCaster //
private real array sd_casterMoveSpeed //
private real array sd_casterTurnSpeed //
private real array sd_casterFlyHeight //
private integer array sd_moveAnimI // *Input
private integer array sd_turnAnimI // *Input
private integer array sd_waitAnimI // *Input
private real array sd_moveAnimR // *Input
private real array sd_turnAnimR // *Input
private real array sd_waitAnimR // *Input
private unit array sd_dashTarget // Input Option A
private real array sd_dashCenterX // Input Option B, X of udg_SDashStarCenter
private real array sd_dashCenterY // Input Option B, Y of udg_SDashStarCenter
private real array sd_dashAngle // Input Option C, Input nothing and use Caster position and angle
private real array sd_dashReturnX //
private real array sd_dashReturnY //
endglobals
private function SD_CallEvent takes integer i, real e returns nothing
local integer a = sd_dashTicks[i] / ( sd_moveTicks[i] + sd_turnTicks[i] + sd_waitTicks[i] )
set udg_SDEventCaster = sd_dashCaster[i]
set udg_SDEventTarget = sd_dashTarget[i]
set udg_SDEventCenterX = sd_dashCenterX[i]
set udg_SDEventAbility = sd_dashAbility[i]
set udg_SDEventAbilityId = sd_dashAbilityId[i]
set udg_SDEventAbilityLevel = sd_dashAbilityLevel[i]
set udg_SDEventTotalPoints = sd_starType[i]
set udg_SDEventTotalTicks = sd_starType[i] * ( sd_moveTicks[i] + sd_turnTicks[i] + sd_waitTicks[i] ) + sd_waitTicks[i]
set udg_SDEventCurrentPoint = sd_starType[i] - a
set a = sd_dashTicks[i] - a * ( sd_moveTicks[i] + sd_turnTicks[i] + sd_waitTicks[i] )
if a >= sd_turnTicks[i] + sd_waitTicks[i] then
set a = a - sd_turnTicks[i] - sd_waitTicks[i]
set udg_SDEventMoveTicks = sd_moveTicks[i]
set udg_SDEventTurnTicks = 0 - sd_turnTicks[i]
set udg_SDEventStandTicks = 0 - sd_waitTicks[i]
set udg_SDEventTick = udg_SDEventTotalTicks - sd_dashTicks[i]
set udg_SDEventSubTick = sd_moveTicks[i] - a
elseif a >= sd_waitTicks[i] then
set a = a - sd_waitTicks[i]
set udg_SDEventMoveTicks = 0 - sd_moveTicks[i]
set udg_SDEventTurnTicks = sd_turnTicks[i]
set udg_SDEventStandTicks = 0 - sd_waitTicks[i]
set udg_SDEventTick = udg_SDEventTotalTicks - sd_dashTicks[i]
set udg_SDEventSubTick = sd_turnTicks[i] - a
else
set udg_SDEventMoveTicks = 0 - sd_moveTicks[i]
set udg_SDEventTurnTicks = 0 - sd_turnTicks[i]
set udg_SDEventStandTicks = sd_waitTicks[i]
set udg_SDEventTick = udg_SDEventTotalTicks - sd_dashTicks[i]
set udg_SDEventSubTick = sd_waitTicks[i] - a
endif
set udg_StarDashEvent = -1.00
set udg_StarDashEvent = e
endfunction
private function SD_SUA_TF takes nothing returns nothing
local integer i = 0
loop
exitwhen i >= SD_SUA_N
call BlzUnitDisableAbility( SD_SUA_U[i], SD_SUA_A[i], false, false )
if SD_SUA_C[i] > 0 then
call SetUnitState( SD_SUA_U[i], UNIT_STATE_MANA, GetUnitState( SD_SUA_U[i], UNIT_STATE_MANA ) + SD_SUA_C[i] )
endif
set SD_SUA_A[i] = 0
set SD_SUA_C[i] = 0
set SD_SUA_U[i] = null
set i = i + 1
endloop
set SD_SUA_N = 0
endfunction
private function SD_StopUnitAbility takes unit u, integer a, boolean refund returns nothing
call BlzUnitDisableAbility( u, a, true, false )
set SD_SUA_U[SD_SUA_N] = u
set SD_SUA_A[SD_SUA_N] = a
if refund then
set SD_SUA_C[SD_SUA_N] = BlzGetUnitAbilityManaCost( u, a, GetUnitAbilityLevel( u, a ) - 1 )
endif
set SD_SUA_N = SD_SUA_N + 1
call TimerStart( SD_SUA_T, 0.00, false, function SD_SUA_TF )
endfunction
private function SD_EnableMobility takes integer i returns nothing
if not sd_noReturn[i] then
call SetUnitX( sd_dashCaster[i], sd_dashReturnX[i] )
call SetUnitY( sd_dashCaster[i], sd_dashReturnY[i] )
endif
call UnitRemoveAbility( sd_dashCaster[i], udg_SDGlobalSpellImmunity )
call UnitRemoveAbility( sd_dashCaster[i], udg_SDGlobalInvulnerability )
call SetUnitPathing( sd_dashCaster[i], true )
call BlzSetUnitRealField( sd_dashCaster[i], UNIT_RF_SPEED, sd_casterMoveSpeed[i] )
call BlzSetUnitRealField( sd_dashCaster[i], UNIT_RF_TURN_RATE, sd_casterTurnSpeed[i] )
call SetUnitFlyHeight( sd_dashCaster[i], sd_casterFlyHeight[i], 0 )
call SetUnitAnimationByIndex( sd_dashCaster[i], 0 )
call SetUnitTimeScale( sd_dashCaster[i], 1 )
endfunction
private function SD_RemoveDasher takes integer i returns boolean
if i > sd_dashCount then
return false
endif
call SD_StopUnitAbility( sd_dashCaster[i], sd_dashAbilityId[i], false )
if sd_isPaused[i] then
call SD_CallEvent( i, 6.00 )
elseif sd_dashTicks[i] > 0 then
call SD_EnableMobility( i )
call SD_CallEvent( i, 7.00 )
else
call SD_EnableMobility( i )
call SD_CallEvent( i, 0.00 )
endif
set sd_dashCount = sd_dashCount - 1
set sd_dashAbility[i] = sd_dashAbility[sd_dashCount]
set sd_isPaused[i] = sd_isPaused[sd_dashCount]
set sd_noReturn[i] = sd_noReturn[sd_dashCount]
set sd_dashAbilityLevel[i] = sd_dashAbilityLevel[sd_dashCount]
set sd_starType[i] = sd_starType[sd_dashCount]
set sd_dashAbilityId[i] = sd_dashAbilityId[sd_dashCount]
set sd_dashOrderId[i] = sd_dashOrderId[sd_dashCount]
set sd_dashArc[i] = sd_dashArc[sd_dashCount]
set sd_dashHover[i] = sd_dashHover[sd_dashCount]
set sd_dashRadius[i] = sd_dashRadius[sd_dashCount]
set sd_moveTicks[i] = sd_moveTicks[sd_dashCount]
set sd_turnTicks[i] = sd_turnTicks[sd_dashCount]
set sd_waitTicks[i] = sd_waitTicks[sd_dashCount]
set sd_dashTicks[i] = sd_dashTicks[sd_dashCount]
set sd_dashCaster[i] = sd_dashCaster[sd_dashCount]
set sd_casterMoveSpeed[i] = sd_casterMoveSpeed[sd_dashCount]
set sd_casterTurnSpeed[i] = sd_casterTurnSpeed[sd_dashCount]
set sd_casterFlyHeight[i] = sd_casterFlyHeight[sd_dashCount]
set sd_moveAnimI[i] = sd_moveAnimI[sd_dashCount]
set sd_turnAnimI[i] = sd_turnAnimI[sd_dashCount]
set sd_waitAnimI[i] = sd_waitAnimI[sd_dashCount]
set sd_moveAnimR[i] = sd_moveAnimR[sd_dashCount]
set sd_turnAnimR[i] = sd_turnAnimR[sd_dashCount]
set sd_waitAnimR[i] = sd_waitAnimR[sd_dashCount]
set sd_dashTarget[i] = sd_dashTarget[sd_dashCount]
set sd_dashCenterX[i] = sd_dashCenterX[sd_dashCount]
set sd_dashCenterY[i] = sd_dashCenterY[sd_dashCount]
set sd_dashReturnX[i] = sd_dashReturnX[sd_dashCount]
set sd_dashReturnY[i] = sd_dashReturnY[sd_dashCount]
set sd_dashAngle[i] = sd_dashAngle[sd_dashCount]
//
set sd_dashAbility[sd_dashCount] = null
set sd_isPaused[sd_dashCount] = false
set sd_noReturn[sd_dashCount] = false
set sd_dashAbilityLevel[sd_dashCount] = 0
set sd_starType[sd_dashCount] = 0
set sd_dashAbilityId[sd_dashCount] = 0
set sd_dashOrderId[sd_dashCount] = 0
set sd_dashArc[sd_dashCount] = 0
set sd_dashHover[sd_dashCount] = 0
set sd_dashRadius[sd_dashCount] = 0
set sd_moveTicks[sd_dashCount] = 0
set sd_turnTicks[sd_dashCount] = 0
set sd_waitTicks[sd_dashCount] = 0
set sd_dashTicks[sd_dashCount] = 0
set sd_dashCaster[sd_dashCount] = null
set sd_casterMoveSpeed[sd_dashCount] = 0
set sd_casterTurnSpeed[sd_dashCount] = 0
set sd_casterFlyHeight[sd_dashCount] = 0
set sd_moveAnimI[sd_dashCount] = 0
set sd_turnAnimI[sd_dashCount] = 0
set sd_waitAnimI[sd_dashCount] = 0
set sd_moveAnimR[sd_dashCount] = 0
set sd_turnAnimR[sd_dashCount] = 0
set sd_waitAnimR[sd_dashCount] = 0
set sd_dashTarget[sd_dashCount] = null
set sd_dashCenterX[sd_dashCount] = 0
set sd_dashCenterY[sd_dashCount] = 0
set sd_dashReturnX[sd_dashCount] = 0
set sd_dashReturnY[sd_dashCount] = 0
set sd_dashAngle[sd_dashCount] = 0
return true
endfunction
private function SD_DashTick takes integer i returns nothing
local integer a = sd_dashTicks[i] / ( sd_moveTicks[i] + sd_turnTicks[i] + sd_waitTicks[i] )
local integer b = sd_starType[i] - a
local real x
local real y
local real z
// set a = number of ticks remaining in current sub-sequence.
set a = sd_dashTicks[i] - a * ( sd_moveTicks[i] + sd_turnTicks[i] + sd_waitTicks[i] )
if a >= sd_turnTicks[i] + sd_waitTicks[i] then
// move sub-sequence
set a = a - sd_turnTicks[i] - sd_waitTicks[i]
set x = bj_PI - bj_PI / sd_starType[i]
set y = Cos( x ) - 1
set z = Sin( x )
set y = sd_dashRadius[i] * SquareRoot( y * y + z * z ) / sd_moveTicks[i]
set z = sd_dashAngle[i] + ( ( ( 2 * ( b - 1 ) + 1 ) * x - bj_PI ) / 2 )
call SetUnitX( sd_dashCaster[i], GetUnitX( sd_dashCaster[i] ) + Cos( z ) * y )
call SetUnitY( sd_dashCaster[i], GetUnitY( sd_dashCaster[i] ) + Sin( z ) * y )
if sd_starType[i] == 1 then
set z = z + bj_PI / 2
endif
if sd_dashArc[i] != 0 then
set x = sd_moveTicks[i] / 2
set y = x - a
set y = ( x - SquareRoot( y * y ) ) / x
set x = sd_dashArc[i] * y
call SetUnitFlyHeight( sd_dashCaster[i], sd_casterFlyHeight[i] + sd_dashHover[i] + x, 0 )
endif
if a == sd_moveTicks[i] - 1 then
call BlzSetUnitFacingEx( sd_dashCaster[i], 180 * z / bj_PI )
if sd_moveAnimR[i] >= 0.00 then
call SetUnitAnimationByIndex( sd_dashCaster[i], sd_moveAnimI[i] )
call SetUnitTimeScale( sd_dashCaster[i], sd_moveAnimR[i] )
endif
endif
call SD_CallEvent( i, 2.00 )
elseif a >= sd_waitTicks[i] then
// turn sub-sequence.
set a = a - sd_waitTicks[i]
set x = sd_dashAngle[i] + b * ( bj_PI - bj_PI / sd_starType[i] )
set y = sd_dashRadius[i] * Cos( x )
set z = sd_dashRadius[i] * Sin( x )
set x = x - a * bj_PI * ( 1 - 1 / ( 2 * x ) ) / sd_turnTicks[i]
if sd_starType[i] == 1 then
set x = x + bj_PI / 2
endif
call BlzSetUnitFacingEx( sd_dashCaster[i], 180 * x / bj_PI )
if a == sd_turnTicks[i] - 1 then
call SetUnitX( sd_dashCaster[i], sd_dashCenterX[i] - y )
call SetUnitY( sd_dashCaster[i], sd_dashCenterY[i] - z )
if sd_turnAnimR[i] >= 0.00 then
call SetUnitAnimationByIndex( sd_dashCaster[i], sd_turnAnimI[i] )
call SetUnitTimeScale( sd_dashCaster[i], sd_turnAnimR[i] )
endif
endif
call SD_CallEvent( i, 3.00 )
else
// wait sub-sequence.
if a == sd_waitTicks[i] - 1 then
if sd_starType[i] == 1 then
call BlzSetUnitFacingEx( sd_dashCaster[i], 180 * sd_dashAngle[i] / bj_PI )
endif
if sd_waitAnimR[i] >= 0.00 then
call SetUnitAnimationByIndex( sd_dashCaster[i], sd_waitAnimI[i] )
call SetUnitTimeScale( sd_dashCaster[i], sd_waitAnimR[i] )
endif
endif
call SD_CallEvent( i, 4.00 )
endif
endfunction
private function SD_ForDashTickerLoop takes integer i returns integer
local integer o = GetUnitCurrentOrder( sd_dashCaster[i] )
local integer a
if sd_dashTicks[i] < 1 or o != sd_dashOrderId[i] or sd_isPaused[i] then
if o == 851973 or sd_isPaused[i] then
if not sd_isPaused[i] then
set sd_isPaused[i] = true
call SD_EnableMobility( i )
call SD_CallEvent( i, 5.00 )
endif
if o != 851973 then
if o != sd_dashOrderId[i] then
call SD_RemoveDasher( i )
return i
else
call SD_StopUnitAbility( sd_dashCaster[i], sd_dashAbilityId[i], false )
endif
endif
else
call SD_RemoveDasher( i )
return i
endif
set sd_isTickerOn = true
return i + 1
endif
set sd_dashTicks[i] = sd_dashTicks[i] - 1
set a = sd_dashTicks[i] / ( sd_moveTicks[i] + sd_turnTicks[i] + sd_waitTicks[i] )
call SD_DashTick( i )
set sd_isTickerOn = true
return i + 1
endfunction
private function SD_DashTicker takes nothing returns nothing
local integer i = 0
local real a
local real b
local real c
set sd_isTickerOn = false
loop
exitwhen i >= sd_dashCount
set i = SD_ForDashTickerLoop( i )
endloop
if sd_isTickerOn then
call TimerStart( sd_dashTicker, udg_SDGlobalTickRate, false, function SD_DashTicker )
endif
endfunction
function SD_GetVectorAngle takes real x, real y returns real
if x == 0 then
if y == 0 then
return -1.0 // if angle < 0 the vector = 0
else
if y > 0 then
return bj_PI / 2
else
return 3 * bj_PI / 2
endif
endif
else // x1 <> x2
if y < 0 then
return Atan2( y, x ) + 2 * bj_PI
else
return Atan2( y, x )
endif
endif
endfunction
private function SD_GetDasherIndex takes unit u returns integer
local integer i = 0
loop
exitwhen i >= sd_dashCount
if u == sd_dashCaster[i] then
set u = null
return i
endif
set i = i + 1
endloop
set u = null
return -1
endfunction
function SD_CancelDash takes unit u returns boolean
local integer i = SD_GetDasherIndex( u )
set u = null
if i < 0 or sd_isPaused[i] == true then
return false
endif
return SD_RemoveDasher( i )
endfunction
function SD_InitiateDash takes nothing returns nothing
local integer a = GetSpellAbilityId()
local integer m = udg_SDashMode
local unit u = GetSpellAbilityUnit()
local unit t = GetSpellTargetUnit()
local location p = GetSpellTargetLoc()
local real tempx = GetUnitX( u )
local real tempy = GetUnitY( u )
if SD_GetDasherIndex( u ) < 0 then
if m < 0 then
set m = 0 - m
endif
set m = m * 2 + 1
set sd_dashAbility[sd_dashCount] = GetSpellAbility()
set sd_isPaused[sd_dashCount] = false
set sd_noReturn[sd_dashCount] = udg_SDashKeepNewLocation
set sd_dashAbilityLevel[sd_dashCount] = GetUnitAbilityLevel( u, GetSpellAbilityId() )
set sd_starType[sd_dashCount] = m
set sd_dashAbilityId[sd_dashCount] = a
set sd_dashOrderId[sd_dashCount] = GetUnitCurrentOrder( u )
set sd_dashArc[sd_dashCount] = udg_SDashJumpHeight
set sd_dashHover[sd_dashCount] = udg_SDashHoverHeight
if udg_SDashStarRadius > 0 then
set sd_dashRadius[sd_dashCount] = udg_SDashStarRadius
else
set sd_dashRadius[sd_dashCount] = BlzGetAbilityRealLevelField( GetSpellAbility(), ABILITY_RLF_AREA_OF_EFFECT, sd_dashAbilityLevel[sd_dashCount] - 1 )
endif
set sd_moveTicks[sd_dashCount] = udg_SDashMoveTicks
set sd_turnTicks[sd_dashCount] = udg_SDashTurnTicks
set sd_waitTicks[sd_dashCount] = udg_SDashStandTicks
set sd_dashTicks[sd_dashCount] = m * ( udg_SDashMoveTicks + udg_SDashTurnTicks + udg_SDashStandTicks ) + udg_SDashStandTicks
set sd_dashCaster[sd_dashCount] = u
set sd_casterMoveSpeed[sd_dashCount] = BlzGetUnitRealField( u, UNIT_RF_SPEED )
set sd_casterTurnSpeed[sd_dashCount] = BlzGetUnitRealField( u, UNIT_RF_TURN_RATE )
set sd_casterFlyHeight[sd_dashCount] = BlzGetUnitRealField( u, UNIT_RF_FLY_HEIGHT )
set sd_moveAnimI[sd_dashCount] = udg_SDashMoveAnimationIndex
set sd_turnAnimI[sd_dashCount] = udg_SDashTurnAnimationIndex
set sd_waitAnimI[sd_dashCount] = udg_SDashStandAnimationIndex
set sd_moveAnimR[sd_dashCount] = udg_SDashMoveAnimationRate
set sd_turnAnimR[sd_dashCount] = udg_SDashTurnAnimationRate
set sd_waitAnimR[sd_dashCount] = udg_SDashStandAnimationRate
set sd_dashReturnX[sd_dashCount] = tempx
set sd_dashReturnY[sd_dashCount] = tempy
if t == null then
set sd_dashCenterX[sd_dashCount] = GetLocationX( p )
set sd_dashCenterY[sd_dashCount] = GetLocationY( p )
set tempx = sd_dashCenterX[sd_dashCount] - tempx
set tempy = sd_dashCenterY[sd_dashCount] - tempy
set sd_dashAngle[sd_dashCount] = SD_GetVectorAngle( tempx, tempy )
if sd_dashAngle[sd_dashCount] < 0 then
set sd_dashAngle[sd_dashCount] = bj_PI * GetUnitFacing( u ) / 360
endif
else
if t == null or t == u then
set sd_dashCenterX[sd_dashCount] = tempx
set sd_dashCenterY[sd_dashCount] = tempy
set sd_dashAngle[sd_dashCount] = bj_PI * GetUnitFacing( u ) / 360
else
set sd_dashTarget[sd_dashCount] = t
set sd_dashCenterX[sd_dashCount] = GetUnitX( t )
set sd_dashCenterY[sd_dashCount] = GetUnitY( t )
set tempx = sd_dashCenterX[sd_dashCount] - tempx
set tempy = sd_dashCenterY[sd_dashCount] - tempy
set sd_dashAngle[sd_dashCount] = SD_GetVectorAngle( tempx, tempy )
if sd_dashAngle[sd_dashCount] < 0 then
set sd_dashAngle[sd_dashCount] = bj_PI * GetUnitFacing( u ) / 360
endif
endif
endif
// remove collision and add invulnerabilities
call SetUnitPathing( u, false )
call BlzSetUnitRealField( u, UNIT_RF_SPEED, 0 )
call BlzSetUnitRealField( u, UNIT_RF_TURN_RATE, 0 )
if udg_SDashIsSpellImmune then
call UnitAddAbility( u, udg_SDGlobalSpellImmunity )
endif
if udg_SDashIsInvulnerable then
call UnitAddAbility( u, udg_SDGlobalInvulnerability )
endif
call SetUnitX( u, sd_dashCenterX[sd_dashCount] - sd_dashRadius[sd_dashCount] * Cos( sd_dashAngle[sd_dashCount] ) )
call SetUnitY( u, sd_dashCenterY[sd_dashCount] - sd_dashRadius[sd_dashCount] * Sin( sd_dashAngle[sd_dashCount] ) )
if sd_dashHover[sd_dashCount] != 0 or sd_dashArc[sd_dashCount] != 0 then
if UnitAddAbility( u, 'Arav' ) then
call UnitRemoveAbility( u, 'Arav' )
endif
call SetUnitFlyHeight( u, sd_casterFlyHeight[sd_dashCount] + sd_dashHover[sd_dashCount], 0 )
endif
// move counter and begin dash
set sd_dashCount = sd_dashCount + 1
if not sd_isTickerOn then
set sd_isTickerOn = true
call TimerStart( sd_dashTicker, udg_SDGlobalTickRate, false, function SD_DashTicker )
call SD_CallEvent( sd_dashCount - 1, 1 )
endif
else
call SD_StopUnitAbility( u, a, true )
endif
set udg_SDashMode = 0
set udg_SDashMoveTicks = 0
set udg_SDashTurnTicks = 0
set udg_SDashStandTicks = 0
set udg_SDashStarRadius = 0.00
set udg_SDashJumpHeight = 0.00
set udg_SDashHoverHeight = 0.00
set udg_SDashKeepNewLocation = false
set udg_SDashIsInvulnerable = false
set udg_SDashIsSpellImmune = false
set udg_SDashMoveAnimationIndex = 0
set udg_SDashMoveAnimationRate = -1.00
set udg_SDashTurnAnimationIndex = 0
set udg_SDashTurnAnimationRate = -1.00
set udg_SDashStandAnimationIndex = 0
set udg_SDashStandAnimationRate = -1.00
call RemoveLocation( p )
set u = null
set t = null
endfunction
endlibrary