- Joined
- Mar 27, 2011
- Messages
- 293
Bribe, I could mention one example where I can use your system?
Knockback 2D Config

Events


Game - UnitIndexEvent becomes Equal to 3.00

Conditions

Actions


Set CenterPoint = (Point(K2DX, K2DY))


Set UnitIndexerEnabled = False


-------- --------


-------- Configure things below --------


-------- --------


-------- Set the timeout to be used throughout the system --------


-------- --------


Set K2DTimeout = (1.00 / 60.00)


-------- --------


-------- Robust Pathing at 0 is only safe for collision sizes 16 and lower, but requires only one SetItemPosition check per timeout. --------


-------- -------- 1 checks collision vertically and horizontally to momentum. Uses an extra 4 SetItemPosition checks pet timeout. --------


-------- -------- 2 checks collision diagonally with momentum. Uses a total of 9 SetItemPosition checks per timeout. --------


-------- In any case, if the unit only has size 16 or lower collision, only one SetItemPosition check will be used for it. --------


-------- If RobustPathing is set to 2 and the unit has 36 or less collision, it will only use the normal check of 5 SetItemPosition calls --------


-------- The only reason to use robustness above 1 is for visual continuity - it features potentially-less glitchy movement. --------


-------- --------


Set Knockback2DRobustPathing = 2


-------- --------


-------- Keep the friction between 0.00 and 1.00, At 0.00, friction keeps the unit at the same speed for the knockback --------


-------- 1.00 friction will be an evenly-distributed deceleration which sees the unit slow to a complete stop --------


-------- Friction outside of these bounds gives the knockback a boomerang-effect, so you are welcome to experiment. --------


-------- --------


Set Knockback2DDefaultFriction = 1.00


Set Knockback2DFriction = Knockback2DDefaultFriction


-------- --------


-------- Determine the default bouncing behavior of units. You can set this before knocking a unit back. --------


-------- --------


Set Knockback2DDefaultBounce = True


Set Knockback2DBounces = Knockback2DDefaultBounce


-------- --------


-------- Determine the default mechanics of whether a unit should be unable to move while knocked back --------


-------- --------


Set Knockback2DDefaultPause = False


Set Knockback2DPause = Knockback2DDefaultPause


-------- --------


-------- Determine if surrounding trees should be killed by default or not --------


-------- --------


Set Knockback2DDefaultKillTrees = True


Set Knockback2DKillTrees = Knockback2DDefaultKillTrees


-------- --------


-------- If so, how wide should the radius be? 128.00 should be the minimum if you use pathing robustness greater than 0. --------


-------- The minimum should be 64 if you use a robustness of 0. --------


-------- --------


Set Knockback2DDefaultDestRadius = 128.00


Set Knockback2DDestRadius = Knockback2DDefaultDestRadius


-------- --------


-------- The "attack" option below will destroy any valid debris, from trees to barrels to creep homes. --------


-------- If you just want to destroy trees, change the string to: harvest --------


-------- --------


Set Knockback2DTreeOrDebris = attack


-------- --------


-------- 0.50 gravity will have equal ascend and decline rate, 1.00 is instant descend, 0.67 is twice as fast, 0.75 is three times as fast. --------


-------- --------


Set Knockback2DDefaultGravity = 0.71


Set Knockback2DGravity = Knockback2DDefaultGravity


-------- --------


-------- Change the following to the default type of looping FX you want to have if you use Knockback Effects --------


-------- --------


Set Knockback2DDefaultFX = Abilities\Weapons\AncientProtectorMissile\AncientProtectorMissile.mdl


Set Knockback2DLoopFX = Knockback2DDefaultFX


-------- --------


-------- How frequently should the effects appear per unit? This can also be customized per-knockback --------


-------- --------


Set Knockback2DDefaultFXRate = 0.10


Set Knockback2DFXRate = Knockback2DDefaultFXRate


-------- --------


-------- Create an item to help verify pathing throughout the game --------


-------- --------


Item - Create Slippers of Agility +3 at CenterPoint


Set K2DItem = (Last created item)


-------- --------


-------- Create a harvest-capable unit to check if debris can be killed --------


-------- --------


Unit - Create 1 Ghoul for Neutral Passive at CenterPoint facing 0.00 degrees


Set K2DDebrisKiller = (Last created unit)


-------- --------


-------- End Configuration --------


-------- --------


Set UnitIndexerEnabled = True


