Name | Type | is_array | initial_value |
CenterPoint | location | No | |
CreepFacing | real | Yes | |
CreepLoc | location | Yes | |
IsUnitBeingKnockedBack | boolean | Yes | |
IsUnitPreplaced | boolean | Yes | |
K2DAmphibious | boolean | Yes | |
K2DAngle | real | Yes | |
K2DBounce | boolean | Yes | |
K2DCollision | real | Yes | |
K2DCos | real | Yes | |
K2DCosD1 | real | Yes | |
K2DCosD2 | real | Yes | |
K2DCosH | real | Yes | |
K2DDebrisKiller | unit | No | |
K2DDestRadius | real | Yes | |
K2DDistanceLeft | real | Yes | |
K2DFlying | boolean | Yes | |
K2DFreeze | boolean | Yes | |
K2DFriction | real | Yes | |
K2DFXModel | string | Yes | |
K2DFXRate | real | Yes | |
K2DFXTimeLeft | real | Yes | |
K2DHeight | real | Yes | |
K2DHeightThreshold | real | Yes | |
K2DImpact | trigger | Yes | |
K2DItem | item | No | |
K2DItemOffset | boolean | No | |
K2DItemsFound | boolean | No | |
K2DKillTrees | boolean | Yes | |
K2DLastX | real | Yes | |
K2DLastY | real | Yes | |
K2DMaxDestRadius | real | No | |
K2DMaxX | real | No | |
K2DMaxY | real | No | |
K2DMinX | real | No | |
K2DMinY | real | No | |
K2DNext | integer | Yes | |
K2DOverride | boolean | Yes | |
K2DPause | boolean | Yes | |
K2DPrev | integer | Yes | |
K2DRadius | integer | Yes | |
K2DRegion | rect | No | |
K2DSimple | boolean | Yes | |
K2DSin | real | Yes | |
K2DSinD1 | real | Yes | |
K2DSinD2 | real | Yes | |
K2DSinH | real | Yes | |
K2DSource | unit | Yes | |
K2DTimeLeft | real | Yes | |
K2DTimeout | real | No | |
K2DTimer | timer | No | |
K2DUnbiasedCollision | boolean | Yes | |
K2DVelocity | real | Yes | |
K2DX | real | No | |
K2DY | real | No | |
Knockback2DAmphibious | boolean | No | |
Knockback2DAngle | real | No | |
Knockback2DBounces | boolean | No | |
Knockback2DCollision | real | No | |
Knockback2DDefaultBounce | boolean | No | |
Knockback2DDefaultDestRadius | real | No | |
Knockback2DDefaultFriction | real | No | |
Knockback2DDefaultFX | string | No | |
Knockback2DDefaultFXRate | real | No | |
Knockback2DDefaultGravity | real | No | |
Knockback2DDefaultKillTrees | boolean | No | |
Knockback2DDefaultPause | boolean | No | |
Knockback2DDestRadius | real | No | |
Knockback2DDistance | real | No | |
Knockback2DFriction | real | No | |
Knockback2DFXRate | real | No | |
Knockback2DGravity | real | No | |
Knockback2DHeight | real | No | |
Knockback2DKillTrees | boolean | No | |
Knockback2DLoopFX | string | No | |
Knockback2DOnImpact | trigger | No | |
Knockback2DOverride | boolean | No | |
Knockback2DPause | boolean | No | |
Knockback2DRobustPathing | integer | No | |
Knockback2DSimple | boolean | No | |
Knockback2DSource | unit | No | |
Knockback2DTime | real | No | |
Knockback2DTreeOrDebris | string | No | |
Knockback2DUnbiasedCollision | boolean | No | |
Knockback2DUnit | unit | No | |
LoopInt | integer | No | |
p | player | No | |
Radians_QuarterPi | real | No | |
Radians_QuarterTurn | real | No | |
Radians_Turn | real | No | |
SKBO_Accel | real | Yes | |
SKBO_Aoe | real | Yes | |
SKBO_Caster | unit | Yes | |
SKBO_CurrentHeight | real | Yes | |
SKBO_Dmg | real | Yes | |
SKBO_DTargetX | real | Yes | |
SKBO_DTargetY | real | Yes | |
SKBO_DummyCaster | unit | No | |
SKBO_DummyUnit | unit | Yes | |
SKBO_DummyUnit2 | unit | Yes | |
SKBO_DummyUnit3 | unit | Yes | |
SKBO_MaxIndex | integer | No | |
SKBO_NodeNext | integer | Yes | |
SKBO_NodePrev | integer | Yes | |
SKBO_Number | integer | Yes | |
SKBO_Parent | integer | Yes | |
SKBO_Player | player | Yes | |
SKBO_RecycledSize | integer | No | |
SKBO_RecycledStack | integer | Yes | |
SKBO_Stage | integer | Yes | |
SKBO_STargetX | real | Yes | |
SKBO_STargetY | real | Yes | |
SKBO_Teleported | boolean | Yes | |
SKBO_Timer | timer | No | |
SKBO_Velocity | real | Yes | |
TempInt | integer | No | |
TempLoc | location | No | |
UDex | integer | No | |
UDexGen | integer | No | |
UDexNext | integer | Yes | |
UDexPrev | integer | Yes | |
UDexRecycle | integer | No | |
UDexUnits | unit | Yes | |
UDexWasted | integer | No | |
UnitIndexerEnabled | boolean | No | |
UnitIndexEvent | real | No |
//TESH.scrollpos=0
//TESH.alwaysfold=0
function K2DItemCheckXY takes real x, real y returns boolean
call SetItemPosition(udg_K2DItem, x, y)
return GetWidgetX(udg_K2DItem) == x and GetWidgetY(udg_K2DItem) == y
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
//---------------------------------------------------------------------------
//
// Rheiko presents
// Skyfall Boulders v1.0
//
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Description:
// Conjures a number of boulders up in the sky and creates two
// portals, one right below the boulders and another right above
// the target location, connected to each other, increasing the
// fall duration, allowing the boulders to hit the ground
// with lethal impact, causing 2 seconds stun to the nearby
// enemies units and knocking them back.
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
// Credits:
// - AlienAtSystem for CircleOutBuff.mdx and
// CircleOutBuff_Portrait.mdx
// - WILL THE ALMIGHTY for NewDirtEXNofire.mdx
// - Bribe for Knockback2D System
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//
// == HOW TO IMPORT ==
//
// 1. Copy Skyfall Boulders ability from Object Editor and paste it
// into your map.
// 2. Copy Skyfall Boulders (Stun) ability from Object Editor and
// paste it into your map.
// 3. Copy SB_Dummy1, SB_Dummy2, SB_Dummy3, SB_Dummy4, SB_DummyCaster
// unit from Object Editor and paste them into your map.
// 4. Make sure your World Editor has "Automatically Create Unknown
// Variable" enabled. You can find it in File => Preferences
// 5. Copy the trigger in Skyfall Boulders folder and in Knockback2D
// folder (Optional) and paste them into your map.
// 6. Double check to make sure everything works properly.
//
// Note:
// If you prefer to not import Knockback2D and does not want to
// utilize the Knockback aspect of the spell, simply import the
// triggers in Skyfall Boulders. You can leave the triggers in
// Knockback2D out. But make sure you change the value of:
//
// constant function SKBO_KBTrigger takes nothing returns trigger
// return gg_trg_Knockback_2D
// endfunction
//
// you can find it configuration down below, change it to null like this:
//
// constant function SKBO_KBTrigger takes nothing returns trigger
// return null
// endfunction
//
// it is recommended that you also disable SKBO_Knockback function by
// setting it to false. You should now be good to go!! ^_^
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
//***************************************************************************
// Configuration Starts Here
//***************************************************************************
//---------------------------------------------------------------------------
// The AbilityID for Skyfall Boulders Spell, make sure it has the same
// value as in Object Editor (to check, press CTRL+D in Object Editor)
//---------------------------------------------------------------------------
constant function SKBO_AbilityID takes nothing returns integer
return 'A000'
endfunction
//---------------------------------------------------------------------------
// The AbilityID for Dummy to cast,
// make sure it has the same value as in Object Editor
// (to check, press CTRL+D in Object Editor)
// - First one is for stun purpose (based on firebolt)
// - Second one is for destroying tree purpose (harvest)
//---------------------------------------------------------------------------
constant function SKBO_StunAbilityID takes nothing returns integer
return 'A001'
endfunction
constant function SKBO_HarvestAbilityID takes nothing returns integer
return 'Ahrl'
endfunction
//---------------------------------------------------------------------------
// This is the Order ID of DummyAbility, this is required to cast the
// ability itself. Check out this list for a reference:
// https://github.com/nestharus/JASS/blob/master/jass/Systems/OrderIds/script.j
//---------------------------------------------------------------------------
constant function SKBO_DOrderID takes nothing returns integer
return 852231
endfunction
//---------------------------------------------------------------------------
// The DummyID for Skyfall Boulders Spell, make sure it has the same
// value as in Object Editor (to check, press CTRL+D in Object Editor)
// - Dummy1 = The boulder
// - Dummy2 = The Portal in the ground
// - Dummy3 = The Portal in the sky
// - Dummy4 = The feral spirit effect for spawn effect
//---------------------------------------------------------------------------
constant function SKBO_Dummy1ID takes nothing returns integer
return 'h000'
endfunction
constant function SKBO_Dummy2ID takes nothing returns integer
return 'h001'
endfunction
constant function SKBO_Dummy3ID takes nothing returns integer
return 'h002'
endfunction
constant function SKBO_Dummy4ID takes nothing returns integer
return 'h003'
endfunction
constant function SKBO_DummyCasterID takes nothing returns integer
return 'h004'
endfunction
//---------------------------------------------------------------------------
// This determines the owner for the dummy units
// You can set it to Neutral Passive to not mess up with game scoreboard
//---------------------------------------------------------------------------
constant function SKBO_DummyOwner takes nothing returns player
return Player(PLAYER_NEUTRAL_PASSIVE)
endfunction
//---------------------------------------------------------------------------
// This determines the size/scale of the dummy
// - Dummy1 = The boulder
// - Dummy2 = The Portal in the ground
// - Dummy3 = The Portal in the sky
// - Dummy4 = The feral spirit effect for spawn effect
//---------------------------------------------------------------------------
constant function SKBO_Dummy1Size takes nothing returns real
return 1.5
endfunction
constant function SKBO_Dummy2Size takes nothing returns real
return 1.0
endfunction
constant function SKBO_Dummy3Size takes nothing returns real
return 1.0
endfunction
constant function SKBO_Dummy4Size takes nothing returns real
return 1.0
endfunction
//---------------------------------------------------------------------------
// This determines the starting height of the dummy
// - Dummy1 = The boulder
// - Dummy2 = The Portal in the ground
// - Dummy3 = The Portal in the sky
// - Dummy4 = The feral spirit effect for spawn effect
//---------------------------------------------------------------------------
constant function SKBO_Dummy1Height takes nothing returns real
return 500.0
endfunction
constant function SKBO_Dummy2Height takes nothing returns real
return 0.0
endfunction
constant function SKBO_Dummy3Height takes nothing returns real
return 500.0
endfunction
constant function SKBO_Dummy4Height takes nothing returns real
return 500.0
endfunction
//---------------------------------------------------------------------------
// This determines the special effect model we will use in the spell
// - Appears when the boulder explodes
//---------------------------------------------------------------------------
constant function SKBO_EffectString takes nothing returns string
return "war3mapImported\\NewDirtEXNofire.mdx"
endfunction
//---------------------------------------------------------------------------
// How many boulders will be conjured and be used throughout the spell?
// Feel free to play around with the number
//---------------------------------------------------------------------------
constant function SKBO_BaseNumber takes nothing returns integer
return 1
endfunction
constant function SKBO_NumberPerLvl takes nothing returns integer
return 2
endfunction
//---------------------------------------------------------------------------
// How much damage should the ability deal?
// The calculation will be something like this:
// Dmg = BaseDmg + (DmgPerLvl * Lvl)
//---------------------------------------------------------------------------
constant function SKBO_BaseDmg takes nothing returns real
return 100.0
endfunction
constant function SKBO_DmgPerLvl takes nothing returns real
return 75.0
endfunction
//---------------------------------------------------------------------------
// This determines the Attack Type, Damage Type, and Weapon Type for the spell
// It can be impactful if you consider how each type interact with armor type
// You can ignore these if they do not concern you
//---------------------------------------------------------------------------
constant function SKBO_AT takes nothing returns attacktype
return ATTACK_TYPE_NORMAL
endfunction
constant function SKBO_DT takes nothing returns damagetype
return DAMAGE_TYPE_NORMAL
endfunction
constant function SKBO_WT takes nothing returns weapontype
return WEAPON_TYPE_WHOKNOWS
endfunction
//---------------------------------------------------------------------------
// How big of a radius will be affected by the damage?
// This is also known as Area of Effect
// The calculation will be something like this:
// Aoe = BaseAoe + (AoePerLvl * Lvl)
//---------------------------------------------------------------------------
constant function SKBO_BaseAoe takes nothing returns real
return 350.0
endfunction
constant function SKBO_AoePerLvl takes nothing returns real
return 0.0
endfunction
//---------------------------------------------------------------------------
// How fast should the boulder fall?
//---------------------------------------------------------------------------
constant function SKBO_BaseSpeed takes nothing returns real
return 30.0
endfunction
constant function SKBO_SpeedPerLvl takes nothing returns real
return 0.0
endfunction
//---------------------------------------------------------------------------
// This is the acceleration value for the falling boulders
//---------------------------------------------------------------------------
constant function SKBO_BaseAccel takes nothing returns real
return 1.5
endfunction
constant function SKBO_AccelPerLvl takes nothing returns real
return 0.0
endfunction
//---------------------------------------------------------------------------
// This allows you toggle the supported features
// - return true to enable
// - return false to disable
//---------------------------------------------------------------------------
constant function SKBO_TreeDestroy takes nothing returns boolean
return true
endfunction
constant function SKBO_Knockback takes nothing returns boolean
return true
endfunction
constant function SKBO_Stun takes nothing returns boolean
return true
endfunction
//---------------------------------------------------------------------------
// Here you can adjust the settings of your knockback
// You can ignore these if SKBO_Knockback is disabled
//---------------------------------------------------------------------------
constant function SKBO_KBDistance takes nothing returns real
return 300.0
endfunction
constant function SKBO_KBTime takes nothing returns real
return 0.70
endfunction
//---------------------------------------------------------------------------
// This is the trigger for Bribe's Knockback2D system
// In case you do not want to import KB2D system into your map
// You can just change this to return null
// Don't forget to disable SKBO_Knockback as well
//---------------------------------------------------------------------------
constant function SKBO_KBTrigger takes nothing returns trigger
return gg_trg_Knockback_2D
endfunction
//---------------------------------------------------------------------------
// The Timer Interval for Loop Function
// Don't change this value unless you know what you are doing
//---------------------------------------------------------------------------
constant function SKBO_Interval takes nothing returns real
return 0.0312500
endfunction
//---------------------------------------------------------------------------
// This is Target Filter, you can modify this to suit your preferences
//---------------------------------------------------------------------------
constant function SKBO_TargetFilter takes unit u, player p returns boolean
return not(IsUnitType(u, UNIT_TYPE_STRUCTURE)) and (IsUnitEnemy(u, p)) and not(IsUnitType(u, UNIT_TYPE_DEAD))
endfunction
//***************************************************************************
// End of Configuration
//***************************************************************************
//---------------------------------------------------------------------------
// RecycleNode Function
//---------------------------------------------------------------------------
function SKBO_RecycleNode takes integer Node returns nothing
set udg_SKBO_RecycledStack[udg_SKBO_RecycledSize] = Node
set udg_SKBO_RecycledSize = udg_SKBO_RecycledSize + 1
set udg_SKBO_NodeNext[udg_SKBO_NodePrev[Node]] = udg_SKBO_NodeNext[Node]
set udg_SKBO_NodePrev[udg_SKBO_NodeNext[Node]] = udg_SKBO_NodePrev[Node]
endfunction
//---------------------------------------------------------------------------
// CreateNode Function
//---------------------------------------------------------------------------
function SKBO_CreateNode takes nothing returns integer
local integer Node
if (udg_SKBO_RecycledSize == 0) then
set udg_SKBO_MaxIndex = udg_SKBO_MaxIndex + 1
set Node = udg_SKBO_MaxIndex
else
set udg_SKBO_RecycledSize = udg_SKBO_RecycledSize - 1
set Node = udg_SKBO_RecycledStack[udg_SKBO_RecycledSize]
endif
set udg_SKBO_NodeNext[Node] = 0
set udg_SKBO_NodeNext[udg_SKBO_NodePrev[0]] = Node
set udg_SKBO_NodePrev[Node] = udg_SKBO_NodePrev[0]
set udg_SKBO_NodePrev[0] = Node
return Node
endfunction
//---------------------------------------------------------------------------
// Destroy Tree Snippet
//---------------------------------------------------------------------------
function SKBO_IsDestTree takes destructable d returns boolean
return IssueTargetOrderById(udg_SKBO_DummyCaster,852018,d) and IssueImmediateOrderById(udg_SKBO_DummyCaster,851972)
endfunction
function SKBO_DestroyTree takes destructable d returns nothing
if SKBO_IsDestTree(d) and GetWidgetLife(d) > 0.405 then
call KillDestructable(d)
endif
endfunction
function SKBO_TreeFilter takes nothing returns boolean
call SKBO_DestroyTree(GetFilterDestructable())
return false
endfunction
//---------------------------------------------------------------------------
// Loop Function
//---------------------------------------------------------------------------
function SKBO_Loop takes nothing returns nothing
local integer Node = 0
local integer i = 0
local integer index = 0
local real angle
local real x
local real y
local unit u
local group g = CreateGroup()
local rect r
loop
set Node = udg_SKBO_NodeNext[Node]
exitwhen Node == null
// Stage 1 handles the fall
if (udg_SKBO_Stage[Node] == 1) then
if (udg_SKBO_CurrentHeight[Node] > 0) then
set udg_SKBO_CurrentHeight[Node] = udg_SKBO_CurrentHeight[Node] - udg_SKBO_Velocity[Node]
set udg_SKBO_Velocity[Node] = udg_SKBO_Velocity[Node] + udg_SKBO_Accel[Node]
call SetUnitFlyHeight(udg_SKBO_DummyUnit[Node], udg_SKBO_CurrentHeight[Node], 0)
else
if (udg_SKBO_Teleported[Node] == true) then
set udg_SKBO_Stage[Node] = 2
else
call KillUnit(udg_SKBO_DummyUnit2[Node])
call KillUnit(udg_SKBO_DummyUnit3[Node])
set udg_SKBO_CurrentHeight[Node] = SKBO_Dummy1Height()
call SetUnitFlyHeight(udg_SKBO_DummyUnit[Node], udg_SKBO_CurrentHeight[Node], 0)
set udg_SKBO_Teleported[Node] = true
// Move the boulders
call SetUnitX(udg_SKBO_DummyUnit[Node], udg_SKBO_DTargetX[Node])
call SetUnitY(udg_SKBO_DummyUnit[Node], udg_SKBO_DTargetY[Node])
endif
endif
// Stage 2 handles damage and recycle
elseif (udg_SKBO_Stage[Node] == 2) then
call KillUnit(udg_SKBO_DummyUnit[Node])
call DestroyEffect(AddSpecialEffect(SKBO_EffectString(), udg_SKBO_DTargetX[Node], udg_SKBO_DTargetY[Node]))
// Deal damage and stuff only if it's the instance of Parent Node
if (udg_SKBO_Parent[Node] == 0) then
call GroupEnumUnitsInRange(g, udg_SKBO_STargetX[Node], udg_SKBO_STargetY[Node], udg_SKBO_Aoe[Node], null)
loop
set u = FirstOfGroup(g)
exitwhen u == null
if (SKBO_TargetFilter(u, udg_SKBO_Player[Node])) then
if (SKBO_Stun()) then
call IssueTargetOrderById(udg_SKBO_DummyCaster, SKBO_DOrderID(), u)
endif
if ((GetWidgetLife(u) - udg_SKBO_Dmg[Node]) <= 0.405) then
call SetUnitExploded( u, true )
endif
call UnitDamageTarget(udg_SKBO_Caster[Node], u, udg_SKBO_Dmg[Node], false, false, SKBO_AT(), SKBO_DT(), SKBO_WT())
if (SKBO_Knockback()) then
set x = GetUnitX(u)
set y = GetUnitY(u)
set udg_Knockback2DAngle = bj_RADTODEG * Atan2(y - udg_SKBO_STargetY[Node], x - udg_SKBO_STargetX[Node])
set udg_Knockback2DDistance = SKBO_KBDistance()
set udg_Knockback2DTime = SKBO_KBTime()
set udg_Knockback2DUnit = u
call TriggerExecute( SKBO_KBTrigger() )
endif
endif
call GroupRemoveUnit(g, u)
endloop
// Check if user wants to destroy tree
if (SKBO_TreeDestroy()) then
set r = Rect(udg_SKBO_STargetX[Node] - udg_SKBO_Aoe[Node], udg_SKBO_STargetY[Node] - udg_SKBO_Aoe[Node], udg_SKBO_STargetX[Node] + udg_SKBO_Aoe[Node], udg_SKBO_STargetY[Node] + udg_SKBO_Aoe[Node])
call EnumDestructablesInRect(r, Condition(function SKBO_TreeFilter), null)
call RemoveRect(r)
endif
endif
// Recycle
call SKBO_RecycleNode(Node)
// Turn off when there's no running instance left
if (udg_SKBO_NodePrev[0] == 0) then
call PauseTimer(udg_SKBO_Timer)
endif
endif
endloop
call DestroyGroup(g)
set g = null
endfunction
//---------------------------------------------------------------------------
// CreateBoulder Function
//---------------------------------------------------------------------------
function SKBO_CreateBoulder takes integer parent, real x, real y, real angle returns nothing
local integer Node = SKBO_CreateNode()
local unit u
// Set up the necessary data for boulder dummy
set udg_SKBO_Parent[Node] = parent
set udg_SKBO_CurrentHeight[Node] = udg_SKBO_CurrentHeight[udg_SKBO_Parent[Node]]
set udg_SKBO_Stage[Node] = udg_SKBO_Stage[udg_SKBO_Parent[Node]]
set udg_SKBO_Teleported[Node] = udg_SKBO_Teleported[udg_SKBO_Parent[Node]]
set udg_SKBO_Velocity[Node] = udg_SKBO_Velocity[udg_SKBO_Parent[Node]]
set udg_SKBO_Accel[Node] = udg_SKBO_Accel[udg_SKBO_Parent[Node]]
set udg_SKBO_Aoe[Node] = udg_SKBO_Aoe[udg_SKBO_Parent[Node]]
set udg_SKBO_DTargetX[Node] = udg_SKBO_DTargetX[udg_SKBO_Parent[Node]]
set udg_SKBO_DTargetY[Node] = udg_SKBO_DTargetY[udg_SKBO_Parent[Node]]
// Create the boulder
set udg_SKBO_DummyUnit[Node] = CreateUnit(SKBO_DummyOwner(), SKBO_Dummy1ID(), x, y, angle)
call SetUnitScale(udg_SKBO_DummyUnit[Node], SKBO_Dummy1Size(), SKBO_Dummy1Size(), SKBO_Dummy1Size())
call SetUnitFlyHeight(udg_SKBO_DummyUnit[Node], SKBO_Dummy1Height(), 0)
// Create the spawn effect
set udg_SKBO_DummyUnit2[Node] = CreateUnit(SKBO_DummyOwner(), SKBO_Dummy2ID(), x, y, angle)
call SetUnitScale(udg_SKBO_DummyUnit2[Node], SKBO_Dummy2Size(), SKBO_Dummy2Size(), SKBO_Dummy2Size())
call SetUnitFlyHeight(udg_SKBO_DummyUnit2[Node], SKBO_Dummy2Height(), 0)
set u = CreateUnit(SKBO_DummyOwner(), SKBO_Dummy4ID(), x, y, angle)
call SetUnitScale(u, SKBO_Dummy4Size(), SKBO_Dummy4Size(), SKBO_Dummy4Size())
call SetUnitFlyHeight(u, SKBO_Dummy4Height(), 0)
call KillUnit(u)
set u = null
// Create the teleported effect
set udg_SKBO_DummyUnit3[Node] = CreateUnit(SKBO_DummyOwner(), SKBO_Dummy3ID(), udg_SKBO_DTargetX[Node], udg_SKBO_DTargetY[Node], angle)
call SetUnitScale(udg_SKBO_DummyUnit3[Node], SKBO_Dummy3Size(), SKBO_Dummy3Size(), SKBO_Dummy3Size())
call SetUnitFlyHeight(udg_SKBO_DummyUnit3[Node], SKBO_Dummy3Height(), 0)
endfunction
//---------------------------------------------------------------------------
// Main Function
//---------------------------------------------------------------------------
function SKBO_Main takes nothing returns boolean
// Declare locals
local integer Node = 0
local integer loopInt = 0
local integer iLevel
local integer index = 0
local real rLevel
local real x1
local real y1
local real x2
local real y2
local real x3
local real y3
local real angle
local unit u
if (GetSpellAbilityId() == SKBO_AbilityID()) then
// set up node
set Node = SKBO_CreateNode()
// Mark this instance as a parent
set udg_SKBO_Parent[Node] = 0
// Assign data to locals
set u = GetTriggerUnit()
set iLevel = GetUnitAbilityLevel(u, SKBO_AbilityID())
set rLevel = I2R(iLevel)
set x1 = GetUnitX(u)
set y1 = GetUnitY(u)
set x2 = GetSpellTargetX()
set y2 = GetSpellTargetY()
set angle = bj_RADTODEG * Atan2(y2-y1, x2-x1)
// Assign data to globals
set udg_SKBO_Caster[Node] = u
set udg_SKBO_Player[Node] = GetTriggerPlayer()
set udg_SKBO_Dmg[Node] = SKBO_BaseDmg() + (SKBO_DmgPerLvl() * rLevel)
set udg_SKBO_Aoe[Node] = SKBO_BaseAoe() + (SKBO_AoePerLvl() * rLevel)
set udg_SKBO_Velocity[Node] = SKBO_BaseSpeed() + (SKBO_SpeedPerLvl() * rLevel)
set udg_SKBO_Accel[Node] = SKBO_BaseAccel() + (SKBO_AccelPerLvl() * rLevel)
set udg_SKBO_Number[Node] = SKBO_BaseNumber() + (SKBO_NumberPerLvl() * iLevel)
set udg_SKBO_CurrentHeight[Node] = SKBO_Dummy1Height()
set udg_SKBO_Stage[Node] = 1
set udg_SKBO_Teleported[Node] = false
set udg_SKBO_STargetX[Node] = x2
set udg_SKBO_STargetY[Node] = y2
// Start timer if this is the only instance
if (udg_SKBO_NodePrev[Node] == 0) then
call TimerStart(udg_SKBO_Timer, SKBO_Interval(), true, function SKBO_Loop)
endif
if (udg_SKBO_Number[Node] > 1) then
loop
set loopInt = loopInt + 1
exitwhen loopInt > udg_SKBO_Number[Node]
set angle = I2R(loopInt) * (360.0 / udg_SKBO_Number[Node])
// Set up the location of boulder spawn
set x3 = x1 + udg_SKBO_Aoe[Node] / 2 * Cos(angle * bj_DEGTORAD)
set y3 = y1 + udg_SKBO_Aoe[Node] / 2 * Sin(angle * bj_DEGTORAD)
// Set up the location where the boulder will teleport
set udg_SKBO_DTargetX[Node] = x2 + udg_SKBO_Aoe[Node] / 2 * Cos(angle * bj_DEGTORAD)
set udg_SKBO_DTargetY[Node] = y2 + udg_SKBO_Aoe[Node] / 2 * Sin(angle * bj_DEGTORAD)
// Create the boulder
call SKBO_CreateBoulder(Node, x3, y3, angle)
endloop
else
// Set up the location of boulder spawn
set x3 = x1 + udg_SKBO_Aoe[Node] / 2 * Cos(angle * bj_DEGTORAD)
set y3 = y1 + udg_SKBO_Aoe[Node] / 2 * Sin(angle * bj_DEGTORAD)
// Set up the location where the boulder will teleport
set udg_SKBO_DTargetX[Node] = x2
set udg_SKBO_DTargetY[Node] = y2
// Create the boulder
call SKBO_CreateBoulder(Node, x3, y3, angle)
endif
set u = null
endif
return false
endfunction
//===========================================================================
function InitTrig_Skyfall_Boulders takes nothing returns nothing
local trigger SKBO_Trig = CreateTrigger()
local integer index = 0
local real x = 0
local real y = 0
// Register event
loop
call TriggerRegisterPlayerUnitEvent(SKBO_Trig, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
set index = index + 1
exitwhen index == bj_MAX_PLAYER_SLOTS
endloop
// Register Main Function
call TriggerAddCondition(SKBO_Trig, Condition(function SKBO_Main))
// Create Dummy Caster
set udg_SKBO_DummyCaster = CreateUnit(SKBO_DummyOwner(), SKBO_DummyCasterID(), x, y, 0)
call UnitAddAbility(udg_SKBO_DummyCaster, SKBO_StunAbilityID())
call UnitAddAbility(udg_SKBO_DummyCaster, SKBO_HarvestAbilityID())
endfunction