Chain Knockback not working!

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 real CHAINRADIUS = 100
    private constant real SPEEDFACTOR = 0.75
    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 integer Invulnerable = 'Avul'
    private constant real RADIUS = 180
    private timer Timer = CreateTimer()
    private integer Count = 0
    private integer array Knocker
    private rect TreeRect
    private boolexpr TreeCheck
    private boolexpr ChainFilter
    private unit source
    private unit target
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 function ChainCheck takes nothing returns boolean
return target != GetFilterUnit() and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(source)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) and GetWidgetLife(GetFilterUnit()) > 0.405 and GetUnitAbilityLevel(GetFilterUnit(), Invulnerable) <= 0
endfunction

private struct Knock
    unit source
    unit target
    integer EffectMode
    group chains
    group hit
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    effect effects
    boolean Terrain
    boolean Trees
    boolean AllowMove
    boolean constantspeed
    boolean chain
    
    
    
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, boolean ConstantSpeed,boolean Chain 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.constantspeed = ConstantSpeed
    set d.AllowMove = Allowmove
    set d.chain = Chain
    if d.chain == true then
        set d.chains = CreateGroup()
        set d.hit = CreateGroup()
    endif
    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 Knock c = 0
    local unit u
    local unit t
    local real sx
    local real sy 
    local real x 
    local real y 
    local real cx
    local real cy
    local integer i = Count - 1
    local integer mode = 0
    loop
        exitwhen i < 0
        set d = Knocker<i>
        set u = d.target
        set sx = GetUnitX(u)
        set sy = GetUnitY(u)
        set x = sx + d.speed * d.cos
        set y = sy + d.speed * d.sin
        if d.speed &lt;= 0 then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
        endif
        set mode = d.EffectMode
            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
            if d.chain == true then
                set sx = GetUnitX(u)
                set sy = GetUnitY(u)
                set source = d.source
                set target = d.target
                call GroupEnumUnitsInRange(d.chains,sx,sy,CHAINRADIUS,ChainFilter)
                loop
                set t = FirstOfGroup(d.chains)
                exitwhen t == null
                    if not IsUnitInGroup(t,d.hit) then
                        set cx = GetUnitX(t)
                        set cy = GetUnitY(t)
                        call GroupAddUnit(d.hit,t)
                        set c = Knock.create(d.source,t, Atan2(cy-sy,cx-sx), d.speed*SPEEDFACTOR, d.decrement, d.Trees,d.AllowMove,d.constantspeed,d.chain)
                        call GroupAddUnit(c.hit, t)
                        set Knocker[Count] = c
                        set Count = Count + 1
                    endif
                    call GroupRemoveUnit(d.chains, t)
                endloop
                endif
            if d.constantspeed == true then
            else
                set d.speed = d.speed - d.decrement
            endif
            set i = i - 1
        endloop
    set u = null
endfunction

function KnockbackStop takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    local boolean b = false
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
            set b = true
        endif
        set i = i - 1
    endloop
    return b
endfunction

function IsKnockedBack takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            return true
        endif
        set i = i - 1
    endloop
    return false
endfunction

function KnockbackTarget takes unit source, unit target, real angle, real speed, real decrement,boolean KillTree, boolean AllowMove, boolean ConstantSpeed,boolean Chain 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,ConstantSpeed,Chain)
    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)
    set ChainFilter = Filter(function ChainCheck)
endfunction
endlibrary</i></i></i></i></i>


The normal knockbacking works fine but when it comes into contact with a unit , they don't get knocked back. I took rising_dusk code as a reference and then tried to do it myself.
 

Viikuna

No Marlo no game.
Reaction score
265
I didnt find the problem, but you could improve your group usage.

Use one static group for all GroupEnums when you are not planing to keep units in group. ( that .chain can be removed and replaced with a static group )