Custom script: call RemoveLocation(udg_CenterPoint)


Game - Preload Knockback2DDefaultFX


Item - Hide K2DItem


Unit - Hide K2DDebrisKiller


Unit - Pause K2DDebrisKiller


Custom script: call UnitAddAbility(udg_K2DDebrisKiller, 'Aloc')


Set Radians_Turn = (Radians(360.00))


Set Radians_QuarterTurn = (Radians(90.00))


Set Radians_QuarterPi = (Radians(45.00))


Set K2DRegion = (Entire map)


Set K2DMaxX = (Max X of K2DRegion)


Set K2DMaxY = (Max Y of K2DRegion)


Set K2DMinX = (Min X of K2DRegion)


Set K2DMinY = (Min Y of K2DRegion)


Set K2DMaxDestRadius = (Knockback2DDefaultDestRadius x 2.00)


Custom script: call SetRect(udg_K2DRegion, 0.00, 0.00, udg_K2DMaxDestRadius, udg_K2DMaxDestRadius)


Set K2DItemsFound = False


Set K2DItemOffset = False
Knockback 2D

Events

Conditions


(Default movement speed of Knockback2DUnit) Not equal to 0.00


K2DOverride[(Custom value of Knockback2DUnit)] Equal to False

Actions


Custom script: local integer pdex = udg_UDex


Set UDex = (Custom value of Knockback2DUnit)


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




IsUnitBeingKnockedBack[UDex] Equal to True



Then - Actions




If (All Conditions are True) then do (Then Actions) else do (Else Actions)





If - Conditions






Knockback2DOverride Equal to False





Then - Actions






Set K2DAngle[UDex] = (Degrees(K2DAngle[UDex]))






Set Knockback2DAngle = ((Knockback2DAngle + K2DAngle[UDex]) x 0.50)






Set Knockback2DDistance = ((K2DDistanceLeft[UDex] + Knockback2DDistance) x 0.50)






Set Knockback2DTime = ((K2DTimeLeft[UDex] + Knockback2DTime) x 0.50)





Else - Actions




Trigger - Run Knockback 2D Destroy <gen> (ignoring conditions)



Else - Actions


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




K2DNext[0] Equal to 0



Then - Actions




Custom script: call ExecuteFunc("StartKnockback2DTimer")



Else - Actions


Set IsUnitBeingKnockedBack[UDex] = True


Set K2DPrev[K2DNext[0]] = UDex


Set K2DNext[UDex] = K2DNext[0]


Set K2DNext[0] = UDex


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




Knockback2DHeight Not equal to 0.00



Then - Actions




Set K2DHeight[UDex] = Knockback2DHeight




Custom script: if UnitAddAbility(udg_Knockback2DUnit, 'Amrf') then




Custom script: call UnitRemoveAbility(udg_Knockback2DUnit, 'Amrf')




Custom script: endif




Animation - Change Knockback2DUnit flying height to ((Default flying height of Knockback2DUnit) + Knockback2DHeight) at ((Knockback2DHeight - (Default flying height of Knockback2DUnit)) / (Knockback2DGravity x Knockback2DTime))




Set K2DHeightThreshold[UDex] = ((1.00 - Knockback2DGravity) x Knockback2DTime)




Set Knockback2DHeight = 0.00



Else - Actions




Set K2DHeight[UDex] = 0.00


Custom script: set udg_K2DX = GetUnitX(udg_Knockback2DUnit)


Custom script: set udg_K2DY = GetUnitY(udg_Knockback2DUnit)


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




Knockback2DPause Equal to True



Then - Actions




Set K2DLastX[UDex] = K2DX




Set K2DLastY[UDex] = K2DY



Else - Actions


Set K2DAngle[UDex] = (Radians(Knockback2DAngle))


Set K2DCos[UDex] = (Cos(Knockback2DAngle))


Set K2DSin[UDex] = (Sin(Knockback2DAngle))


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




Knockback2DRobustPathing Greater than 0



Then - Actions




-------- --------




-------- Handle the pathing checker based on the unit's collision size --------




-------- --------




Custom script: if not IsUnitInRangeXY(udg_Knockback2DUnit, udg_K2DX + 17, udg_K2DY, 0) then




Set K2DRadius[UDex] = 0




Custom script: else




Custom script: if not IsUnitInRangeXY(udg_Knockback2DUnit, udg_K2DX + 25, udg_K2DY, 0) then




