Knockback system

Viikuna

No Marlo no game.
Reaction score
265
One timer and struct array because its faster + it leaves you more instances of TimerUtils to be used where it is really needed.

I didnt see any reason why effect dont work. Add some debug msges to find the problem.

edit. That just how to calculate angle and sin and cos. Are you still looking answer for that? I think I missed some posts..

Ok, A is some point. Ax and Ay are its x and y coordinates. A is also the point where your attacking unit is standing. The other point, B, is where your 'soon to be knockbacked' unit is standing. Bx and By are his coordinates. Now when unit standing in point A, attacks and knocks unit standing in point B, you calculate the direction where that knocked unit must slide. dx and dy are distance in x coordinates and distance in y coordinates. You can use Atan2 to get angle, and SquareRoot(dx*dx+dy*dy) to get distance between A and B.

its just some math. ( Damn that Bolded text looks ugly :/ )
 

wraithseeker

Tired.
Reaction score
122
Just posting so you won't get flamed for double posting , I edited my above code about the angles.

Did a DebugMsg on the Dust rock effect , it never runs at all.
 

Kenny

Back for now.
Reaction score
202
JASS:
library Knockback initializer Init requires BoundSentinel, TimerUtils, DestructableLib, IsTerrainWalkable

globals
    private constant real TIME = 0.03
    private constant string GROUND = "MDX\\Dust.mdx"
    private constant string WATER = "MDX\\SlideWater.mdx"
    private constant string COLLISION = "MDX\\DustAndRocks.mdx"
    private constant string ATTACHPOINT = "origin"
    private constant real RADIUS = 180.00
    private rect TreeRect = null
    private boolexpr TreeCheck = null
endglobals