If you are planning to store your units in some group for some time, like you do with that .hit goup, you should recycle your groups. Basicly, you only create your group when some struct id is used at the first time. If you want to know how this is done, check my how I recycle my group group ( inside ability struct ) in my WormField spell ( You can find it from spell contest #2 thread link )
 

wraithseeker

Tired.
Reaction score
122
putting it in globals? private static group g or in struct static group chain? How do I recycle without any system?
 

Flare

Stops copies me!
Reaction score
662
putting it in globals? private static group g or in struct static group chain? How do I recycle without any system?
Either
JASS:
globals
  private group chain = Creategroup ()
endglobals

or
JASS:
struct ...
  static group chain = CreateGroup ()
endstruct

whichever you prefer. From what I can see, you are only enumerating units with the chain group (i.e. they aren't being stored for any length of time, they are just being filtered, used and removed), so a single group would be easy. Also, you could do the actions within the enumeration filter i.e.
JASS:
function filterfunc takes nothing returns boolean
local StructType data = globalstructdata
if ... then
//Insert your actions here
endif
return false
endfunction


set globalstructdata = localstructdata
call GroupEnumUnitsInRange (...)


As for group recycling,
JASS:
if data.groupVar == null then
  set data.groupVar = CreateGroup ()
endif

in your create method.
 

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 real CHAINRADIUS = 100
    private constant real SPEEDFACTOR = 0.75
    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 integer Invulnerable = &#039;Avul&#039;
    private constant real RADIUS = 180
    private timer Timer = CreateTimer()
    private group chain = CreateGroup()
    private integer Count = 0
    private integer array Knocker
    private rect TreeRect
    private boolexpr TreeCheck
    private boolexpr ChainFilter
    private unit source
    private unit target
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 function ChainCheck takes nothing returns boolean
return true
//return target != GetFilterUnit() and IsUnitEnemy(GetFilterUnit(), GetOwningPlayer(source)) and IsUnitType(GetFilterUnit(), UNIT_TYPE_GROUND) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_MECHANICAL) and GetWidgetLife(GetFilterUnit()) &gt; 0.405 and GetUnitAbilityLevel(GetFilterUnit(), Invulnerable) &lt;= 0
endfunction

private struct Knock
    unit source
    unit target
    integer EffectMode
    group hit
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    effect effects
    boolean Terrain
    boolean Trees
    boolean AllowMove
    boolean constantspeed
    boolean chain
    
    
    
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, boolean ConstantSpeed,boolean Chain 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.constantspeed = ConstantSpeed
    set d.AllowMove = Allowmove
    set d.chain = Chain
    if d.chain == true then
        set d.hit = CreateGroup()
    endif
    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 chain == null then
    set chain = CreateGroup()
    endif
    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 Knock c = 0
    local unit u
    local unit t
    local real sx
    local real sy 
    local real x 
    local real y 
    local real cx
    local real cy
    local integer i = Count - 1
    local integer mode = 0
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        set u = d.target
        set sx = GetUnitX(u)
        set sy = GetUnitY(u)
        set x = sx + d.speed * d.cos
        set y = sy + d.speed * d.sin
        if d.speed &lt;= 0 then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
        endif
        set mode = d.EffectMode
            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
            if d.chain == true then
            call BJDebugMsg(&quot;Working!&quot;)
                set sx = GetUnitX(u)
                set sy = GetUnitY(u)
                set source = d.source
                set target = d.target
                call GroupEnumUnitsInRange(chain,sx,sy,CHAINRADIUS,ChainFilter)
                loop
                set t = FirstOfGroup(chain)
                exitwhen t == null
                    if not IsUnitInGroup(t,d.hit) then
                        set cx = GetUnitX(t)
                        set cy = GetUnitY(t)
                        call GroupAddUnit(d.hit,t)
                        set c = Knock.create(d.source,t, Atan2(cy-sy,cx-sx), d.speed*SPEEDFACTOR, d.decrement, d.Trees,d.AllowMove,d.constantspeed,d.chain)
                        call GroupAddUnit(c.hit, u)
                        set Knocker[Count] = c
                        set Count = Count + 1
                    endif
                     call GroupRemoveUnit(chain, t)
                endloop
                endif
            if d.constantspeed == true then
            else
                set d.speed = d.speed - d.decrement
            endif
            set i = i - 1
        endloop
    set u = null
endfunction

function KnockbackStop takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    local boolean b = false
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
            set b = true
        endif
        set i = i - 1
    endloop
    return b
endfunction

function IsKnockedBack takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            return true
        endif
        set i = i - 1
    endloop
    return false
endfunction

function KnockbackTarget takes unit source, unit target, real angle, real speed, real decrement,boolean KillTree, boolean AllowMove, boolean ConstantSpeed,boolean Chain 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,ConstantSpeed,Chain)
    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)
    set ChainFilter = Filter(function ChainCheck)