Set K2DRadius[UDex] = 8




Custom script: elseif not IsUnitInRangeXY(udg_Knockback2DUnit, udg_K2DX + 33, udg_K2DY, 0) then




Set K2DRadius[UDex] = 16




Custom script: elseif not IsUnitInRangeXY(udg_Knockback2DUnit, udg_K2DX + 49, udg_K2DY, 0) then




Set K2DRadius[UDex] = 32




Custom script: else




Set K2DRadius[UDex] = 48




Custom script: endif




Set Knockback2DAngle = ((Knockback2DAngle + 90.00) mod 360.00)




Set K2DCosH[UDex] = (Cos(Knockback2DAngle))




Set K2DSinH[UDex] = (Sin(Knockback2DAngle))




If (All Conditions are True) then do (Then Actions) else do (Else Actions)





If - Conditions






Knockback2DRobustPathing Equal to 2






K2DRadius[UDex] Greater than 16





Then - Actions






Set Knockback2DAngle = ((Knockback2DAngle + 45.00) mod 360.00)






Set K2DCosD1[UDex] = (Cos(Knockback2DAngle))






Set K2DSinD1[UDex] = (Sin(Knockback2DAngle))






Set Knockback2DAngle = ((Knockback2DAngle + 90.00) mod 360.00)






Set K2DCosD2[UDex] = (Cos(Knockback2DAngle))






Set K2DSinD2[UDex] = (Sin(Knockback2DAngle))





Else - Actions




Custom script: endif



Else - Actions


Set K2DDistanceLeft[UDex] = Knockback2DDistance


Set Knockback2DDistance = (((1.00 + Knockback2DFriction) x Knockback2DDistance) / Knockback2DTime)


Set K2DFriction[UDex] = ((Knockback2DDistance / Knockback2DTime) x ((1.00 - (1.00 - Knockback2DFriction)) x (K2DTimeout x K2DTimeout)))


Set K2DVelocity[UDex] = (Knockback2DDistance x K2DTimeout)


-------- --------


Set K2DKillTrees[UDex] = Knockback2DKillTrees


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




Knockback2DKillTrees Equal to True



Then - Actions




-------- Square the radius so we don't have to use SquareRoot when comparing distance. --------




Set K2DDestRadius[UDex] = (Knockback2DDestRadius x Knockback2DDestRadius)




If (All Conditions are True) then do (Then Actions) else do (Else Actions)





If - Conditions






(Knockback2DDestRadius x 2.00) Greater than K2DMaxDestRadius





Then - Actions






-------- Update the size of the enumerating rect to compensate for the desired extra radius. --------






Set K2DMaxDestRadius = (Knockback2DDestRadius x 2.00)






Custom script: call SetRect(udg_K2DRegion, 0.00, 0.00, udg_K2DMaxDestRadius, udg_K2DMaxDestRadius)





Else - Actions




Set Knockback2DDestRadius = Knockback2DDefaultDestRadius



Else - Actions


-------- --------


Set K2DAmphibious[UDex] = Knockback2DAmphibious


Set K2DBounce[UDex] = Knockback2DBounces


Set K2DCollision[UDex] = Knockback2DCollision


Set K2DFreeze[UDex] = False


Set K2DFXModel[UDex] = Knockback2DLoopFX


Set K2DFXRate[UDex] = Knockback2DFXRate


Set K2DFXTimeLeft[UDex] = Knockback2DFXRate


Set K2DImpact[UDex] = Knockback2DOnImpact


Set K2DOverride[UDex] = Knockback2DOverride


Set K2DPause[UDex] = Knockback2DPause


Set K2DSimple[UDex] = Knockback2DSimple


Set K2DSource[UDex] = Knockback2DSource


Set K2DTimeLeft[UDex] = Knockback2DTime


Set K2DUnbiasedCollision[UDex] = Knockback2DUnbiasedCollision


Set Knockback2DAmphibious = False


Set Knockback2DBounces = Knockback2DDefaultBounce


Set Knockback2DCollision = 0.00


Set Knockback2DFriction = Knockback2DDefaultFriction


Set Knockback2DFXRate = Knockback2DDefaultFXRate


Set Knockback2DGravity = Knockback2DDefaultGravity


Set Knockback2DKillTrees = Knockback2DDefaultKillTrees


Set Knockback2DLoopFX = Knockback2DDefaultFX


