Slide System v1.00
The goal here was to make an all encompassing, end all be all Slide/Knockback System. I think I have created that, minus any glaring slights on my behalf.
The main issue I had with the extended knockback system is that you can't have multiple slides on a single unit - I alleviate this issue by calculating the vector components of the current slide and the updated slide, which allows me to implement concurrent slides all into one instance. Also, a few of the scripting techniques in the previous are a little archaic (ex. no static ifs), that along with its heavy system requirements makes for a less then desirable system.
The slide struct should be treated as a unique object, and used as such.
Wrappers for the structs methods are also included for GUI users implementation.
Test map includes several examples, from simple through advanced.
I tried to incorporate interfaces, but I am not entirely sure how they really work. Regardless, I think my method ends up getting the job done.
The syntax may need to be tweaked a bit, but I think it fits pretty good.
Critiques and other thoughts welcome. I humbly submit for consideration.
Requirements:
- UnitAlive native
Implementation:
Read Me Part1:
Copy the Slide System trigger to your map, configure the options, and enjoy!
Requires, optionally, TimerUtils, GroupUtils, DestructableLib, and IsTerrainWalkable. The system will function fine without them, but it will work better and faster if they are present.
Also requires the UnitAlive native.
When creating slides, the angle to slide should be in degrees, not radians. Velocity and deceleration are in WC3 units, aka distance/second.
Typical GUI use:
//==Wrapper Functions==\\
// Create a new instance for a unit, deceleration=0 to use the DECEL global
function UnitStartSlide takes unit slider, real angle, real velocity, real deceleration returns slide
// Retrieve the units current slide information
function UnitGetSlide takes unit slider returns slide
// Is the unit currently sliding?
function IsUnitSliding takes unit slider returns boolean
// Stop the unit from sliding immediately
function UnitStopSlide takes unit slider returns boolean
// Incase you need to set a custom slide effect mid slide
// Use "" to restore automatic sfx updates
function UnitSetSlideEffect takes unit slider, string sfx returns boolean
// Kinematics
// Slide a unit for a specific duration, given the initial velocity
function UnitSlideTimed takes unit slider, real angle, real velocity, real time returns slide
// Slide a unit over a specific distance, given the initial velocity
function UnitSlideDistance takes unit slider, real angle, real velocity, real distance returns slide
// Collision utilities
// Remove a unit from the sliders collision group instantly
function RemoveTargetFromSlide takes slide d, unit target returns boolean
// Remove a unit from the sliders collision group after REHITTIME duration
function RemoveTargetFromSlideTimed takes slide d, unit target returns boolean
Read Me Part2:
Typical JASS use:
The structs name is slide, to use it, declare a local of the type slide.
// Create a new instance for a unit, deceleration=0 to use the DECEL global
static method create takes unit slider, real angle, real velocity, real deceleration returns slide
// Retrieve the units current slide information
static method unitgetslide takes unit slider returns slide
// Is the unit currently sliding?
static method isunitsliding takes unit slider returns boolean
// Stop the unit from sliding immediately
static method unitstopslide takes unit slider returns boolean
// Incase you need to set a custom slide effect mid slide
// Use "" to restore automatic sfx updates
static method unitsetslideeffect takes unit slider, string sfx returns boolean
// Kinematics
// Slide a unit for a specific duration, given the initial velocity
static method unitslidetimed takes unit slider, real angle, real velocity, real time returns slide
// Slide a unit over a specific distance, given the initial velocity
static method unitslidedistance takes unit slider, real angle, real velocity, real distance returns slide
// Collision utilities
// Remove a unit from sliders collision group instantly
static method removetargetfromslide takes slide d, unit target returns boolean
// Remove a unit from sliders collision group after REHITTIME duration
static method removetargetfromslidetimed takes slide d, unit target returns boolean
Read Me Part3
Advanced JASS use:
The struct has the following members, which can be accessed as desired:
private effect sfx
private integer marker
private real cos
private real decel
private real sin
public boolean constvel
public group g
public real angle
public real maxdist
public real maxtime
public real velocity
readonly boolean customsfx
readonly boolean fly
readonly boolean land
readonly boolean trees
readonly real totaldist
readonly real totaltime
readonly unit slider
Setting constvel to true creates a non-acceleration slide - this can be useful for dash type spells. maxtime and maxdist can be used to create a maximum time or maximum distance slide for a unit, respectively.
When in constant velocity mode, units are not collided with, and new slide instances on that unit cannot be created. See Shockwave for a demo.
Struct interfaces have been developed for the following uses:
method onPeriodic takes nothing returns nothing defaults nothing
method onEnd takes nothing returns nothing defaults nothing
method onHit takes nothing returns nothing defaults nothing
onPeriodic fires every TIMEOUT interval, onEnd fires when the target finishes sliding, and onHit fires when a collision takes place. See Bash for a demo.
Copy the Slide System trigger to your map, configure the options, and enjoy!
Requires, optionally, TimerUtils, GroupUtils, DestructableLib, and IsTerrainWalkable. The system will function fine without them, but it will work better and faster if they are present.
Also requires the UnitAlive native.
When creating slides, the angle to slide should be in degrees, not radians. Velocity and deceleration are in WC3 units, aka distance/second.
Typical GUI use:
//==Wrapper Functions==\\
// Create a new instance for a unit, deceleration=0 to use the DECEL global
function UnitStartSlide takes unit slider, real angle, real velocity, real deceleration returns slide
// Retrieve the units current slide information
function UnitGetSlide takes unit slider returns slide
// Is the unit currently sliding?
function IsUnitSliding takes unit slider returns boolean
// Stop the unit from sliding immediately
function UnitStopSlide takes unit slider returns boolean
// Incase you need to set a custom slide effect mid slide
// Use "" to restore automatic sfx updates
function UnitSetSlideEffect takes unit slider, string sfx returns boolean
// Kinematics
// Slide a unit for a specific duration, given the initial velocity
function UnitSlideTimed takes unit slider, real angle, real velocity, real time returns slide
// Slide a unit over a specific distance, given the initial velocity
function UnitSlideDistance takes unit slider, real angle, real velocity, real distance returns slide
// Collision utilities
// Remove a unit from the sliders collision group instantly
function RemoveTargetFromSlide takes slide d, unit target returns boolean
// Remove a unit from the sliders collision group after REHITTIME duration
function RemoveTargetFromSlideTimed takes slide d, unit target returns boolean
Read Me Part2:
Typical JASS use:
The structs name is slide, to use it, declare a local of the type slide.
// Create a new instance for a unit, deceleration=0 to use the DECEL global
static method create takes unit slider, real angle, real velocity, real deceleration returns slide
// Retrieve the units current slide information
static method unitgetslide takes unit slider returns slide
// Is the unit currently sliding?
static method isunitsliding takes unit slider returns boolean
// Stop the unit from sliding immediately
static method unitstopslide takes unit slider returns boolean
// Incase you need to set a custom slide effect mid slide
// Use "" to restore automatic sfx updates
static method unitsetslideeffect takes unit slider, string sfx returns boolean
// Kinematics
// Slide a unit for a specific duration, given the initial velocity
static method unitslidetimed takes unit slider, real angle, real velocity, real time returns slide
// Slide a unit over a specific distance, given the initial velocity
static method unitslidedistance takes unit slider, real angle, real velocity, real distance returns slide
// Collision utilities
// Remove a unit from sliders collision group instantly
static method removetargetfromslide takes slide d, unit target returns boolean
// Remove a unit from sliders collision group after REHITTIME duration
static method removetargetfromslidetimed takes slide d, unit target returns boolean
Read Me Part3
Advanced JASS use:
The struct has the following members, which can be accessed as desired:
private effect sfx
private integer marker
private real cos
private real decel
private real sin
public boolean constvel
public group g
public real angle
public real maxdist
public real maxtime
public real velocity
readonly boolean customsfx
readonly boolean fly
readonly boolean land
readonly boolean trees
readonly real totaldist
readonly real totaltime
readonly unit slider
Setting constvel to true creates a non-acceleration slide - this can be useful for dash type spells. maxtime and maxdist can be used to create a maximum time or maximum distance slide for a unit, respectively.
When in constant velocity mode, units are not collided with, and new slide instances on that unit cannot be created. See Shockwave for a demo.
Struct interfaces have been developed for the following uses:
method onPeriodic takes nothing returns nothing defaults nothing
method onEnd takes nothing returns nothing defaults nothing
method onHit takes nothing returns nothing defaults nothing
onPeriodic fires every TIMEOUT interval, onEnd fires when the target finishes sliding, and onHit fires when a collision takes place. See Bash for a demo.
Script:
JASS:
library SlideSystem needs optional GroupUtils, optional TimerUtils, optional DestructableLib, optional IsTerrainWalkable
globals
//==Configurables==\\
private constant boolean ALLOWMOVE = false // Allow movement while units slide
private constant boolean COLLIDE = true // Unit/Structure collision detection
private constant boolean CLIFF = true // Cliff detection, stops unit movement
private constant boolean PRELOAD = true // Preload slide effects
private constant boolean REHIT = true // Can collide with the same target more then once during a single slide event
private constant boolean SINCELAST = false // When tracking total slide time and distance, will reset value for each newly created slide
private constant boolean TREES = true // Destroy trees in sliding path
private constant integer OFFSET = 0x100000 // Id of the first handle in your map, if unsure don't change
public constant real BREAK = 10. // Velocity below which units stop sliding
public constant real CLIFFBREAK = 75. // Break point for a terrian height change to be considered a cliff, if not using IsTerrainWalkable library
public constant real DECEL = .95 // In the abscence of a linear deceleration set point, DECEL/TIMEOUT
public constant real FACTORA = .66 // Percentage of slide velocity transfered to colliding units
public constant real FACTORB = .66 // Percentage of slide velocity retained after a collision
public constant real FLYBREAK = 150. // Units above this fly height will not be struck by collisions or destroy trees
public constant real RADIUS = 180. // Collision detection radius
public constant real REHITTIME = .4 // Elapsed time required before a unit can be collided with again
public constant real TIMEOUT = .05 // Periodic timer interval
private constant string AIR = "sfx\\AirSlide.mdx" // Flying units slide effect
private constant string ATTACH = "origin" // Slide effects attachment point
private constant string HIT = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl" // Collision effect
private constant string LAND = "sfx\\LandSlide.mdx" // Land slide effect
private constant string SEA = "sfx\\SeaSlide.mdx" // Water slide effect
endglobals
// Establish custom unit collision conditions
private function CollisionFilter takes unit slider, unit target returns boolean
return IsUnitEnemy(target,GetOwningPlayer(slider))
endfunction
//==NO TOUCHING PAST THIS POINT==\\
globals
private boolexpr TREEBOOL
private boolexpr UNITBOOL
private group COLLISION = CreateGroup()
private hashtable HT // Only needed if no TimerUtils
private integer COUNT = 0
private slide array DATA
private slide array DATA2 // Remove O(n) searches
private slide TEMPDATA
private location LOC = Location(0.,0.)
public constant real FRAMERATE = 1./TIMEOUT
private constant real HALFRADIUS = RADIUS/2.
public constant real REALBREAK = BREAK/FRAMERATE
private rect RECT
private unit T
private unit TREECHECK
// Incase either of these need to be accessed
public group GROUP = CreateGroup()
public timer TIMER = CreateTimer()
endglobals
private struct rehit
timer t = null
unit target = null
unit slider = null
group g = null
method destroy takes nothing returns nothing
// Clean up
static if LIBRARY_TimerUtils then
call ReleaseTimer(.t)
else
call FlushChildHashtable(HT,GetHandleId(.t))
call PauseTimer(.t)
call DestroyTimer(.t)
endif
call .deallocate()
endmethod
static method timeout takes nothing returns nothing
local rehit this=GetTimerData(GetExpiredTimer())
// Unit is still sliding
if IsUnitInGroup(.slider,GROUP) then
call GroupRemoveUnit(.g,.target)
endif
call .destroy()
endmethod
static method create takes unit target, unit slider, group g returns rehit
local rehit this=rehit.allocate()
static if LIBRARY_TimerUtils then
set .t=NewTimer()
call SetTimerData(.t,this)
else
set .t=CreateTimer()
call SaveInteger(HT,GetHandleId(.t),0,this)
endif
set .target=target
set .slider=slider
set .g=g
// Remove target from sliders hit group after a duration
call TimerStart(.t,REHITTIME,false,function rehit.timeout)
return this
endmethod
endstruct
private interface face
method onPeriodic takes nothing returns nothing defaults nothing
method onEnd takes nothing returns nothing defaults nothing
method onHit takes nothing returns nothing defaults nothing
endinterface
struct slide extends face
private effect sfx = null
private integer marker = 0 // mark spot in movement loop stack
private real cos = 0.
private real decel = 0.
private real sin = 0.
public boolean constvel = false
public group g = null
public real angle = 0.
public real maxdist = 0. // Only used during constant velocity mode
public real maxtime = 0. // Only used during constant velocity mode
public real velocity = 0.
readonly boolean customsfx = false
readonly boolean fly = false
readonly boolean land = true
readonly boolean trees = true
readonly real totaldist = 0.
readonly real totaltime = 0.
readonly unit slider = null
method destroy takes nothing returns nothing
// Clean up
set .customsfx=false
set .fly=false
set .land=true
set .trees=true
set .constvel=false
set .totaldist=0.
set .totaltime=0.
set .maxdist=0.
set .maxtime=0.
set .decel=0.
if .onEnd.exists then
call .onEnd.execute()
endif
call DestroyEffect(.sfx)
static if LIBRARY_GroupUtils then
call ReleaseGroup(.g)
else
call DestroyGroup(.g)
endif
call GroupRemoveUnit(GROUP,.slider)
set DATA[.marker]=DATA[COUNT]
set DATA[.marker].marker=.marker
set COUNT=COUNT-1
call .deallocate()
endmethod
private static method unitfilter takes nothing returns boolean
local slide this=TEMPDATA
local slide d
local real xT
local real yT
local real x
local real y
local timer t
set T=GetFilterUnit()
// Make sure target is alive and not invulnerable, is not the slider and has not already been hit, and isn't flying too high, along with
// conditions from the custom user edited filter
if CollisionFilter(.slider,T) and GetUnitFlyHeight(T)<=FLYBREAK and GetUnitAbilityLevel(T,039;Avul039;)==0 and UnitAlive(T) and not IsUnitInGroup(T,.g) and T!=.slider then
if .onHit.exists then
call .onHit.execute()
endif
set xT=GetUnitX(T)
set yT=GetUnitY(T)
set x=GetUnitX(.slider)
set y=GetUnitY(.slider)
// Only begin a slide on the target if its not a structure
if IsUnitType(T,UNIT_TYPE_STRUCTURE)==false then
// Start collision slide
set d=slide.create(T,bj_RADTODEG*Atan2(yT-y,xT-x),(.velocity*FRAMERATE)*FACTORA,.decel*FRAMERATE)
call GroupAddUnit(d.g,.slider)
call DestroyEffect(AddSpecialEffectTarget(HIT,T,ATTACH))
// If allowed, start re-hit effects
static if REHIT then
call rehit.create(T,.slider,.g)
endif
endif
// Fancy maths for deflection, see my GetDeflectionAngle script
set .angle=.angle+180.+(2.*((bj_RADTODEG*Atan2(yT-y,xT-x))-.angle))
set .cos=Cos(.angle*bj_DEGTORAD)
set .sin=Sin(.angle*bj_DEGTORAD)
set .velocity=.velocity*FACTORB
call DestroyEffect(AddSpecialEffectTarget(HIT,.slider,ATTACH))
call GroupAddUnit(.g,T)
endif
return false
endmethod
private static method killtrees takes nothing returns boolean
// Make sure the destructable is actually a tree
static if not LIBRARY_DestructableLib then
if IssueTargetOrder(TREECHECK,"harvest",GetFilterDestructable()) then
call KillDestructable(GetFilterDestructable())
endif
else
if IsDestructableTree(GetFilterDestructable()) then
call KillDestructable(GetFilterDestructable())
endif
endif
return false
endmethod
private static method movement takes nothing returns nothing
local slide this
local integer i=1
local real x
local real xc
local real y
local real yc
local real z
loop
exitwhen i>COUNT
set this=DATA<i>
// Slide is over
if .velocity<=REALBREAK or not UnitAlive(.slider) or (.constvel and ((.totaltime>=.maxtime and .maxtime!=0.) or (.totaldist>=maxdist and .maxdist!=0.))) then
// Clean up
call .destroy()
set i=i-1
// Slide is not over
else
// Caculate positioning
set x=GetUnitX(.slider)+.velocity*.cos
set y=GetUnitY(.slider)+.velocity*.sin
if .onPeriodic.exists then
call .onPeriodic.execute()
endif
// Destroy trees
static if TREES then
if .trees then
call MoveRectTo(RECT,x,y)
static if not LIBRARY_DestructableLib then
call PauseUnit(TREECHECK,false)
endif
call EnumDestructablesInRect(RECT,TREEBOOL,null)
static if not LIBRARY_DestructableLib then
call PauseUnit(TREECHECK,true)
endif
endif
endif
// Cliff detection
static if CLIFF then
// Check out in front of the slider a bit in the direction it's traveling
set xc=x+HALFRADIUS*.cos
set yc=y+HALFRADIUS*.sin
static if LIBRARY_IsTerrainWalkable then
// Cliff found
if not IsTerrainWalkable(xc,yc) then
call .destroy()
endif
else
call MoveLocation(LOC,x,y)
set z=GetLocationZ(LOC)
call MoveLocation(LOC,xc,yc)
// Cliff found
if GetLocationZ(LOC)>z+CLIFFBREAK or GetLocationZ(LOC)<z-CLIFFBREAK then
call .destroy()
endif
endif
endif
// Update position and slide speed
static if ALLOWMOVE then
call SetUnitX(.slider,x)
call SetUnitY(.slider,y)
else
call SetUnitPosition(.slider,x,y)
endif
// Update total time and distance slid
set .totaldist=.totaldist+.velocity
set .totaltime=.totaltime+TIMEOUT
// If a deceleration has been set, use it, so long as we aren't in a constant velocity mode
if not .constvel then
if .decel!=0. then
set .velocity=.velocity-.decel
else
set .velocity=.velocity*DECEL
endif
endif
// Update slide effects
if not .fly and not .customsfx then
// Ground
if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) or not IsTerrainPathable(x,y,PATHING_TYPE_ANY) then
if not .land then
set .land=true
call DestroyEffect(.sfx)
set .sfx=AddSpecialEffectTarget(LAND,.slider,ATTACH)
endif
// Water
elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
if .land then
set .land=false
call DestroyEffect(.sfx)
set .sfx=AddSpecialEffectTarget(SEA,.slider,ATTACH)
endif
endif
endif
// Collision detection
static if COLLIDE then
if not .constvel then
set TEMPDATA=this
call GroupEnumUnitsInRange(COLLISION,x,y,RADIUS,UNITBOOL)
endif
endif
endif
set i=i+1
endloop
if COUNT==0 then
call PauseTimer(TIMER)
endif
endmethod
//==User Methods==\\
// Create a new instance for a unit, deceleration=0 to use the DECEL global
static method create takes unit slider, real angle, real velocity, real deceleration returns slide
local slide this
local integer id=GetHandleId(slider)-OFFSET
local real x
local real y
// No need to continue...
if slider==null or not UnitAlive(slider) then
return 0
endif
// Unit wasn't previously sliding
if not IsUnitInGroup(slider,GROUP) then
// Initial slide struct setup
set this=slide.allocate()
set .slider=slider
set .angle=angle
set .velocity=velocity/FRAMERATE
set .cos=Cos(.angle*bj_DEGTORAD)
set .sin=Sin(.angle*bj_DEGTORAD)
// Don't want to speed up do we?
if deceleration!=0 then
set .decel=RAbsBJ(deceleration/FRAMERATE)
endif
static if LIBRARY_GroupUtils then
set .g=NewGroup()
else
set .g=CreateGroup()
endif
set x=GetUnitX(.slider)
set y=GetUnitY(.slider)
call GroupAddUnit(GROUP,slider)
// Unit is a flyer
if IsUnitType(slider,UNIT_TYPE_FLYING)==true then
set .fly=true
set .sfx=AddSpecialEffectTarget(AIR,.slider,ATTACH)
// Too high??
if GetUnitFlyHeight(slider)>FLYBREAK then
set .trees=false
endif
else
// Ground Stairs don't have any pathing...
if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) or not IsTerrainPathable(x,y,PATHING_TYPE_ANY) then
set .sfx=AddSpecialEffectTarget(LAND,.slider,ATTACH)
// Water
elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
set .sfx=AddSpecialEffectTarget(SEA,.slider,ATTACH)
set .land=false
endif
endif
// Store struct data
set DATA2[id]=this
set COUNT=COUNT+1
set DATA[COUNT]=this
set .marker=COUNT
// First sliding unit
if COUNT==1 then
call TimerStart(TIMER,TIMEOUT,true,function slide.movement)
endif
// Unit was already sliding
else
// To avoid bugs and general preposterousness, when moving in constant velocity mode, we can't update slide attributes
// I figure most likely the user wouldn't want the targets trajectory being changed anyhow
if .constvel then
return 0
endif
// Calculate vector components of slide velocity
set this=DATA2[id]
set velocity=velocity/FRAMERATE
set x=.velocity*.cos+(velocity)*Cos(angle*bj_DEGTORAD)
set y=.velocity*.sin+(velocity)*Sin(angle*bj_DEGTORAD)
// Update slide direction and velocity
set .velocity=SquareRoot(x*x+y*y)
set .angle=Atan2(y,x)
set .cos=Cos(.angle)
set .sin=Sin(.angle)
set .angle=.angle*bj_RADTODEG
if deceleration!=0 then
set .decel=RAbsBJ(deceleration/FRAMERATE)
endif
// Reset total slide time and distance
static if SINCELAST then
set .slidedist=0.
set .totaltime=0.
endif
endif
return this
endmethod
// Retrieve the units current slide information
static method unitgetslide takes unit slider returns slide
if IsUnitInGroup(slider,GROUP) then
return DATA2[GetHandleId(slider)-OFFSET]
else
debug call BJDebugMsg(SCOPE_PREFIX+" UnitGetSlide Error: Unit is not sliding.")
return 0
endif
endmethod
// Is the unit currently sliding?
static method isunitsliding takes unit slider returns boolean
return IsUnitInGroup(slider,GROUP)
endmethod
// Stop the unit from sliding immediately
static method unitstopslide takes unit slider returns boolean
if IsUnitInGroup(slider,GROUP) then
call DATA2[GetHandleId(slider)-OFFSET].destroy()
return true
else
debug call BJDebugMsg(SCOPE_PREFIX+" UnitStopSlide Error: Unit is not sliding.")
return false
endif
endmethod
// Incase you need to set a custom slide effect mid slide
// Use "" to restore automatic sfx updates
static method unitsetslideeffect takes unit slider, string sfx returns boolean
local slide this
if IsUnitInGroup(slider,GROUP) then
set this=DATA2[GetHandleId(slider)-OFFSET]
call DestroyEffect(.sfx)
if sfx!="" then
set .customsfx=true
set .sfx=AddSpecialEffectTarget(sfx,slider,ATTACH)
else
set .customsfx=false
if .fly then
set .sfx=AddSpecialEffectTarget(AIR,slider,ATTACH)
endif
endif
return true
else
debug call BJDebugMsg(SCOPE_PREFIX+" UnitSetSlideEffect Error: Unit is not sliding.")
return false
endif
endmethod
// Kinematics
// Slide a unit for a specific duration, given the initial velocity
static method unitslidetimed takes unit slider, real angle, real velocity, real time returns slide
// a=Vi-Vo/t
if slider!=null and time>0. then
return slide.create(slider,angle,velocity,(velocity-BREAK)/(time*FRAMERATE))
else
debug call BJDebugMsg(SCOPE_PREFIX+" UnitSlideTimed Error: Incorrect argument inputs.")
return 0
endif
endmethod
// Slide a unit over a specific distance, given the initial velocity
static method unitslidedistance takes unit slider, real angle, real velocity, real distance returns slide
// a=(Vf^2-Vi^2)/(2*d)
if slider!=null and distance>0. then
return slide.create(slider,angle,velocity,(REALBREAK*REALBREAK-velocity*velocity*TIMEOUT)/(2.*distance))
else
debug call BJDebugMsg(SCOPE_PREFIX+" UnitSlideDistance Error: Incorrect argument inputs.")
return 0
endif
endmethod
// Remove a unit from sliders collision group instantly
static method removetargetfromslide takes slide d, unit target returns boolean
if IsUnitInGroup(target,d.g) and d.g!=null and d!=null and target!=null and UnitAlive(target) then
call GroupRemoveUnit(d.g,target)
return true
else
return false
endif
endmethod
// Remove a unit from sliders collision group after REHITTIME duration
static method removetargetfromslidetimed takes slide d, unit target returns boolean
if d.g!=null and d!=null and target!=null and UnitAlive(target) then
if not IsUnitInGroup(target,d.g) then
call GroupAddUnit(d.g,target)
endif
call rehit.create(target,d.slider,d.g)
return true
else
return false
endif
endmethod
//==Initialize System==\\
private static method onInit takes nothing returns nothing
set UNITBOOL=Condition(function slide.unitfilter)
// Destroy trees in path of sliding units setup
static if TREES then
set RECT=Rect(-RADIUS,-RADIUS,RADIUS,RADIUS)
set TREEBOOL=Condition(function slide.killtrees)
// Don't have DestructableUtils
static if not LIBRARY_DestructableLib then
set TREECHECK=CreateUnit(Player(15),039;hfoo039;, 0.0, 0.0, 0.0)
call PauseUnit(TREECHECK,true)
call ShowUnit(TREECHECK,false)
call UnitAddAbility(TREECHECK,039;Ahrl039;)
call UnitAddAbility(TREECHECK,039;Aloc039;)
endif
endif
// If you don't have TimerUtils
static if not LIBRARY_TimerUtils then
set HT=InitHashtable()
endif
// Preload slide effects
static if PRELOAD then
call Preload(AIR)
call Preload(HIT)
call Preload(LAND)
call Preload(SEA)
endif
endmethod
endstruct
//==Wrapper Functions==\\
// Create a new instance for a unit, deceleration=0 to use the DECEL global
function UnitStartSlide takes unit slider, real angle, real velocity, real deceleration returns slide
debug if slider==null or not UnitAlive(slider) or IsUnitType(slider,UNIT_TYPE_DEAD)==true then
debug call BJDebugMsg(SCOPE_PREFIX+" UnitStartSlide Error: Invalid argument inputs.")
debug return 0
debug endif
return slide.create(slider,angle,velocity,deceleration)
endfunction
// Retrieve the units current slide information
function UnitGetSlide takes unit slider returns slide
return slide.unitgetslide(slider)
endfunction
// Is the unit currently sliding?
function IsUnitSliding takes unit slider returns boolean
return slide.isunitsliding(slider)
endfunction
// Stop the unit from sliding immediately
function UnitStopSlide takes unit slider returns boolean
return slide.unitstopslide(slider)
endfunction
// Incase you need to set a custom slide effect mid slide
// Use "" to restore automatic sfx updates
function UnitSetSlideEffect takes unit slider, string sfx returns boolean
return slide.unitsetslideeffect(slider,sfx)
endfunction
// Kinematics
// Slide a unit for a specific duration, given the initial velocity
function UnitSlideTimed takes unit slider, real angle, real velocity, real time returns slide
return slide.unitslidetimed(slider,angle,velocity,time)
endfunction
// Slide a unit over a specific distance, given the initial velocity
function UnitSlideDistance takes unit slider, real angle, real velocity, real distance returns slide
return slide.unitslidedistance(slider,angle,velocity,distance)
endfunction
// Remove a unit from sliders collision group instantly
function RemoveTargetFromSlide takes slide d, unit target returns boolean
return slide.removetargetfromslide(d,target)
endfunction
// Remove a unit from sliders collision group after REHITTIME duration
function RemoveTargetFromSlideTimed takes slide d, unit target returns boolean
return slide.removetargetfromslidetimed(d,target)
endfunction
endlibrary</i>
Change Log:
v1.00 - Initial Release