endfunction
endlibrary</i></i></i></i></i>


JASS:
scope KnockTest initializer Init

private function Conditions takes nothing returns boolean
    return GetSpellAbilityId() == &#039;TEST&#039;
endfunction

private function Actions takes nothing returns nothing
    local unit u = GetSpellTargetUnit()
    local unit t = GetTriggerUnit()
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real tx = GetUnitX(t)
    local real ty = GetUnitY(t)
    local real a = Atan2(y-ty,x-tx)
    call KnockbackTarget(t,u,a,1000,15,true,false,false,true)
    set u = null
    set t = null
endfunction

//===========================================================================
private function Init takes nothing returns nothing
    local trigger t = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddAction( t, function Actions )
    call TriggerAddCondition(t,Condition(function Conditions))
endfunction

endscope


Alright , did all you said above execpt doing every thing in the filter part , the filter part already have enough lines for the return line :S, and I don't know how to do it there properly....

I included the Test spell in there too , it is a single target unit spell.

EDIT : Alright, made it have no conditions and guess what happened when a unit comes near? The effects gets created and never destroyed and the unit gets stuck at the location forever and cannot hit people. After 3 unit got this bug , the warcraft hanged so I used windows task manager, I assumed that there was a infinite loop.
 

Viikuna

No Marlo no game.
Reaction score
265
If you make your filter return true, it means that your knockback unit also Groups himself and so tries to Knockback himself.

Also, I think it would nice if unit looses some speed, when it collides with some unit ( if chain knockback is actived ).
 

wraithseeker

Tired.
Reaction score
122
SpeedFactor decreases the speed yeah. For the first part , is that what is causing the infinite lag / loop? doesn't matter if it knocks himself , just wanting to test if my chain works.
 

Viikuna

No Marlo no game.
Reaction score
265
Well, when you knockback unit u, system calls a new chain knockback for him, because he gets Grouped. This happens after 0.03 second of u´s knockback.

After 0.06 seconds both of those 2 knockbacks knock u again and there is 4 knocbacks for u.

after 0.09 second there is already 8 knockbacks for u.

Try to calculate how many knocbacks there is for u after 1 sec.
 

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 real CHAINRADIUS = 100
    private constant real SPEEDFACTOR = 0.50
    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 integer Invulnerable = &#039;Avul&#039;
    private constant real RADIUS = 180
    private timer Timer = CreateTimer()
    private integer Count = 0
    private integer array Knocker
    private rect TreeRect
    private boolexpr TreeCheck
    private boolexpr ChainFilter
    private unit source
    private unit target
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 function ChainCheck takes nothing returns boolean
return target != GetFilterUnit()
endfunction

private struct Knock
    unit source
    unit target
    integer EffectMode
    group hit
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    effect effects
    boolean Terrain
    boolean Trees
    boolean AllowMove
    boolean constantspeed
    boolean chain
    
    
    
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, boolean ConstantSpeed,boolean Chain 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.constantspeed = ConstantSpeed
    set d.AllowMove = Allowmove
    set d.chain = Chain
    set d.hit = NewGroup()
    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)
    call ReleaseGroup(this.hit)
    endmethod
        endstruct
        