Custom script: set udg_Knockback2DOnImpact = null


Set Knockback2DOverride = False


Set Knockback2DPause = Knockback2DDefaultPause


Set Knockback2DSimple = False


Set Knockback2DSource = No unit


Set Knockback2DUnbiasedCollision = False


Custom script: set udg_UDex = pdex
function K2DItemCheckXY takes real x, real y returns boolean
call SetItemPosition(udg_K2DItem, x, y)
return RAbsBJ(GetWidgetX(udg_K2DItem) - x +GetWidgetY(udg_K2DItem) - y) < 1
endfunction
function K2DItemCheckAxis takes real x, real y returns boolean
local real x2 = x*udg_K2DRadius[udg_UDex]
local real y2 = y*udg_K2DRadius[udg_UDex]
set x = udg_K2DX + x2
set y = udg_K2DY + y2
if K2DItemCheckXY(x, y) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) then
set x = udg_K2DX - x2
set y = udg_K2DY - y2
return K2DItemCheckXY(x, y) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY)
endif
return false
endfunction
function K2DItemCheck takes nothing returns boolean
local boolean result = K2DItemCheckXY(udg_K2DX, udg_K2DY)
//Only perform additional pathing checks if the unit has a larger collision.
if result and udg_Knockback2DRobustPathing > 0 and udg_K2DRadius[udg_UDex] > 0 then
//Check horizontal axis of unit to make sure nothing is going to collide
set result = K2DItemCheckAxis(udg_K2DCosH[udg_UDex], udg_K2DSinH[udg_UDex])
//Check vertical axis of unit to ensure nothing will collide
set result = result and K2DItemCheckAxis(udg_K2DCos[udg_UDex], udg_K2DSin[udg_UDex])
if result and udg_Knockback2DRobustPathing == 2 and udg_K2DRadius[udg_UDex] > 16 then
//Check diagonal axis of unit if more thorough pathing is desired
set result = K2DItemCheckAxis(udg_K2DCosD1[udg_UDex], udg_K2DSinD1[udg_UDex])
set result = result and K2DItemCheckAxis(udg_K2DCosD2[udg_UDex], udg_K2DSinD2[udg_UDex])
endif
endif
//Reset item so it won't interfere with the map
call SetItemPosition(udg_K2DItem, udg_K2DMaxX, udg_K2DMaxY)
call SetItemVisible(udg_K2DItem, false)
return result
endfunction
function K2DItemFilter takes nothing returns boolean
//Check for visible items, temporarily hide them and add them to the filter.
if IsItemVisible(GetFilterItem()) then
call SetItemVisible(GetFilterItem(), false)
return true
endif
return false
endfunction
function K2DItemCode takes nothing returns nothing
//Perform the item-pathing check only once, then unhide those filtered items
if not udg_K2DItemsFound then
set udg_K2DItemsFound = true
set udg_K2DItemOffset = K2DItemCheck()
endif
call SetItemVisible(GetEnumItem(), true)
endfunction
function K2DKillDest takes nothing returns nothing
local real x
local real y
//Handle destruction of debris
set bj_destRandomCurrentPick = GetEnumDestructable()
if GetWidgetLife(bj_destRandomCurrentPick) > 0.405 and IssueTargetOrder(udg_K2DDebrisKiller, udg_Knockback2DTreeOrDebris, bj_destRandomCurrentPick) then
set x = GetWidgetX(bj_destRandomCurrentPick) - udg_K2DX
set y = GetWidgetY(bj_destRandomCurrentPick) - udg_K2DY
if x*x + y*y <= udg_K2DDestRadius[udg_UDex] then
call KillDestructable(bj_destRandomCurrentPick)
endif
endif
endfunction
function K2DEnumDests takes nothing returns nothing
call MoveRectTo(udg_K2DRegion, udg_K2DX, udg_K2DY)
if udg_K2DKillTrees[udg_UDex] then
call SetUnitX(udg_K2DDebrisKiller, udg_K2DX)
call SetUnitY(udg_K2DDebrisKiller, udg_K2DY)
call EnumDestructablesInRect(udg_K2DRegion, null, function K2DKillDest)
endif
endfunction
function Knockback2DCheckXY takes real x, real y returns boolean
set udg_K2DX = x + udg_K2DVelocity[udg_UDex]*udg_K2DCos[udg_UDex]
set udg_K2DY = y + udg_K2DVelocity[udg_UDex]*udg_K2DSin[udg_UDex]
if udg_K2DSimple[udg_UDex] then
//A "pull" effect or a missile system does not require complex pathing.
if udg_K2DX <= udg_K2DMaxX and udg_K2DX >= udg_K2DMinX and udg_K2DY <= udg_K2DMaxY and udg_K2DY >= udg_K2DMinY then
call K2DEnumDests()
return true
endif
return false
elseif udg_K2DFlying[udg_UDex] then
return not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_FLYABILITY)
elseif not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_WALKABILITY) then
call K2DEnumDests()
set udg_K2DItemOffset = false
call EnumItemsInRect(udg_K2DRegion, Filter(function K2DItemFilter), function K2DItemCode)
if udg_K2DItemsFound then
//If items were found, the check was already performed.
set udg_K2DItemsFound = false
else
//Otherwise, perform the check right now.
set udg_K2DItemOffset = K2DItemCheck()
endif
return udg_K2DItemOffset
endif
return udg_K2DAmphibious[udg_UDex] and not IsTerrainPathable(udg_K2DX, udg_K2DY, PATHING_TYPE_FLOATABILITY)
endfunction
function Knockback2DApplyAngle takes real angle returns nothing
set angle = ModuloReal(angle, udg_Radians_Turn)
set udg_K2DCos[udg_UDex] = Cos(angle)
set udg_K2DSin[udg_UDex] = Sin(angle)
set udg_K2DAngle[udg_UDex] = angle
if udg_Knockback2DRobustPathing > 0 then
set angle = ModuloReal(angle + udg_Radians_QuarterTurn, udg_Radians_Turn)
set udg_K2DCosH[udg_UDex] = Cos(angle)
set udg_K2DSinH[udg_UDex] = Sin(angle)
if udg_Knockback2DRobustPathing == 2 and udg_K2DRadius[udg_UDex] > 16 then
set angle = ModuloReal(angle + udg_Radians_QuarterPi, udg_Radians_Turn)
set udg_K2DCosD1[udg_UDex] = Cos(angle)
set udg_K2DSinD1[udg_UDex] = Sin(angle)
set angle = ModuloReal(angle + udg_Radians_QuarterTurn, udg_Radians_Turn)
set udg_K2DCosD2[udg_UDex] = Cos(angle)
set udg_K2DSinD2[udg_UDex] = Sin(angle)
endif
endif
endfunction
function Knockback2DLooper takes nothing returns nothing
local integer i = 0
local unit u
local real x
local real y
call PauseUnit(udg_K2DDebrisKiller, false)
loop
set i = udg_K2DNext[i]
exitwhen i == 0
set udg_UDex = i
set udg_K2DTimeLeft[i] = udg_K2DTimeLeft[i] - udg_K2DTimeout
set udg_K2DDistanceLeft[i] = udg_K2DDistanceLeft[i] - udg_K2DVelocity[i]
set u = udg_UDexUnits[i]
if udg_K2DTimeLeft[i] > 0.00 then
if udg_K2DTimeLeft[i] < udg_K2DHeightThreshold[i] and udg_K2DHeightThreshold[i] != 0.00 then
call SetUnitFlyHeight(u, GetUnitDefaultFlyHeight(u), GetUnitFlyHeight(u) - GetUnitDefaultFlyHeight(u)/udg_K2DHeightThreshold[i])
set udg_K2DHeightThreshold[i] = 0.00
endif
if udg_K2DPause[i] then
set x = udg_K2DLastX[i]
set y = udg_K2DLastY[i]
else
set x = GetUnitX(u)
set y = GetUnitY(u)
endif
if not Knockback2DCheckXY(x, y) then
if not udg_K2DFreeze[i] and IsTriggerEnabled(udg_K2DImpact[i]) and TriggerEvaluate(udg_K2DImpact[i]) then
call TriggerExecute(udg_K2DImpact[i])
endif
if udg_K2DBounce[i] then
call Knockback2DApplyAngle(udg_Radians_Turn - udg_K2DAngle[i])
if not Knockback2DCheckXY(x, y) then
call Knockback2DApplyAngle(udg_K2DAngle[i] + bj_PI)
if not Knockback2DCheckXY(x, y) then
call Knockback2DApplyAngle(udg_Radians_Turn - udg_K2DAngle[i])
set udg_K2DX = x
set udg_K2DY = y
endif
endif
else
set udg_K2DX = x
set udg_K2DY = y
set udg_K2DFreeze[i] = true
endif
endif
call SetUnitX(u, udg_K2DX)
call SetUnitY(u, udg_K2DY)
set udg_K2DLastX[i] = udg_K2DX
set udg_K2DLastY[i] = udg_K2DY
if udg_K2DFXModel[i] != "" then
set udg_K2DFXTimeLeft[i] = udg_K2DFXTimeLeft[i] - udg_K2DTimeout
if udg_K2DFXTimeLeft[i] <= 0.00 then
set udg_K2DFXTimeLeft[i] = udg_K2DFXRate[i]
if udg_K2DFlying[i] then
call DestroyEffect(AddSpecialEffectTarget(udg_K2DFXModel[i], u, "origin"))
else
call DestroyEffect(AddSpecialEffect(udg_K2DFXModel[i], udg_K2DX, udg_K2DY))
endif
endif
endif
if udg_K2DCollision[i] >= 0.00 then
set udg_Knockback2DSource = u
call GroupEnumUnitsInRange(bj_lastCreatedGroup, udg_K2DX, udg_K2DY, 200.00, null)
call GroupRemoveUnit(bj_lastCreatedGroup, u)
loop
set udg_Knockback2DUnit = FirstOfGroup(bj_lastCreatedGroup)
exitwhen udg_Knockback2DUnit == null
call GroupRemoveUnit(bj_lastCreatedGroup, udg_Knockback2DUnit)
if IsUnitInRange(udg_Knockback2DUnit, u, udg_K2DCollision[i]) and udg_K2DFlying[i] == IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_FLYING) and (not IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_STRUCTURE)) and not IsUnitType(udg_Knockback2DUnit, UNIT_TYPE_DEAD) and (udg_K2DUnbiasedCollision[i] or IsUnitAlly(udg_Knockback2DUnit, GetOwningPlayer(u))) and TriggerEvaluate(gg_trg_Knockback_2D) then
set udg_Knockback2DAngle = bj_RADTODEG * Atan2(GetUnitY(udg_Knockback2DUnit) - udg_K2DY, GetUnitX(udg_Knockback2DUnit) - udg_K2DX)
set udg_Knockback2DDistance = udg_K2DDistanceLeft[i]
set udg_Knockback2DBounces = udg_K2DBounce[i]
set udg_Knockback2DCollision = udg_K2DCollision[i]
if udg_K2DHeight[i] != 0.00 then
set udg_Knockback2DHeight = GetUnitFlyHeight(u) - GetUnitDefaultFlyHeight(u)
endif
set udg_Knockback2DLoopFX = udg_K2DFXModel[I]
set udg_Knockback2DTime = udg_K2DTimeLeft[i]
set udg_Knockback2DUnbiasedCollision = udg_K2DUnbiasedCollision[i]
call TriggerExecute(gg_trg_Knockback_2D)
set udg_Knockback2DSource = u //in case of a recursive knockback
endif
endloop
endif
set udg_K2DVelocity[i] = udg_K2DVelocity[i] - udg_K2DFriction[i]
else
call TriggerExecute(gg_trg_Knockback_2D_Destroy)
endif
endloop
set u = null
//Disable dummy after the loop finishes so it doesn't interfere with the map
call PauseUnit(udg_K2DDebrisKiller, true)
endfunction
//===========================================================================
function StartKnockback2DTimer takes nothing returns nothing
call TimerStart(udg_K2DTimer, udg_K2DTimeout, true, function Knockback2DLooper)
endfunction
function InitTrig_Knockback_2D_System takes nothing returns nothing
endfunction
Knockback 2D Destroy