private function CheckTrees takes nothing returns boolean
    if IsDestructableTree(GetFilterDestructable()) then
        return true
    endif
    return false
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private struct Knock
    unit source
    unit target
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    timer Timer
    effect effects
    boolean Terrain
    integer EffectMode
    boolean Trees
    
    public method TerrainCheck takes Knock d returns integer
        local real x = GetUnitX(d.target)
        local real y = GetUnitY(d.target)

        if IsTerrainWalkable(x + 50.00 * d.cos,y + 50.00 * d.sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif            

        return 0
    endmethod

    static method create takes unit source, unit target, real angle, real speed, real decrement, boolean KillTree returns Knock
        local Knock d = Knock.allocate()
        local real x
        local real y
        
        set d.source = source
        set d.target = target
        set d.Trees = KillTree
        set x = GetUnitX(d.target)
        set y = GetUnitY(d.target)
        set d.speed = speed * TIME
        set d.decrement = decrement * TIME
        set d.sin = Sin(angle)
        set d.cos = Cos(angle)
        set d.Timer = NewTimer()
        set d.EffectMode = d.TerrainCheck(d)
        
        if d.EffectMode == 1 then
            set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
        elseif d.EffectMode == 2 then
            set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
        elseif d.EffectMode == 3 then
            set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
        endif

        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call DestroyEffect(.effects)
        call ReleaseTimer(.Timer)
    endmethod

endstruct

private function Update takes nothing returns nothing
    local Knock d = Knock(GetTimerData(GetExpiredTimer()))
    local real sx = GetUnitX(d.target)
    local real sy = GetUnitY(d.target)
    local real x = sx + d.speed * d.cos
    local real y = sy + d.speed * d.sin
    local integer mode = d.EffectMode
    
    if d.speed <= 0.00 then
        call d.destroy()
    endif
    
    if d.Trees == true then
        call SetRect(TreeRect,sx-RADIUS,sy-RADIUS,sx+RADIUS,sy+RADIUS)
        call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
    endif
        
    call SetUnitPosition(d.target,x,y)
    set d.EffectMode = d.TerrainCheck(d)
    
    if d.EffectMode == 1 and (mode == 2 or mode == 3) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    elseif d.EffectMode == 2 and (mode == 1 or mode == 3) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    elseif d.EffectMode == 3 and (mode == 1 or mode == 2) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
    
    set d.speed = d.speed - d.decrement
endfunction

function KnockbackTarget takes unit source, unit target, real angle, real speed, real decrement, boolean KillTree returns boolean
    local Knock d = 0
    
    if target == null or source == null or speed == null or decrement == null then
        call BJDebugMsg("Invalid Values!")
        return false
    endif
    
    set d = Knock.create(source,target,angle,speed,decrement,KillTree)
    
    call SetTimerData(d.Timer,d)
    call TimerStart(d.Timer,TIME,true,function Update)
    
    return true
endfunction

private function Init takes nothing returns nothing
    set TreeRect = Rect(0,0,1,1)
    set TreeCheck = Filter(function CheckTrees)
endfunction

endlibrary


The rocks show now.
 

Viikuna

No Marlo no game.
Reaction score
265
No need for method TerrainCheck to take Knock d, just use this.member or just .member
 

wraithseeker

Tired.
Reaction score
122
@KENNY!
Mind if you highlight or make the line stand out which you added? Because I added a extra parathesis.

Ok, A is some point. Ax and Ay are its x and y coordinates. A is also the point where your attacking unit is standing. The other point, B, is where your 'soon to be knockbacked' unit is standing. Bx and By are his coordinates. Now when unit standing in point A, attacks and knocks unit standing in point B, you calculate the direction where that knocked unit must slide. dx and dy are distance in x coordinates and distance in y coordinates. You can use Atan2 to get angle, and SquareRoot(dx*dx+dy*dy) to get distance between A and B.

Is A a location or a Real? How can A be at 2 points? Same for B. What is the difference between BX BY and DX DY.

Vikkuna I wasn't talking about knocking back unit , I was talking about bouncing back units , or am I wrong that the thing that you are posting is related to bouncing units?
 

Kenny

Back for now.
Reaction score
202
JASS:
library Knockback initializer Init requires BoundSentinel, TimerUtils, DestructableLib, IsTerrainWalkable // <-- IsTerrainWalkable


Requires IsTerrainWalkable. :p

And (but not as important):

JASS:
public method TerrainCheck takes Knock d returns integer
        local real x = GetUnitX(d.target)
        local real y = GetUnitY(d.target)

        if IsTerrainWalkable(x + 50.00 * d.cos,y + 50.00 * d.sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif            

        return 0
    endmethod
 

Viikuna

No Marlo no game.
Reaction score
265
I was talking about bouncing back units

Oh, sorry, I was talking about something different. Sorry that I confused you.

Bouncing back you need some vector math maybe.. I will see if I can find some bouncing formula.

You need to check where the terrain is Pathable and then do some complicate vector math and add those little vectors to units speed vector.

See this image:
View attachment BounceFromACliff.bmp

You need someone who is better in math than me to explain how this is done.
 

wraithseeker

Tired.
Reaction score
122
Well forget about the issue then , I think it needs a physis system to do that.... right now , I want to know why does my IsTerrainWalkable checks only for cliffs but not for units.

JASS:
//Formula to calculate Distance = -1 * V * V / (2 * A / Interval)  Where variable V is speed and A is decrement.//
//                            Note! V must be positive and A must be negative!!!!                             //
library Knockback initializer Init requires BoundSentinel, TimerUtils, DestructableLib, IsTerrainWalkable

globals
    private constant real TIME = 0.03
    private constant string GROUND = "MDX\\Dust.mdx"
    private constant string WATER = "MDX\\SlideWater.mdx"
    private constant string COLLISION = "MDX\\DustAndRocks.mdx"
    private constant string ATTACHPOINT = "origin"
    private constant real RADIUS = 180
    private rect TreeRect
    private boolexpr TreeCheck
endglobals

private function CheckTrees takes nothing returns boolean
    if IsDestructableTree(GetFilterDestructable()) then
        return true
    endif
    return false
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private struct Knock
    unit source
    unit target
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    timer Timer
    effect effects
    boolean Terrain
    integer EffectMode
    boolean Trees
    boolean AllowMove
    
    public method TerrainCheck takes Knock d returns integer
        local real x = GetUnitX(d.target)
        local real y = GetUnitY(d.target)

        if IsTerrainWalkable(x + 50.00 * d.cos,y + 50.00 * d.sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif 
        return 0
        endmethod

static method create takes unit source, unit target, real angle, real speed, real decrement, boolean KillTree, boolean Allowmove returns Knock
    local Knock d = Knock.allocate()
    local real x
    local real y
    set d.source = source
    set d.target = target
    set d.Trees = KillTree
    set d.AllowMove = Allowmove
    set x = GetUnitX(d.target)
    set y = GetUnitY(d.target)
    set d.speed = speed * TIME
    set d.decrement = decrement * TIME
    set d.sin = Sin(angle)
    set d.cos = Cos(angle)
    set d.Timer = NewTimer()
    set d.EffectMode = d.TerrainCheck(d)
    if d.EffectMode == 1 then
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    endif
    if d.EffectMode == 2 then
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    endif
    if d.EffectMode == 3 then
     set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
    return d
    endmethod
    
method onDestroy takes nothing returns nothing
    call DestroyEffect(this.effects)
    call ReleaseTimer(this.Timer)
    endmethod
        endstruct

private function Update takes nothing returns nothing
    local Knock d = Knock(GetTimerData(GetExpiredTimer()))
    local unit u = d.target
    local real sx = GetUnitX(u)
    local real sy = GetUnitY(u)
    local real x = sx + d.speed * d.cos
    local real y = sy + d.speed * d.sin
    local integer mode = d.EffectMode
    if d.speed <= 0 then
        call d.destroy()
    endif
    if d.Trees == true then
        call SetRect(TreeRect,sx-RADIUS,sy-RADIUS,sx+RADIUS,sy+RADIUS)
        call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
        endif
        if d.AllowMove == true then
        call SetUnitX(d.target,x)
        call SetUnitY(d.target,y)
        else
    call SetUnitPosition(u,x,y)
    endif
    set d.EffectMode = d.TerrainCheck(d)
    if d.EffectMode == 1 and (mode == 2 or mode == 3) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    elseif d.EffectMode == 2 and (mode == 1 or mode == 3) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    elseif d.EffectMode == 3 and (mode == 1 or mode == 2) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
        set d.speed = d.speed - d.decrement
    set u = null
endfunction

function KnockbackTarget takes unit source, unit target , real angle, real speed, real decrement,boolean KillTree,boolean AllowMove returns boolean
    local Knock d = 0
    if target == null or source == null or speed == null or decrement == null then
        call BJDebugMsg("Invalid Values!")
        return false
    endif
    set d = Knock.create(source,target,angle,speed,decrement,KillTree,AllowMove)
    call SetTimerData(d.Timer,d)
    call TimerStart(d.Timer,TIME,true,function Update)
    return true
endfunction


private function Init takes nothing returns nothing
    set TreeRect = Rect(0,0,1,1)
    set TreeCheck = Filter(function CheckTrees)
endfunction
endlibrary
 

Kenny

Back for now.
Reaction score
202
It is because IsTerrainWalkable uses items to detect pathability. They do not count units as being not pathable, its just how it works. If you want it to detect units too, you will have to group units around the sliding unit, then play the effect when a unit comes within like 100 range of the sliding unit.
 

wraithseeker

Tired.
Reaction score
122
JASS:
//Formula to calculate Distance = -1 * V * V / (2 * A / Interval)  Where variable V is speed and A is decrement.//
//                            Note! V must be positive and A must be negative!!!!                             //
library Knockback initializer Init requires BoundSentinel, DestructableLib, IsTerrainWalkable

globals
    private constant real TIME = 0.03
    private constant string GROUND = "MDX\\Dust.mdx"
    private constant string WATER = "MDX\\SlideWater.mdx"
    private constant string COLLISION = "MDX\\DustAndRocks.mdx"
    private constant string ATTACHPOINT = "origin"
    private constant real RADIUS = 180
    private timer Timer = CreateTimer()
    private integer Count = 0
    private integer array Knocker
    private rect TreeRect
    private boolexpr TreeCheck
endglobals

private function CheckTrees takes nothing returns boolean
    if IsDestructableTree(GetFilterDestructable()) then
        return true
    endif
    return false
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private struct Knock
    unit source
    unit target
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    effect effects
    boolean Terrain
    integer EffectMode
    boolean Trees
    boolean AllowMove
    
    public method TerrainCheck takes Knock d returns integer
        local real x = GetUnitX(d.target)
        local real y = GetUnitY(d.target)

        if IsTerrainWalkable(x + 50.00 * d.cos,y + 50.00 * d.sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif 
        return 0
        endmethod

static method create takes unit source, unit target, real angle, real speed, real decrement, boolean KillTree, boolean Allowmove returns Knock
    local Knock d = Knock.allocate()
    local real x
    local real y
    set d.source = source
    set d.target = target
    set d.Trees = KillTree
    set d.AllowMove = Allowmove
    set x = GetUnitX(d.target)
    set y = GetUnitY(d.target)
    set d.speed = speed * TIME
    set d.decrement = decrement * TIME
    set d.sin = Sin(angle)
    set d.cos = Cos(angle)
    set d.EffectMode = d.TerrainCheck(d)
    if d.EffectMode == 1 then
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    endif
    if d.EffectMode == 2 then
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    endif
    if d.EffectMode == 3 then
     set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
    return d
    endmethod
    
method onDestroy takes nothing returns nothing
    call DestroyEffect(this.effects)
    endmethod
        endstruct

private function Update takes nothing returns nothing
    local Knock d = Knock(GetTimerData(GetExpiredTimer()))
    local unit u = d.target
    local real sx = GetUnitX(u)
    local real sy = GetUnitY(u)
    local real x = sx + d.speed * d.cos
    local real y = sy + d.speed * d.sin
    local integer i = Count - 1
    local integer mode = d.EffectMode
    loop
    exitwhen i < 0
    if d.speed <= 0 then
        call d.destroy()
        set Count = Count - 1
        if Count < 0 then
        call PauseTimer(Timer)
        set Count = 0
        else
        set Knocker<i> = Knocker[Count]
    endif
    else
        if d.AllowMove == true then
        call SetUnitX(d.target,x)
        call SetUnitY(d.target,y)
        else
    call SetUnitPosition(u,x,y)
    endif
     if d.Trees == true then
        call SetRect(TreeRect,sx-RADIUS,sy-RADIUS,sx+RADIUS,sy+RADIUS)
        call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
        endif
    set d.EffectMode = d.TerrainCheck(d)
    if d.EffectMode == 1 and (mode == 2 or mode == 3) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    elseif d.EffectMode == 2 and (mode == 1 or mode == 3) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    elseif d.EffectMode == 3 and (mode == 1 or mode == 2) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif
        set d.speed = d.speed - d.decrement
        set i = i - 1
        endif
        endloop
    set u = null
endfunction

function KnockbackTarget takes unit source, unit target , real angle, real speed, real decrement,boolean KillTree,boolean AllowMove returns boolean
    local Knock d = 0
    if target == null or source == null or speed == null or decrement == null then
        call BJDebugMsg(&quot;Invalid Values!&quot;)
        return false
    endif
    set d = Knock.create(source,target,angle,speed,decrement,KillTree,AllowMove)
    if Count == 0 then
    call TimerStart(Timer,TIME,true,function Update)
    endif
    set Knocker[Count] = d
    set Count = Count + 1
    return true
endfunction


private function Init takes nothing returns nothing
    set TreeRect = Rect(0,0,1,1)
    set TreeCheck = Filter(function CheckTrees)
endfunction
endlibrary</i>


Can anyone tell me what's wrong , there is only effect but no knockback now.
 

Viikuna

No Marlo no game.
Reaction score
265
Seriously. Learn to properly Debug your code. Add some debug msges and comments so it is easier for you to find bugs and us to help you.
 

wraithseeker

Tired.
Reaction score
122
The effects are only d.Effects which are varied from GROUND , WATER , COLLISION.

The knockback doesn't work meaning the unit still stand in place.


JASS:
if d.EffectMode == 1 and (mode == 2 or mode == 3) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
    elseif d.EffectMode == 2 and (mode == 1 or mode == 3) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
    elseif d.EffectMode == 3 and (mode == 1 or mode == 2) then
        call DestroyEffect(d.effects)
        set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
    endif


Which worked.
 

Kenny

Back for now.
Reaction score
202
JASS:
private function Update takes nothing returns nothing
    local Knock d = Knock(GetTimerData(GetExpiredTimer()))
    local unit u = d.target
    local real sx = GetUnitX(u)
    local real sy = GetUnitY(u)
    local real x = sx + d.speed * d.cos
    local real y = sy + d.speed * d.sin
    local integer i = Count - 1
    local integer mode = d.EffectMode


You still have to port all of that stuff to your struct array loop, because d.target and all that does not exist outside of the loop.
 

Viikuna

No Marlo no game.
Reaction score
265
JASS:
local Knock d = Knock(GetTimerData(GetExpiredTimer()))

What is this for?
You should set d=Knocker in your loop..

If you want to use a single timer aproach, you can always check my Timer Tutorial or some other single timer knockback system.
 

Kenny

Back for now.
Reaction score
202
JASS:
//Formula to calculate Distance = -1 * V * V / (2 * A / Interval)  Where variable V is speed and A is decrement.//
//                            Note! V must be positive and A must be negative!!!!                             //
library Knockback initializer Init requires BoundSentinel, DestructableLib, IsTerrainWalkable

private keyword Knock

globals
    private constant real TIME = 0.03
    private constant string GROUND = &quot;MDX\\Dust.mdx&quot;
    private constant string WATER = &quot;MDX\\SlideWater.mdx&quot;
    private constant string COLLISION = &quot;MDX\\DustAndRocks.mdx&quot;
    private constant string ATTACHPOINT = &quot;origin&quot;
    private constant real RADIUS = 180
    private timer Timer = CreateTimer()
    private integer Count = 0
    private Knock array Knocker
    private rect TreeRect
    private boolexpr TreeCheck
endglobals

private function CheckTrees takes nothing returns boolean
    if IsDestructableTree(GetFilterDestructable()) then
        return true
    endif
    return false
endfunction

private function Trees takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

private struct Knock
    unit source
    unit target
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    effect effects
    boolean Terrain
    integer EffectMode
    boolean Trees
    boolean AllowMove
    
    public method TerrainCheck takes Knock d returns integer
        local real x = GetUnitX(d.target)
        local real y = GetUnitY(d.target)

        if IsTerrainWalkable(x + 50.00 * d.cos,y + 50.00 * d.sin) == false then
            return 3
        else
            if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
                return 1
            elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
                return 2
            endif
        endif 
        
        return 0
    endmethod

    static method create takes unit source, unit target, real angle, real speed, real decrement, boolean KillTree, boolean Allowmove returns Knock
        local Knock d = Knock.allocate()
        local real x
        local real y
        
        set d.source = source
        set d.target = target
        set d.Trees = KillTree
        set d.AllowMove = Allowmove
        set x = GetUnitX(d.target)
        set y = GetUnitY(d.target)
        set d.speed = speed * TIME
        set d.decrement = decrement * TIME
        set d.sin = Sin(angle)
        set d.cos = Cos(angle)
        set d.EffectMode = d.TerrainCheck(d)
        
        if d.EffectMode == 1 then
            set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
        endif
        if d.EffectMode == 2 then
            set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
        endif
        if d.EffectMode == 3 then
         set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
        endif
        
        return d
    endmethod
    
    method onDestroy takes nothing returns nothing
        call DestroyEffect(this.effects)
    endmethod
    
endstruct

private function Update takes nothing returns nothing
    local Knock d = 0
    local integer mode = 0
    local integer i = Count - 1
    local real x = 0.00
    local real y = 0.00
    
    loop
        exitwhen i &lt; 0
        local Knock d = Knocker<i>
        set mode = d.EffectMode
        
        set x = GetUnitX(d.target)
        set y = GetUnitY(d.target)
        
        if d.speed &lt;= 0 then
            call d.destroy()
            set Knocker<i> = Knocker[Count]
            set Count = Count - 1
        else
            set x = x + d.speed * d.cos
            set y = y + d.speed * d.sin
            
            if d.AllowMove == true then
                call SetUnitX(d.target,x)
                call SetUnitY(d.target,y)
            else
                call SetUnitPosition(d.target,x,y)
            endif
            
            if d.Trees == true then
                call SetRect(TreeRect,sx-RADIUS,sy-RADIUS,sx+RADIUS,sy+RADIUS)
                call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
            endif
            
            set d.EffectMode = d.TerrainCheck(d)
            
            if d.EffectMode == 1 and (mode == 2 or mode == 3) then
                call DestroyEffect(d.effects)
                set d.effects = AddSpecialEffectTarget(GROUND,d.target,ATTACHPOINT)
            elseif d.EffectMode == 2 and (mode == 1 or mode == 3) then
                call DestroyEffect(d.effects)
                set d.effects = AddSpecialEffectTarget(WATER,d.target,ATTACHPOINT)
            elseif d.EffectMode == 3 and (mode == 1 or mode == 2) then
                call DestroyEffect(d.effects)
                set d.effects = AddSpecialEffectTarget(COLLISION,d.target,ATTACHPOINT)
            endif
            
            set d.speed = d.speed - d.decrement
        endif
        
        set i = i - 1
    endloop
    
    if Count &lt;= 0 then
        call PauseTimer(Timer)
        set Count = 0
    endif
endfunction

function KnockbackTarget takes unit source, unit target , real angle, real speed, real decrement,boolean KillTree,boolean AllowMove returns boolean
    local Knock d = 0
    
    if target == null or source == null or speed == null or decrement == null then
        call BJDebugMsg(&quot;Invalid Values!&quot;)
        return false
    endif
    
    set d = Knock.create(source,target,angle,speed,decrement,KillTree,AllowMove)
    
    if Count == 0 then
        call TimerStart(Timer,TIME,true,function Update)
    endif
    
    set Knocker[Count] = d
    set Count = Count + 1
    
    return true
endfunction

private function Init takes nothing returns nothing
    set TreeRect = Rect(0,0,1,1)
    set TreeCheck = Filter(function CheckTrees)
endfunction

endlibrary
</i></i>


I think thats a bit closer to what you want.
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top