private function Update takes nothing returns nothing
    local Knock d = 0
    local Knock c = 0
    local unit u
    local unit t
    local real sx
    local real sy 
    local real x 
    local real y 
    local real cx
    local real cy
    local integer i = Count - 1
    local integer mode = 0
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        set u = d.target
        set sx = GetUnitX(u)
        set sy = GetUnitY(u)
        set x = sx + d.speed * d.cos
        set y = sy + d.speed * d.sin
        if d.speed &lt;= 0 then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
        endif
        set mode = d.EffectMode
            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
            if d.chain == true then
                set sx = GetUnitX(u)
                set sy = GetUnitY(u)
                set source = d.source
                set target = d.target
                call GroupEnumUnitsInRange(ENUM_GROUP,sx,sy,CHAINRADIUS,ChainFilter)
                loop
                set t = FirstOfGroup(ENUM_GROUP)
                exitwhen t == null
                    if not IsUnitInGroup(t,d.hit) then
                        set cx = GetUnitX(t)
                        set cy = GetUnitY(t)
                        call GroupAddUnit(d.hit,t)
                        set c = Knock.create(d.source,t, Atan2(cy-sy,cx-sx), d.speed*SPEEDFACTOR, d.decrement, d.Trees,d.AllowMove,d.constantspeed,d.chain)
                        call GroupAddUnit(c.hit, u)
                        set Knocker[Count] = c
                        set Count = Count + 1
                        call BJDebugMsg(&quot;working now&quot;)
                    endif
                     call GroupRemoveUnit(ENUM_GROUP, t)
                endloop
                endif
            if d.constantspeed == true then
            else
                set d.speed = d.speed - d.decrement
            endif
            set i = i - 1
        endloop
    set u = null
    set t = null
endfunction

function KnockbackStop takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    local boolean b = false
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
            set b = true
        endif
        set i = i - 1
    endloop
    return b
endfunction

function IsKnockedBack takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            return true
        endif
        set i = i - 1
    endloop
    return false
endfunction

function KnockbackTarget takes unit source, unit target, real angle, real speed, real decrement,boolean KillTree, boolean AllowMove, boolean ConstantSpeed,boolean Chain 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,ConstantSpeed,Chain)
    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)
    set ChainFilter = Filter(function ChainCheck)
endfunction
endlibrary</i></i></i></i></i>


Some updates and sometimes warcraft hang because of some effect or knocks , made sure that the target wouldn't get grouped again but it still doesn't get knocked back.
 

Kenny

Back for now.
Reaction score
202
What is ENUM_GROUP ? Is it from GroupUtils or something along those lines? Cause i cant seem to find a group by that name in your library.
 

Kenny

Back for now.
Reaction score
202
Try adding GroupUtils to the requirements of your library...

So:

JASS:
library Knockback initializer Init requires BoundSentinel, DestructableLib, IsTerrainWalkable, GroupUtils


Other than that im not sure why its not working.
 

Kenny

Back for now.
Reaction score
202
Do the 3 units that were collided with slide properly?

Have you got a link to dusks system?
 

wraithseeker

Tired.
Reaction score
122
Ok, uploaded mine and dusk's system. For my system, press escape to spawn grunts and then use the mountain king channal ability which is death pact icon on any units.
 

Kenny

Back for now.
Reaction score
202
Im not sure what is going on, but i did manage to get it to not freeze, but maybe thats just my comp.

The units that the main unit collides with are hit and begin to slide, except for some reason they do not move very far at all, but they do sit there until their slide is over. So i guess im just missing something.

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, GroupUtils
globals
    private constant real TIME = 0.03
    private constant real CHAINRADIUS = 100
    private constant real SPEEDFACTOR = 0.75
    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 integer Invulnerable = &#039;Avul&#039;
    private constant real RADIUS = 180
    private timer Timer = CreateTimer()
    private integer Count = 0
    private integer array Knocker
    private rect TreeRect
    private boolexpr TreeCheck
    private boolexpr ChainFilter
    private unit source
    private unit target
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 function ChainCheck takes nothing returns boolean
    return target != GetFilterUnit()