Events


Game - UnitIndexEvent becomes Equal to 2.00

Conditions


IsUnitBeingKnockedBack[UDex] Equal to True

Actions


-------- --------


-------- This trigger destroys any knockback; you can execute it yourself by first setting UDex to the custom value --------


-------- --------


Set IsUnitBeingKnockedBack[UDex] = False


Set K2DNext[K2DPrev[UDex]] = K2DNext[UDex]


Set K2DPrev[K2DNext[UDex]] = K2DPrev[UDex]


Set K2DPrev[UDex] = 0


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




K2DNext[0] Equal to 0



Then - Actions




Countdown Timer - Pause K2DTimer



Else - Actions


Set Knockback2DUnit = UDexUnits[UDex]


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




K2DHeight[UDex] Not equal to 0.00



Then - Actions




Animation - Change Knockback2DUnit flying height to (Default flying height of Knockback2DUnit) at 0.00



Else - Actions


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




K2DFreeze[UDex] Not equal to True




(K2DImpact[UDex] is on) Equal to True



Then - Actions




Trigger - Run K2DImpact[UDex] (checking conditions)



Else - Actions
On Damage

Events


Game - DamageModifierEvent becomes Equal to 1.00

Conditions

Actions


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




IsDamageSpell Equal to False




(Owner of DamageEventSource) Equal to Player 1 (Red)