endfunction

private struct Knock
    unit source
    unit target
    integer EffectMode
    group hit
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    effect effects
    boolean Terrain
    boolean Trees
    boolean AllowMove
    boolean constantspeed
    boolean chain
    
    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, boolean ConstantSpeed,boolean Chain 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.constantspeed = ConstantSpeed
        set d.AllowMove = Allowmove
        set d.chain = Chain
        set d.hit = NewGroup()
        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)
        call ReleaseGroup(this.hit)
    endmethod

endstruct
        
private function Update takes nothing returns nothing
    local Knock d = 0
    local Knock c = 0
    local unit u
    local unit t
    local real x 
    local real y 
    local real cx
    local real cy
    local integer i = Count - 1
    local integer mode = 0
    
    loop
        exitwhen i &lt; 0
        
        set d = Knocker<i>
        set u = d.target
        set mode = d.EffectMode
        
        set x = GetUnitX(u)
        set y = GetUnitY(u)
        
        if d.speed &lt;= 0 then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
        else
            set x = x + d.speed * d.cos
            set y = y + d.speed * d.sin
            
            if d.AllowMove == true then
                call SetUnitX(u,x)
                call SetUnitY(u,y)
            else
                call SetUnitPosition(u,x,y)
            endif
            
            if d.Trees == true then
                call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+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
            
            if d.chain == true then
                set source = d.source
                set target = d.target
                call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter)
                loop
                    set t = FirstOfGroup(ENUM_GROUP)
                    exitwhen t == null
                    if not IsUnitInGroup(t,d.hit) then
                        set cx = GetUnitX(t)
                        set cy = GetUnitY(t)
                        call GroupAddUnit(d.hit,t)
                        set c = Knock.create(d.source,t,Atan2(cy-y,cx-x),d.speed,d.decrement,d.Trees,d.AllowMove,d.constantspeed,d.chain)
                        call GroupAddUnit(c.hit,u)
                        set Knocker[Count] = c
                        set Count = Count + 1
                        call BJDebugMsg(&quot;working now&quot;)
                    endif
                    call GroupRemoveUnit(ENUM_GROUP, t)
                endloop
            endif
            
            set d.speed = d.speed - d.decrement
        endif
            
        set i = i - 1
    endloop
        
    set u = null
    set t = null
endfunction

function KnockbackStop takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    local boolean b = false
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
            set b = true
        endif
        set i = i - 1
    endloop
    return b
endfunction

function IsKnockedBack takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            return true
        endif
        set i = i - 1
    endloop
    return false
endfunction

function KnockbackTarget takes unit source, unit target, real angle, real speed, real decrement,boolean KillTree, boolean AllowMove, boolean ConstantSpeed,boolean Chain 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,ConstantSpeed,Chain)
    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)
    set ChainFilter = Filter(function ChainCheck)
endfunction

endlibrary

</i></i></i></i></i>


Thats what i have for now.

Oh and your idea about having the option to decrease the speed or keep it constant is flawed. If you keep the speed constant, then d.speed will never hit 0.00 or less, therefore the knockback will not stop. Im guessing you have a way to fix that?
 

wraithseeker

Tired.
Reaction score
122
Did some changes and probaby fixed now , now I need to know why the chained unit don't move much.

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, GroupUtils
globals
    private constant real TIME = 0.03
    private constant real CHAINRADIUS = 100
    private constant real SPEEDFACTOR = 0.90
    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 integer Invulnerable = &#039;Avul&#039;
    private constant real RADIUS = 180
    private timer Timer = CreateTimer()
    private integer Count = 0
    private integer array Knocker
    private rect TreeRect
    private boolexpr TreeCheck
    private boolexpr ChainFilter
    private unit source
    private unit target
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 function ChainCheck takes nothing returns boolean
    return target != GetFilterUnit()
endfunction

private struct Knock
    unit source
    unit target
    integer EffectMode
    group hit
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    effect effects
    boolean Terrain
    boolean Trees
    boolean AllowMove
    boolean constantspeed
    boolean chain
    
    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, boolean ConstantSpeed,boolean Chain 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.constantspeed = ConstantSpeed
        set d.AllowMove = Allowmove
        set d.chain = Chain
        set d.hit = NewGroup()
        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)
        call ReleaseGroup(this.hit)
endmethod

endstruct
        
private function Update takes nothing returns nothing
    local Knock d = 0
    local Knock c = 0
    local unit u
    local unit t
    local real x 
    local real y 
    local real cx
    local real cy
    local integer i = Count - 1
    local integer mode = 0
    
    loop
        exitwhen i &lt; 0
        
        set d = Knocker<i>
        set u = d.target
        set mode = d.EffectMode
        
        set x = GetUnitX(u)
        set y = GetUnitY(u)
        
        if d.speed &lt;= 0 then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
        else
            set x = x + d.speed * d.cos
            set y = y + d.speed * d.sin
            set d.EffectMode = d.TerrainCheck(d)
            if d.AllowMove == true then
                call SetUnitX(u,x)
                call SetUnitY(u,y)
            else
                call SetUnitPosition(u,x,y)
            endif
            if d.Trees == true then
                call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+RADIUS)
                call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
            endif
            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
              if d.chain == true then
                set source = d.source
                set target = d.target
                call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter)
                loop
                    set t = FirstOfGroup(ENUM_GROUP)
                    exitwhen t == null
                    if not IsUnitInGroup(t,d.hit) then
                        set cx = GetUnitX(t)
                        set cy = GetUnitY(t)
                        call GroupAddUnit(d.hit,t)
                        set c = Knock.create(d.source,t,Atan2(y-cy,x-cx),d.speed,d.decrement,d.Trees,d.AllowMove,d.constantspeed,d.chain)
                        call GroupAddUnit(c.hit,u)
                        set Knocker[Count] = c
                        set Count = Count + 1
                        call BJDebugMsg(&quot;working now&quot;)
                    endif
                    call GroupRemoveUnit(ENUM_GROUP, t)
                endloop
            endif
        endif
            
        set i = i - 1
    endloop
        
    set u = null
    set t = null
endfunction

function KnockbackStop takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    local boolean b = false
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
            set b = true
        endif
        set i = i - 1
    endloop
    return b
endfunction

function IsKnockedBack takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            return true
        endif
        set i = i - 1
    endloop
    return false
endfunction

function KnockbackTarget takes unit source, unit target, real angle, real speed, real decrement,boolean KillTree, boolean AllowMove, boolean ConstantSpeed,boolean Chain 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,ConstantSpeed,Chain)
    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)
    set ChainFilter = Filter(function ChainCheck)
endfunction

endlibrary</i></i></i></i></i>
 

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!!!!                             //
//******************************************************************************
//*                     Formula to calculate the distance                      *
//*                      - 1 * V * V / ( 2 * A / Interval)                     *
//*              Variable V = The amount of speed the knockedback unit has     *
//*              Variable A = The amount of speed reduced per Interval         *
//*       Variable Interval = Located at the top of the Knockback System       *
//*                                                                            *
//*                   Some things to note about them                           *
//*                  Variable A must be a positive number                      *
//*                  Variable B must be a negative number                      *
//*                                                                            *
//*                                                                            *
//*                                                                            *
//*                                                                            *
//******************************************************************************
library Knockback initializer Init requires BoundSentinel, DestructableLib, IsTerrainWalkable, GroupUtils
globals
    private constant real TIME = 0.03
    private constant real CHAINRADIUS = 100
    private constant real SPEEDFACTOR = 0.90
    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 integer Invulnerable = &#039;Avul&#039;
    private constant real RADIUS = 180
    private timer Timer = CreateTimer()
    private integer Count = 0
    private integer array Knocker
    private rect TreeRect
    private boolexpr TreeCheck
    private boolexpr ChainFilter
    private unit source
    private unit target
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 function ChainCheck takes nothing returns boolean
    return target != GetFilterUnit()