Then - Actions




-------- --------




-------- There are four required variables when issuing a knockback --------




-------- --------




-------- 1. Knockback2DAngle -------- this is the direction angle the unit is knocked back (in degrees) --------




-------- 2. Knockback2DTime -------- this is how long the unit will be knocked back (in seconds) --------




-------- 3. Knockback2DDistance -------- this is how far the unit will be knocked back --------




-------- 4. Knockback2DUnit -------- this is the unit being knocked back --------




-------- --------




-------- When all four variables are set, you can run the Knockback 2D trigger, ignoring conditions --------




-------- --------




Set CenterPoint = (Position of DamageEventSource)




Set TargetPoint = (Position of DamageEventTarget)




Set Knockback2DAngle = (Angle from CenterPoint to TargetPoint)




Custom script: call RemoveLocation(udg_CenterPoint)




Custom script: call RemoveLocation(udg_TargetPoint)




Set Knockback2DTime = 0.90




Set Knockback2DDistance = 500.00




Set Knockback2DUnit = DamageEventTarget




If (All Conditions are True) then do (Then Actions) else do (Else Actions)





If - Conditions






(Owner of DamageEventSource) Not equal to (Owner of DamageEventTarget)





Then - Actions






-------- --------






-------- There are optional variables you can consider when issuing a knockback --------