endfunction

private struct Knock
    unit source
    unit target
    integer EffectMode
    group hit
    real x
    real y
    real cos
    real sin
    real speed
    real decrement
    real angle
    effect effects
    boolean Terrain
    boolean Trees
    boolean AllowMove
    boolean constantspeed
    boolean chain
    
    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, boolean ConstantSpeed,boolean Chain 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.constantspeed = ConstantSpeed
        set d.AllowMove = Allowmove
        set d.chain = Chain
        set d.hit = NewGroup()
        set x = GetUnitX(d.target)
        set y = GetUnitY(d.target)
        set d.speed = speed * TIME
        set d.decrement = decrement * TIME
        set d.angle = angle
        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)
        call ReleaseGroup(this.hit)
endmethod

endstruct
        
private function Update takes nothing returns nothing
    local Knock d = 0
    local Knock c = 0
    local unit u
    local unit t
    local real x 
    local real y 
    local real cx
    local real cy
    local integer i = Count - 1
    local integer mode = 0
    
    loop
        exitwhen i &lt; 0
        
        set d = Knocker<i>
        set u = d.target
        set mode = d.EffectMode
        
        set x = GetUnitX(u)
        set y = GetUnitY(u)
        
        if d.speed &lt;= 0 then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
        else
            set x = x + d.speed * d.cos
            set y = y + d.speed * d.sin
            set d.EffectMode = d.TerrainCheck(d)
            if d.AllowMove == true then
                call SetUnitX(u,x)
                call SetUnitY(u,y)
            else
                call SetUnitPosition(u,x,y)
            endif
            if d.Trees == true then
                call SetRect(TreeRect,x-RADIUS,y-RADIUS,x+RADIUS,y+RADIUS)
                call EnumDestructablesInRect(TreeRect,TreeCheck,function Trees)
            endif
            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)
                else
                set d.angle = d.angle = 0.00 - d.angle
            endif
            set d.speed = d.speed - d.decrement
              if d.chain == true then
                set source = d.source
                set target = d.target
                call GroupEnumUnitsInRange(ENUM_GROUP,x,y,CHAINRADIUS,ChainFilter)
                loop
                    set t = FirstOfGroup(ENUM_GROUP)
                    exitwhen t == null
                    if not IsUnitInGroup(t,d.hit) then
                        set cx = GetUnitX(t)
                        set cy = GetUnitY(t)
                        call GroupAddUnit(d.hit,t)
                        set c = Knock.create(d.source,t,Atan2(y-cy,x-cx),d.speed,d.decrement,d.Trees,d.AllowMove,d.constantspeed,d.chain)
                        call GroupAddUnit(c.hit,u)
                        set Knocker[Count] = c
                        set Count = Count + 1
                        call BJDebugMsg(&quot;working now&quot;)
                    endif
                    call GroupRemoveUnit(ENUM_GROUP, t)
                endloop
            endif
        endif
            
        set i = i - 1
    endloop
        
    set u = null
    set t = null
endfunction

function KnockbackStop takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    local boolean b = false
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            call d.destroy()
            set Count = Count - 1
            if Count &lt; 0 then
                call PauseTimer(Timer)
                set Count = 0
            else
                set Knocker<i> = Knocker[Count]
            endif
            set b = true
        endif
        set i = i - 1
    endloop
    return b
endfunction

function IsKnockedBack takes unit target returns boolean
    local integer i = Count - 1
    local Knock d = 0
    loop
        exitwhen i &lt; 0
        set d = Knocker<i>
        if d.target == target then
            return true
        endif
        set i = i - 1
    endloop
    return false
endfunction

function KnockbackTarget takes unit source, unit target, real angle, real speed, real decrement,boolean KillTree, boolean AllowMove, boolean ConstantSpeed,boolean Chain 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,ConstantSpeed,Chain)
    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)
    set ChainFilter = Filter(function ChainCheck)
endfunction

endlibrary</i></i></i></i></i>
 
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