-------- If they are not set, "0.00, false, null" or their default states assigned in the Knockback 2D Config trigger will be used --------






-------- --------






-------- Knockback2DAmphibious -------- Allows the unit to pass over deep water, but it is more performance-intensive --------






-------- -------- If you aren't ToolOrDie from TheHiveWorkshop, you probably won't use this --------






-------- Knockback2DBounces -------- if the unit will bounce off of walls or remain stunned there. --------






-------- --------






-------- Knockback2DCollision -------- You can specify the collision radius of units to be adjacently knocked back if you want --------






-------- -------- A value of 0 will require the units' collision sizes to overlap to knock back --------






-------- -------- A value greater than 0 will allow that much space between the units to still permit the knockback --------






-------- -------- A value less than 0 will disable collision checking altogether. --------






-------- --------






-------- Knockback2DDestRadius -------- If debris is to be killed, how far away must it be? --------






-------- Knockback2DFriction -------- How quickly the unit will slow down from its initial speed. --------






-------- Knockback2DFX -------- What kind of special effect will occasionally be played on the ground of the unit --------






-------- Knockback2DFXRate -------- How often should the effect appear? --------






-------- Knockback2DGravity -------- If you want to specify a custom gravity for each knockback, you can --------






-------- Knockback2DHeight -------- How high you want the unit to go during the knockback --------






-------- Knockback2DKillTrees -------- If you want surrounding trees to die, this is for you --------






-------- Knockback2DOnImpact -------- this trigger is run when the unit hits a wall or structure. --------






-------- -------- If it is bouncing, it can hit multiple walls and fire this trigger multiple times --------






-------- -------- The trigger will not run if it is off, so you can use this if you only want it to run on the first bounce --------






-------- Knockback2DOverride -------- Set this to true to prevent future knockbacks from interrupting this one --------






-------- Knockback2DPause -------- confines the unit to its knockback velocity (no running to change course) --------






-------- Knockback2DSimple -------- Only checks to make sure unit movement is within the map bounds --------






-------- Knockback2DSource -------- If you need to store this unit to deal damage on-impact or within the timer loop --------






-------- Knockback2DUnbiasedCollision -------- Should adjacent knockbacks consider alliances or be neutral? --------






-------- --------






Set Knockback2DAmphibious = True






Set Knockback2DBounces = False






Set Knockback2DCollision = 16.00






Set Knockback2DDestRadius = 128.00






Set Knockback2DGravity = 0.67






Set Knockback2DHeight = 137.00






Set Knockback2DKillTrees = False






Set Knockback2DOnImpact = On Impact <gen>






Set Knockback2DOverride = True






Set Knockback2DPause = True






Set Knockback2DSimple = True






Set Knockback2DSource = DamageEventSource






Set Knockback2DUnbiasedCollision = False





Else - Actions






-------- Allied units shouldn't allow collision with each other, but for the sake of the demo let's make it interesting --------






Set Knockback2DCollision = 32.00






-------- Also make it so that enemies will bounce with these experiments --------






Set Knockback2DUnbiasedCollision = True






Set Knockback2DLoopFX = Abilities\Weapons\FaerieDragonMissile\FaerieDragonMissile.mdl






Set Knockback2DFXRate = 0.20




-------- --------




-------- When all variables are set, run the Knockback 2D trigger, checking conditions if you want to be safe --------




-------- --------




Trigger - Run Knockback 2D <gen> (checking conditions)



Else - Actions




If (All Conditions are True) then do (Then Actions) else do (Else Actions)





If - Conditions






Or - Any (Conditions) are true







Conditions








Tauren_Shockwave[(Custom value of DamageEventSource)] Equal to True








Tauren_WarStomp[(Custom value of DamageEventSource)] Equal to True





Then - Actions






Set CenterPoint = (Position of DamageEventSource)






Set TargetPoint = (Position of DamageEventTarget)






Set Knockback2DAngle = (Angle from CenterPoint to TargetPoint)






Custom script: call RemoveLocation(udg_CenterPoint)






Custom script: call RemoveLocation(udg_TargetPoint)






Set Knockback2DTime = 0.50






Set Knockback2DDistance = 75.00






Set Knockback2DUnit = DamageEventTarget






If (All Conditions are True) then do (Then Actions) else do (Else Actions)







If - Conditions








Tauren_WarStomp[(Custom value of DamageEventSource)] Equal to True







Then - Actions








-------- For War Stomp, add a height factor --------








Set Knockback2DHeight = 250.00








Set Knockback2DDistance = 100.00







Else - Actions








Set Knockback2DDistance = 300.00






Trigger - Run Knockback 2D <gen> (ignoring conditions)





Else - Actions


-------- Deleting the next line will re-enable damage in the map --------


Set DamageEventAmount = 0.00
On Spell Cast

Events


Unit - A unit owned by Player 1 (Red) Starts the effect of an ability

Conditions

Actions


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




(Ability being cast) Equal to Shockwave



Then - Actions




Set Tauren_Shockwave[(Custom value of (Triggering unit))] = True



Else - Actions




If (All Conditions are True) then do (Then Actions) else do (Else Actions)





If - Conditions






(Ability being cast) Equal to War Stomp





Then - Actions






Set Tauren_WarStomp[(Custom value of (Triggering unit))] = True





Else - Actions
On Spell Stop

Events


Unit - A unit owned by Player 1 (Red) Stops casting an ability

Conditions

Actions


Unit - Reset ability cooldowns for (Triggering unit)


Unit - Set mana of (Triggering unit) to 100.00%


If (All Conditions are True) then do (Then Actions) else do (Else Actions)



If - Conditions




(Ability being cast) Equal to Shockwave



Then - Actions




-------- In case the unit had other damaging spells, we don't want those spells to trigger an unwanted knockback --------




Set Tauren_Shockwave[(Custom value of (Triggering unit))] = False



Else - Actions




If (All Conditions are True) then do (Then Actions) else do (Else Actions)





If - Conditions






(Ability being cast) Equal to War Stomp





Then - Actions






-------- Same goes for here --------






Set Tauren_WarStomp[(Custom value of (Triggering unit))] = False





Else - Actions
//Each [ ] represents a SetItemPosition call on that space
//Collision when pathing robustness is set to 0 or the unit's collision size is
//set to 16 is simply one SetItemPosition call.
//With robustness set to 1 or the unit has 32 collision:
[ ]
[ ][ ][ ]
[ ]
//With robustness set to 2 and the unit has 48 collision:
[ ]
[ ] [ ]
[ ] [ ] [ ]
[ ] [ ]
[ ]
//At 64 collision, the white spaces just become more pronounced.
//As you can see, knocking back a unit with more than 32 collision size and
//robustness set to 2 requires quite a few SetItemPosition calls. I am not using
//SetUnitPosition with a dummy due to potential "enter/leave region" events in a
//user's map.