System Knockback System (KBS)

Kenny

Back for now.
Reaction score
202
Knockback System (KBS)
by kenny!
v2.04

Basically, I'm submitting this system because I think it is worthy. However, for all those people who wonder why we need another knockback system, here are some other reasons:

- This system is fully documented and easy to use.
- Runs on one timer. I believe the only other systems to do this are emjlr3's and uberplayer's (on this site).
- Has easily changeable special effects.
- It is also completely MUI and needs no other systems at all.

So, I originally made this system well over a year ago and it leaked and was slow etc etc. So a few months ago i ported it to VJASS to fix it up a bit, finding out that i still had a handle leak problem which i could not for the life of me solve. Then i tried again a little while ago and fixed it. So i put some documentation in and got it ready to submit.

I tried to make the system easy enough for GUI users to use, as well as JASS users. Its simplistic form allows for basic uses and more creative users for those more experienced.

Heres the code:
JASS:
library KBS initializer Init
//***************************************************************************************
//**                                                                                   **     
//**    Knockback System (KBS)                                    **By kenny!**        **
//**    v 2.04                                                                         **
//**                                                                                   **
//**    A system I made that can be used for knockback spells in a variety of          **
//**    applications in a map. User defined variables make it easy to give the desired **
//**    effect for any spell.                                                          **
//**                                                                                   **
//**    Requires:                                                                      **
//**        - A vJASS preprocessor (NewGen Pack).                                      **
//**        - No other systems.                                                        **
//**        - A dummy unit. One can be found in this map ('u000')                      **
//**        - The special effects found in the import/export section of this map.      **
//**          They are the "Dust.mdx" and the "SlideWater.mdx". Or you can use your    **
//**          own if you have some.                                                    **
//**                                                                                   **
//***************************************************************************************

//***************************************************************************************
//**                                                                                   **
//**    Other Information:                                                             **
//**        - Angle is taken in degrees. But can easily be changed if you know how.    **
//**        - Units will be stopped if they hit the map borders.                       **
//**        - Remember to import the special effect into your map if you need them.    **
//**        - There are two functions that can be used in this system.                 **
//**        - NEW FUNCTION: KBS_BeginCommon() is for all the common knockback uses in  **
//**          your map. It only takes 4 parameters, and use global parameters for Area **
//**          AllowMove and CheckPathing. Making it an icredibly easy function to use. **
//**                                                                                   **
//**    Sliding Distances:                                                             **
//**        - This is some general knowledge on the different distances and how to     **
//**          get them.                                                                **
//**        - Sliding distances have changed in this version of the system.            **
//**        - The function call (KBS_Begin/Ex) now takes distance and duration         **
//**          parameters instead of startspeed and deceleration.                       **
//**        - Therefore the parameter 'Distance' will set the length of the knockback  **
//**          while the parameter 'Duration" will set the time it will take.           **
//**                                                                                   **
//***************************************************************************************

//***************************************************************************************
//**                                                                                   **
//**    Implementation:                                                                **
//**        - First off you need the NewGen world editor. This is a must.              **
//**        - Copy this trigger into your map. Or make a trigger in your map and       **
//**          convert it to custom text. Then copy this text into that trigger.        **
//**        - Now you will either need to export the special effects from this map to  **
//**          your map, or you will need your own. I do not take credit for the        **
//**          special effects found in this map.                                       **
//**        - Once you have the effects in your map. Find the configuration block      **
//**          that is underneath all this green text. Change the WATER_SFX and the     **
//**          DIRT_SFX strings to the ones in your map. These should be the same if    **
//**          you exported the ones from this map.                                     **
//**        - Make sure you have the dummy unit needed. It can be any unit, but i      **
//**          suggest you use the one found in this map, it is labelled 'Dummy Unit'   **
//**          or 'u000'.                                                               **
//**        - Your done! Save your map, make a spell using this system and try it out. **
//**                                                                                   **
//**    NOTE: Please report any bugs to me at thehelper.net via PM. (User name: kenny!)**
//**                                                                                   **
//***************************************************************************************
                                                                           
//***************************************************************************************
//**                                                                                   **
//**    Usage:                                                                         **
//**                                                                                   **
//**                call KBS_Begin(Target,Distance,Duration,Angle,Area)                **
//**                                       or                                          **
//**call KBS_BeginEx(Target,Distance,Duration,Angle,Effect,Area,AllowMove,CheckPathing)**
//**                                       or                                          **
//**                call KBS_BeginCommon(Target,Distance,Duration,Angle)               **
//**                                                                                   **
//**    - Target        - The unit that will be used in the knockback.                 **
//**    - Distance      - The distance of the knockback (how far the unit will slide). **                 
//**    - Duration      - The duration of the knockback refers to how long the unit    **
//**                      will slide for.                                              **
//**    - Angle         - The angle that the unit will be knocked back at.             **
//**                      THIS MUST BE IN DEGREES. <- Easier for GUI users.            **
//**    - Effect        - This is only used in the extended function. If you do not    **
//**                      want one of the predefined effects, you can choose your own. **
//**                      However, this effect is attached to the unit and removed at  **
//**                      the end, so non-looping or repeating effect wont work.       **
//**    - Area          - This determines whether or not trees will be knocked down.   **
//**                      For trees to be knocked down, a positive number (real) must  **
//**                      be used, such as 150.00, which would give a radius of 150.00 **
//**                      in which trees will be knocked down.                         **
//**                      For trees to not be knocked down, a negative number (real)   **
//**                      must be used, such as -150.00, which would create a radius   **
//**                      that if a tree comes within it, the unit will stop moving.   **
//**                      For none of those effects, the number 0 (0.00) can be used.  **
//**                      This will just cause the units to "bounce" off trees.        **
//**    -Allowmove      - This boolean will decided whether or not you want the unit   **
//**                      to have the ability to move while being knocked back.        **
//**                      "true" will allow them to move, while "false" will not.      **
//**    -CheckPathing   - A boolean that, if true, will check for unpathable terrain   **
//**                      such as a wall or cliff, or where doodads may be. If false   **
//**                      it will ignore these changes and the unit will be pushed     **
//**                      along the wall, cliff or doodad.                             **
//**                                                                                   **
//**       REMEMBER: Positive = trees destroyed, Negative = trees not destroyed.       **
//**                                                                                   **
//**    Example of Usage:                                                              **
//**                                                                                   **
//**  -call KBS_Begin(target,500.00,2.00,270.00,150.00)                                **
//**    or                                                                             **
//**  -call KBS_BeginEx(target,500.00,2.00,270.00,"Effect.mdl",-150.00,true,true)      **
//**                                                                                   **
//**    The first one will cause the target unit of a spell to be knocked back 500.00  **
//**    range over a 2.00 second duration. It will be knocked back at an angle of      **    
//**    270.00, which I'm pretty sure is south, and it will knock down trees within    ** 
//**    a 150.00 radius around the unit.                                               **
//**                                                                                   **
//**    The bottom one of the two will do the exact same as the top, however you are   **
//**    able to choose your own special effect that will be attached to the unit. As   **
//**    you can see, the number for Area (destroying trees) is negative, therefore     **
//**    no trees will be knocked down, and the unit will stop moving if it comes in    **
//**    contact with a tree. There is also an extra boolean nearing end, this is for   **
//**    allowing units to move while sliding. It is true, meaning units are allowed.   **
//**    There is also an added feature that will check for pathable terrain and stop a **
//**    unit if it comes in contact with things such as walls, cliffs or doodads.      **
//**    If true, the unit will stop moving if it comes in direct contact will a wall   **
//**    or cliff.                                                                      **
//**                                                                                   **
//***************************************************************************************

//***************************************************************************************
//**                                                                                   **
//**    Other functions:                                                               **
//**                                                                                   **
//**    - call KBS_IsUnitSliding(Target)                                               **
//**                                                                                   **
//**    - This function checks if a picked unit is currently sliding using this        **
//**      system. It will return true if it is.                                        **
//**                                                                                   **
//**    - call KBS_StopUnitSliding(Target)                                             **
//**                                                                                   **
//**    - This function will stop a picked unit from sliding (using this system).      **
//**      It also returns true if the unit is stopped.                                 **
//**                                                                                   **
//**    - These functions can be used in conjunction with each other, by checking if a **
//**      unit is sliding then stopping it if it is. The regular Storm Bolt spell in   **
//**      the Test Spells section uses these two function in conjunction with each     **
//**      other as an example.                                                         **
//**                                                                                   **
//***************************************************************************************      

//***************************************************************************************
//**                                                                                   **
//**    Some points on checking for pathable terrain:                                  **
//**                                                                                   **
//**`   - The area specified for destroying trees must be at least 75.00-100.00 range  **
//**      larger than the distance for checking for pathing, which is below in the     **
//**      globals block.                                                               **
//**    - When using KBS_BeginEx() and using either 0.00 or a negative value for the   **
//**      parameter 'Area' (destroying trees) it is better to have CheckPathing as     **
//**      FALSE. This is due to the fact that setting CheckPathing to TRUE will        **
//**      override the 'Area' Parameter and stop a unit if it gets near trees.         **
//**    - Basically what this means is that you cannot get a unit to just 'bounce' off **
//**      trees anymore, it is either destroy trees or get stopped by them.            **
//**                                                                                   **
//***************************************************************************************

globals
    // CONFIGURABLES:
    
    private constant integer DUMMY_ID       = 'u000'           // This is the dummy unit.
    private constant real    INTERVAL       = 0.04             // Recommended Interval.
    private constant string  ATTACH_POINT   = "origin"         // Attachment point for effects.
    private constant string  WATER_SFX      = "SlideWater.mdx" // Water slide effect.
    private constant string  DIRT_SFX       = "Dust.mdx"       // Ground slide effect.
    private constant string  COLLISION_SFX  = "Abilities\\Weapons\\AncientProtectorMissile\\AncientProtectorMissile.mdl" // Collision effect when unit hits a wall/cliff etc.
    private constant boolean SHOW_COLLISION = true             // Whether or not effect will show if a unit collides with a wall/cliff etc.
    
    // The follow are used when using KBS_BeginCommon() for the common parameters that will be used.
    
    private constant real    COMMON_AREA          = 150.00  // The area in which trees will be destroyed.
    private constant boolean COMMON_ALLOW_MOVE    = true    // Whether or not to allow units to move.
    private constant boolean COMMON_CHECK_PATHING = true    // Whether or not to check pathing.
    
    // The following raw codes will probably not need to be changed for most maps.
    
    private constant integer HARVEST        = 'Ahrl' // Raw code for: Harvest(Ghouls Lumber).
    private constant integer LOCUST         = 'Aloc'  // Raw code for Locust ability.
    
    // The following value is used for terrain pathability checking.
    
    private constant real    DISTANCE       = 50.00
    // The above is the distance in front of the unit that terrain pathability
    // will be checked. A value of 40.00-50.00 is recommended. Also make sure
    // that this distance is AT LEAST 75.00-100.00 units less than the ranges set
    // for destroying trees, otherwise it wont work properly.
    
    // Example: Keep above distance at 50.00, and use 150.00 for knocking down trees.
    //          This seems to work very well.
    
    private constant real    MAX_RANGE      = 10.00
    // Max range for checking for pathability. I suggest you leave this alone.
endglobals

//***************************************************************************************
//**                                                                                   ** 
//**          DO NOT TOUCH BELOW HERE UNLESS YOU KNOW WHAT YOUR ARE DOING!             **
//**                                                                                   **
//***************************************************************************************     

private keyword Data

globals
    private Data     array D
    private boolean  array BA
    private item     array Hidden
    private integer  Hidden_max       = 0
    private integer  Total            = 0
    private real     Game_maxX        = 0.00
    private real     Game_minX        = 0.00
    private real     Game_maxY        = 0.00
    private real     Game_minY        = 0.00
    private rect     Rect1            = null
    private unit     Tree_dummy       = null
    private item     Item             = null
    private timer    Timer            = null
    private boolexpr Tree_filt        = null
endglobals

//=======================================================================
private function Filter_items takes nothing returns nothing
    if IsItemVisible(GetEnumItem()) then
        set Hidden[Hidden_max] = GetEnumItem()
        call SetItemVisible(Hidden[Hidden_max],false)
        set Hidden_max = Hidden_max + 1
    endif
endfunction

// Thanks to Vexorian for original concept, and Anitarf for the up-to-date version. (Slightly midified).
private function Check_pathability takes real x1, real y1 returns boolean
    local real x2 = 0.00
    local real y2 = 0.00
    
    call SetRect(Rect1,0.00,0.00,128.00,128.00)
    call MoveRectTo(Rect1,x1,y1)
    call EnumItemsInRect(Rect1,null,function Filter_items)

    call SetItemPosition(Item,x1,y1)
    set x2 = GetItemX(Item)
    set y2 = GetItemY(Item)
    call SetItemVisible(Item,false)

    loop
        exitwhen Hidden_max <= 0
        set Hidden_max = Hidden_max - 1
        call SetItemVisible(Hidden[Hidden_max],true)
        set Hidden[Hidden_max] = null
    endloop

    return (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) < MAX_RANGE * MAX_RANGE
endfunction

//=======================================================================
private function Destroy_trees takes nothing returns nothing
    if BA[0] then
        call KillDestructable(GetEnumDestructable()) // Used to destroy destructables.
    else
        set BA[1] = true
    endif
endfunction

// Thanks to PitzerMike for this function. (Modified Slightly).
private function Check_trees takes nothing returns boolean
    local destructable dest   = GetFilterDestructable()
    local boolean      result = false
    
    if GetDestructableLife(dest) > 0.405 then
        call ShowUnit(Tree_dummy,true)
        call SetUnitX(Tree_dummy,GetWidgetX(dest))
        call SetUnitY(Tree_dummy,GetWidgetY(dest))
        
        set result = IssueTargetOrder(Tree_dummy,"harvest",dest)
        call IssueImmediateOrder(Tree_dummy,"stop")
        call ShowUnit(Tree_dummy,false)
        
        set dest = null
        return result
    endif
    
    set dest = null
    return result
endfunction

// Checks if a point is on the map boundaries.
private function Outside_bounds takes real x, real y returns boolean
    return (x > Game_maxX or y > Game_maxY or x < Game_minX or y < Game_minY)
endfunction

//=======================================================================
private struct Data
    unit    targ      = null
    
    real    speed     = 0.00
    real    decrease  = 0.00
    real    sin       = 0.00
    real    cos       = 0.00
    real    radius    = 0.00
    
    integer sfxmode   = 0
    effect  sfx       = null
    
    boolean custom    = false
    boolean allowmove = false
    boolean pathing   = false
    boolean forcestop = false
    
    // Checking for terrain type.
    method terrain takes nothing returns integer
        local real x = GetUnitX(.targ)
        local real y = GetUnitY(.targ)

        if IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
            return 1
        elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
            return 2
        endif
        
        return 0
    endmethod
    
    static method create takes unit Target, real Distance, real Duration, real Angle, string Effect, real Area, boolean AllowMove, boolean CheckPathing returns Data
        local Data d = Data.allocate()
        
        // Allocates struct members to user defined variables.
        set d.targ      = Target
        set d.speed     = (2.00 * Distance) / (Duration + 1.00)
        set d.decrease  = d.speed / Duration
        set d.sin       = Sin(Angle)
        set d.cos       = Cos(Angle)
        set d.radius    = Area
        set d.allowmove = AllowMove
        set d.pathing   = CheckPathing
        set d.sfxmode   = d.terrain()
        
        if Effect != "" and Effect != null then
            set d.custom = true
        endif
        
        // Adding effects to the unit.
        if d.custom then
            set d.sfx = AddSpecialEffectTarget(Effect,d.targ,ATTACH_POINT)
        else
            if d.sfxmode == 1 then
                set d.sfx = AddSpecialEffectTarget(DIRT_SFX,d.targ,ATTACH_POINT)
            elseif d.sfxmode == 2 then
                set d.sfx = AddSpecialEffectTarget(WATER_SFX,d.targ,ATTACH_POINT)
            endif
        endif
        
        return d
    endmethod
    
    private method onDestroy takes nothing returns nothing
        set .targ = null
        if .sfx != null then
            call DestroyEffect(.sfx) // Destroys effects if needed.
            set .sfx = null
        endif
        set BA[0] = false
        set BA[1] = false
    endmethod
endstruct

//=======================================================================
private function Update takes nothing returns nothing
    local integer i       = 1
    local integer newmode = 0
    local integer height  = 0
    local Data    d       = 0
    local real    x       = 0.00
    local real    y       = 0.00
    local real    newx    = 0.00
    local real    newy    = 0.00
        
    loop
        exitwhen i > Total
        set d = D<i>
        set newmode = d.sfxmode
       
        set x = GetUnitX(d.targ)
        set y = GetUnitY(d.targ)
        
        // Destroys trees if wanted, or stops the unit
        if d.radius != 0.00 then
            set BA[0] = d.radius &gt; 0.00

            call SetRect(Rect1,x - d.radius,y - d.radius,x + d.radius,y + d.radius)
            call EnumDestructablesInRect(Rect1,Tree_filt,function Destroy_trees)
        endif
        
        // Checks for terrain pathability, such as walls and cliffs.
        if d.pathing then
            if Check_pathability(x + DISTANCE * d.cos,y + DISTANCE * d.sin) == false then
                set height = 1
                if SHOW_COLLISION then
                    call DestroyEffect(AddSpecialEffect(COLLISION_SFX,x,y))
                endif
            endif
        endif

        if not d.custom then
            set d.sfxmode = d.terrain() // Checks for pathing again.                
            
            // Adds special effect if terrain changes.
            if d.sfxmode == 1 and newmode == 2 then
                call DestroyEffect(d.sfx)
                set d.sfx = AddSpecialEffectTarget(DIRT_SFX,d.targ,ATTACH_POINT)
            elseif d.sfxmode == 2 and newmode == 1 then
                call DestroyEffect(d.sfx)
                set d.sfx = AddSpecialEffectTarget(WATER_SFX,d.targ,ATTACH_POINT)
            endif
        endif
         
        if d.speed &lt;= 0 or Outside_bounds(x,y) or BA[1] or height == 1 or d.forcestop == true then
            call d.destroy() // Finish knockback
            set D<i> = D[Total]
            set Total = Total - 1
            set i = i - 1
            set height = 0
        else
            set newx = x + d.speed * d.cos
            set newy = y + d.speed * d.sin
            
            // Allows unit to move while sliding, if specified.
            if d.allowmove then
                call SetUnitX(d.targ,newx)
                call SetUnitY(d.targ,newy)
            else
                call SetUnitPosition(d.targ,newx,newy)
            endif
                
            set d.speed = d.speed - d.decrease // Sets new speed.
        endif
            
        set i = i + 1
    endloop
    
    if Total &lt;= 0 then
        call PauseTimer(Timer)
        set Total = 0
    endif
endfunction

//=======================================================================
// Checks if a unit is sliding - returns true if it is.
public function IsUnitSliding takes unit Target returns boolean
    local integer i = 1

    loop
        exitwhen i &gt; Total
        if D<i>.targ == Target then
            return true
        endif
        set i = i + 1
    endloop
    
    return false
endfunction

//=======================================================================
// Stops a unit from sliding - returns true if a unit is stopped.
public function StopUnitSliding takes unit Target returns boolean
    local integer i = 1

    loop
        exitwhen i &gt; Total
        if D<i>.targ == Target then
            set D<i>.forcestop = true
            return true
        endif
        set i = i + 1
    endloop
    
    return false
endfunction

//=======================================================================
// Extended function - gives the most customisation for a single unit knockback.
public function BeginEx takes unit Target, real Distance, real Duration, real Angle, string Effect, real Area, boolean AllowMove, boolean CheckPathing returns boolean
    local Data d = 0
    
    if Target == null or Distance &lt;= 0.00 or Duration &lt;= 0.00 then
        debug call BJDebugMsg(&quot;Error: Invalid input in KBS_Begin(Ex)&quot;) // Error message.
        return false
    endif
    
    set d = Data.create(Target,Distance,(Duration/INTERVAL),(Angle * 0.01745328),Effect,Area,AllowMove,CheckPathing)
    
    set Total = Total + 1
    if Total == 1 then
        call TimerStart(Timer,INTERVAL,true,function Update)
    endif
    set D[Total] = d
    
    return true
endfunction

//=======================================================================
// Basic function - Can be used in a wide variety of ways and gives a basic knockback.
public function Begin takes unit Target, real Distance, real Duration, real Angle, real Area returns nothing    
    call BeginEx(Target,Distance,Duration,Angle,&quot;&quot;,Area,false,false)
endfunction

// Common function - For all basic knockback needs, easy to use and simple to remember.
public function BeginCommon takes unit Target, real Distance, real Duration, real Angle returns nothing
    call BeginEx(Target,Distance,Duration,Angle,null,COMMON_AREA,COMMON_ALLOW_MOVE,COMMON_CHECK_PATHING)
endfunction

//=======================================================================
// Sets map boundries and sets timer, rect and filter.
private function Init takes nothing returns nothing
    set Timer     = CreateTimer()
    set Rect1     = Rect(0.00,0.00,1.00,1.00)
    set Tree_filt = Filter(function Check_trees)
    
    // Map bounds
    set Game_maxX = GetRectMaxX(bj_mapInitialPlayableArea) - 64.00
    set Game_maxY = GetRectMaxY(bj_mapInitialPlayableArea) - 64.00
    set Game_minX = GetRectMinX(bj_mapInitialPlayableArea) + 64.00
    set Game_minY = GetRectMinY(bj_mapInitialPlayableArea) + 64.00
    
    // Boolean values for destroying trees
    set BA[0]     = false
    set BA[1]     = false
     
    // Creating unit for destroying trees
    set Tree_dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),DUMMY_ID,0.00,0.00,0.00)
    call SetUnitPathing(Tree_dummy,false)
    call ShowUnit(Tree_dummy,false)
    call UnitAddAbility(Tree_dummy,HARVEST)
    call UnitAddAbility(Tree_dummy,LOCUST)
    
    // Creating item for pathability checking
    set Item = CreateItem(&#039;ciri&#039;,0.00,0.00)
    call SetItemVisible(Item,false)  
endfunction

endlibrary

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


Screenshots:
StormBolt.jpg

ThunderClap.jpg

*Change Log*

- 30th Oct - Initial Release.

- 19th Nov - Version 2.00 released, few big updates to the system. Re-worked how trees are knocked down, now uses a real value instead of boolean. Read green block of writing in the code for more information. Added an option to allow the player to move the knocked back unit while it's sliding. Added an option to check terrain height changes and stop the unit accordingly. Its pretty sketchy but it gets the job done in most maps. However it has problems when there are large/steep hills in the map. Some other coding changes to increase efficiency and stuff.

- 26th Nov - Version 2.01 released. No major changes except for the addition of two simple function that were "requested" by like 1 or 2 people. So i decided to add them.

- 17th Dec - Version 2.02 released. Few major changes to how the system works, including: the parameters "Startspeed" and "Deceleration" have now been changed to "Distance" and "Duration" which i find is far easier to use. Now it is as easy as putting in a value of say 500.00 for distance and 2.00 for duration, making it last 2 seconds and knocking the unit back 500.00 distance. Also "Checkheight" (which checked for terrain height using Z locations) has now been replaced with "CheckPathing" which checks for pathable terrain using an item check. Original concept is from Vexorian, it has been slightly modified. Also added an effect for when a unit hits something with Checkpathing == true, this can also be made to not show. Unfortunately this means it is not backwards compatible with earlier versions, but this is made up for with the easier arguments needed.

- 9th April - Version 2.03 released. Few minor changes made. Standardized the coding, making it easier to read. Updated the check pathability function from Vexorian's old version to Anitarf's newer version. Few minor changes to the coding in general, changed the two bonus functions a little bit. Nothing big, but it should be a little nicer now.

- 9th April - Version 2.04 released. Another couple of minor changes. Figured out my calculation for distance was a little off, it is now fixed. An incredibly minor change to how the effects work when wanting a custom one. And finally i added a new function. Check this post for details.
 

Attachments

  • KBS by kenny! [Version 2.01].w3x
    95.5 KB · Views: 325
  • KBS by kenny! [Version 2.02].w3x
    84.7 KB · Views: 402
  • KBS by kenny! [Version 2.04].w3x
    99.1 KB · Views: 472

Romek

Super Moderator
Reaction score
963
Not another one of these..
- This system is fully documented and easy to use.
- Runs on one timer. I believe the only other systems to do this are emjlr3's and uberplayer's (on this site).
- Has easily changeable special effects.
- It is also completely MUI and needs no other systems at all.

You even mentioned 2 other systems which do exactly the same thing there. They're easy to use too.

JASS:
private function KillEnumDestructables takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction

Could be put into the "TreeCheck" function.
if result == true then KillDestructible.

and make it return false. Always :)
 

Kenny

Back for now.
Reaction score
202
The two other systems mentioned are different in many ways. Uberplayer's, even though it is MUI and all that, is a little more basic then this one and it needs other systems. Its special effects and tree filters are far different to mine.

Emjlr3's on the other hand, is more advanced, using friction and gravity and physics stuff, which a lot of people do not understand. Also the last time I checked his system, it didn't even knock down trees, even though it said it would.

Therefore, i see this system as somewhat half way between the two others, kind of bridging the gap between beginners and advanced mappers.
 

Kenny

Back for now.
Reaction score
202
Instructions on how to call it can be found in the green text section above the actualy system itself.

JASS:
//***************************************************************************************
//**                                                                                   **
//**    Usage:                                                                         **
//**                                                                                   **
//**    call KBS_Begin(Target,Startspeed,Deceleration,Angle,Killtrees)                 **
//**    or                                                                             **
//**    call KBS_BeginEx(Target,Startspeed,Deceleration,Angle,Specialeffect,Killtrees) **
//**                                                                                   **
//**    - Target        - The unit that will be used in the knockback.                 **
//**    - Startspeed    - The initial speed at which the unit will be knocked back.    **                 
//**    - Deceleration  - The deceleration of the unit. Slows the unit down over       **
//**                      the duration of the knockback.                               **
//**    - Angle         - The angle that the unit will be knocked back at.             **
//**                      THIS MUST BE IN DEGREES. &lt;- Easier for GUI users.            **
//**    - Specialeffect - This is only used in the extended function. If you do not    **
//**                      want one of the predefined effects, you can choose your own. **
//**                      However, this effect is attached to the unit and removed at  **
//**                      the end, so non-looping or repeating effect wont work.       **
//**    - Killtrees     - Whether or not trees will be knocked down when units get     **
//**                      close to them. If true then trees will be knocked down, if   **
//**                      false then the unit will go around them.                     **
//**                                                                                   **
//**    Example of Usage:                                                              **
//**                                                                                   **
//**    - call KBS_Begin(target,15.00,0.50,270.00,true)                                **
//**    or                                                                             **
//**    - cann KBS_BeginEx(target,15.00,0.50,270.00,&quot;Your\\Effect.mdl&quot;,true)           **
//**                                                                                   **
//**    This will cause the target unit of a spell to be knocked back 15.00 range      **
//**    every interval, with a 0.50 decrease in speed (so 15.00 then 14.50 then 14.00  **
//**    and so on). It will be knocked back at an angle of 270.00, which I&#039;m pretty    **
//**    sure is south, and it will knock down trees in its path.                       **
//**                                                                                   **
//**    The bottom one of the two will do the exact same as the top, however you are   **
//**    able to choose your own special effect that will be attached to the unit.      **
//**                                                                                   **
//***************************************************************************************


And for GUI, you just do the same thing but in the "custom script" thingo.
 

Flare

Stops copies me!
Reaction score
662
Looks pretty good, can't see any issues, and well-documented, which is nice :)

Could be put into the "TreeCheck" function.
if result == true then KillDestructible.

and make it return false. Always
What's the point in that? There may be greater efficiency, but any improvement will be very scattered, since you're not always going to be sliding into trees - hell, you may not even be sliding near any destructables at all, so 0 improvement in efficiency there, which is just making it extra work for the sake of possibly getting a tiny bit of improvement to efficiency.
 

Trollvottel

never aging title
Reaction score
262
what if a unit is at the border of a cliff and is knocked down? i mean, will it just continue sliding at the ground or fall down while sliding? and what if a unit hits a cliff or destructible? will it bounce correctly or just continue sliding or even stop?
 

Tyman2007

Ya Rly >.
Reaction score
74
Well, if it just destroys all destructables in the way, it will also destroy pathing blockers and some other stuff.

I learned about destroying pathing blockers like that the hard way, or my map just really glitched out... every time...
 

Kenny

Back for now.
Reaction score
202
what if a unit is at the border of a cliff and is knocked down? i mean, will it just continue sliding at the ground or fall down while sliding? and what if a unit hits a cliff or destructible? will it bounce correctly or just continue sliding or even stop?

- The unit will just fall down a cliff and keep going, which may cause problems, but if you use pathing blockers on the cliff edges it would be ok. I had a hard time detecting terrain height changes without and bugs occuring so i scratched that idea.

- If it hits a cliff or destructable it will just keep going, just not through it, kind of around it. To see the effect, just turn off destroying trees and that will be the same thing that will happen when coming on contact with destructables and walls/cliffs.

- I wasnt sure whether or not to make the unit stop when hitting a destructable, because then it would bring other issues up. Like hitting a destructable head on will cause a unit to stop, however if it happens at an angle the unit should bounce or something, which would make the system more complicated, and i wouldn't know how to do it.

Although, any ideas on how to improve this would be greatly appreciated, and all comments are welcomed, and thanks for the feedback so far.
 

emjlr3

Change can be a good thing
Reaction score
395
just a thought - if a tree was invuln, why would it get destroyed?

aside from that, an option to allow movement during the slide would be nice, as would a function to check for cliffs (and an option to allow or not allow knocking off cliffs/being stopped at walls)

Emjlr3's on the other hand, is more advanced, using friction and gravity and physics stuff, which a lot of people do not understand. Also the last time I checked his system, it didn't even knock down trees, even though it said it would.

mine is a halted WIP and should not be used, it was more of a proof of concept that I never finished

I see no reason not to approve this if the above is addressed - ti will then be far more robust then Ubers, and mine doesn't even count
 

Kenny

Back for now.
Reaction score
202
just a thought - if a tree was invuln, why would it get destroyed?

Haha, i've never thought of that, i'll give it a try and see wot happens.

an option to allow movement during the slide would be nice, as would a function to check for cliffs (and an option to allow or not allow knocking off cliffs/being stopped at walls)

- So your saying independent movement, so the user can kinda of drag the unit to the side while it is being knocked back? If so, I've always found that to give an undesired effect.

- As for the function to check for cliffs and walls, I would love that to be part of the system, however i cant seem to successfully make it work. And if i check for terrain height changes i dont like how it can bug with terrain deformation.

Any pointers by anyone on how to do it properly would be good. Maybe that would be a good little snippet to submit...*hint*

Oh and thanks for the comment.

*EDIT*

Okay, so basically as long as a tree is actually targeted as a tree, it will be destroyed if that's what you want, otherwise it will not be recognised as a tree by the filter.
 

emjlr3

Change can be a good thing
Reaction score
395
about the trees - all I am saying is that you check whether the "tree" is indestructable or not, if it is, you make it not so, then return it to its initial state (doubt it would get destroyed if its indestructable anyway, thats kind of the point) - if the map creator made someting indestructable, I doubt he wants it killed, ever

So your saying independent movement, so the user can kinda of drag the unit to the side while it is being knocked back? If so, I've always found that to give an undesired effect.

its a simple addition, ppl may want to allow units to move during certain or all knockbacks, you claim more options, well, add them

As for the function to check for cliffs and walls, I would love that to be part of the system, however i cant seem to successfully make it work. And if i check for terrain height changes i dont like how it can bug with terrain deformation.

Vex has some system with items, but I could never make it work - what I do is simple compare the units current Z Height with that of a location say, 100 or 150 distance in the direction hes going to move - if its < or > 30 or so difference, its probably a cliff/wall, respectively

with that said - if ppl dont want a KB to destroy trees, they probably don't want it sliding around trees either (I wouldn't, and it looks ugly) - therefore, perhaps you may want to think about stopping units if they hit trees as well, if they don't knock them down tha tis
 

Kenny

Back for now.
Reaction score
202
Allowing units to move is done, however i wont be updating this until i find a good way to stop the KB if a unit comes in contact with a tree when the user doesnt want trees to be knocked down. And then if i get that i may try for detecting terrain heights using Z heights, which at the moment is easier for me then the tree thing.

Best way i can think of now is changing the boolean for knocking down trees to a real. Then using a positive real to knock down trees and a negative real if you dont want them to be knocked down and 0 if you dont want either, which i think isnt a bad idea, seeing as there are 3 things to choose from.

However, as always, other ideas on the matter are welcome.

*EDIT*

Okay so here is the updated version of the system so far.

What I've done:
- Now allows the player to specify if the unit can move while sliding.
- Fix the TreeFilter() so that it does not knock down invulnerable trees.
- Completely re-worked how trees are filtered and destroyed. Instead of a boolean Killtrees, there is now a real Area. Basically positive numbers (such as 150.00) will create a radius in which trees will be destroyed, while negative numbers (such as -150.00) will create a radius in which the unit will be stopped if a tree enters it. And if the user inputs a 0 (0.00) then it will do neither and just kind of "bounce" off the trees and continue. For a better understanding try it out.

JASS:
library KBS initializer Init
//***************************************************************************************
//**                                                                                   **     
//**    Knockback System (KBS)                                    **By kenny!**        **
//**    v 1.00                                                                         **
//**                                                                                   **
//**    A system I made that can be used for knockback spells in a variety of          **
//**    applications in a map. User defined variables make it easy to give the desired **
//**    effect for any spell.                                                          **
//**                                                                                   **
//**    Requires:                                                                      **
//**        - A vJASS preprocessor (NewGen Pack).                                       **
//**        - No other systems.                                                        **
//**        - A dummy unit. This rarely changes in most maps though. (&#039;h000&#039;)          **
//**        - The special effects found in the import/export section of this map.       **
//**          They are the &quot;Dust.mdx&quot; and the &quot;SlideWater.mdx&quot;. Or you can use your    **
//**          own if you have some.                                                    **
//**                                                                                   **
//***************************************************************************************

//***************************************************************************************
//**                                                                                   **
//**    Other Information:                                                             **
//**        - Angle is taken in degrees. But can easily be changed if you know how.    **
//**        - Units will be stopped if they hit the map borders.                       **
//**        - Remember to import the special effect into your map if you need them.    **
//**        - There are two functions that can be used in this system.                 **
//**                                                                                   **
//**    Sliding Distances:                                                             **
//**        - This is some general knowledge on the different distances and how to     **
//**          get them.                                                                **
//**        - A small knockback, such as one used for a bash would be around 15.00 for **
//**          the Startspeed and 0.50 for the deceleration.                            **
//**        - 25.00-30.00 for Startspeed with 0.50 would give a knockback for a small  **
//**          stomp spell of sorts.                                                    **
//**        - 62.50 Startspeed with a 1.5625 deceleration would give a very long       **
//**          knockback which is also quite fast.                                      **
//**                                                                                   **
//**    NOTE: This is all with an interval of 0.04, which is recommended. This is      **
//**          25 intervals per second.                                                 **
//**                                                                                   **
//***************************************************************************************

//***************************************************************************************
//**                                                                                   **
//**    Implementation:                                                                **
//**        - First off you need the NewGen world editor. This is a must.              **
//**        - Copy this trigger into your map. Or make a trigger in your map and       **
//**          convert it to custom text. Then copy this text into that trigger.        **
//**        - Now you will either need to export the special effects from this map to  **
//**          your map, or you will need your own. I do not take credit for the        **
//**          special effects found in this map.                                       **
//**        - Once you have the effects in your map. Find the configuration block      **
//**          that is underneath all this green text. Change the Water_sfx and the     **
//**          Dirt_sfx strings to the ones in your map. These should be the same if    **
//**          you exported the ones from this map.                                     **
//**        - Make sure you have the dummy unit needed. It can be any unit, but i      **
//**          suggest you use the one found in this map, it is labelled &#039;Dummy Unit&#039;   **
//**          or &#039;u001&#039;.                                                               **
//**        - Your done! Save your map, make a spell using this system and try it out. **
//**                                                                                   **
//**    NOTE: Please report any bugs to me at thehelper.net via PM. (User name: kenny!)**
//**                                                                                   **
//***************************************************************************************
                                                                           
//***************************************************************************************
//**                                                                                   **
//**    Usage:                                                                         **
//**                                                                                   **
//**             call KBS_Begin(Target,Startspeed,Deceleration,Angle,Area)             **
//**                                       or                                          **
//**call KBS_BeginEx(Target,Startspeed,Deceleration,Angle,Specialeffect,Area,Allowmove)**
//**                                                                                   **
//**    - Target        - The unit that will be used in the knockback.                 **
//**    - Startspeed    - The initial speed at which the unit will be knocked back.    **                 
//**    - Deceleration  - The deceleration of the unit. Slows the unit down over       **
//**                      the duration of the knockback.                               **
//**    - Angle         - The angle that the unit will be knocked back at.             **
//**                      THIS MUST BE IN DEGREES. &lt;- Easier for GUI users.            **
//**    - Specialeffect - This is only used in the extended function. If you do not    **
//**                      want one of the predefined effects, you can choose your own. **
//**                      However, this effect is attached to the unit and removed at  **
//**                      the end, so non-looping or repeating effect wont work.       **
//**    - Area          - This determines whether or not trees will be knocked down.   **
//**                      For trees to be knocked down, a positive number (real) must  **
//**                      be used, such as 150.00, which would give a radius of 150.00 **
//**                      in which trees will be knocked down.                         **
//**                      For trees to not be knocked down, a negative number (real)   **
//**                      must be used, such as -150.00, which would create a radius   **
//**                      that if a tree comes within it, the unit will stop moving.   **
//**                      For none of those effects, the number 0 (0.00) can be used.  **
//**                      This will just cause the units to &quot;bounce&quot; off trees.        **
//**    -Allowmove      - This boolean will decided whether or not you want the unit   **
//**                      to have the ability to move while being knocked back.        **
//**                      &quot;true&quot; will allow them to move, while &quot;false&quot; will not.      **
//**                                                                                   **
//**       REMEMBER: Positive = trees destroyed, Negative = trees not destroyed.       **
//**                                                                                   **
//**    Example of Usage:                                                              **
//**                                                                                   **
//**    - call KBS_Begin(target,15.00,0.50,270.00,150.00)                              **
//**    or                                                                             **
//**    - call KBS_BeginEx(target,15.00,0.50,270.00,&quot;Your\\Effect.mdl&quot;,-150.00,true)   **
//**                                                                                   **
//**    This will cause the target unit of a spell to be knocked back 15.00 range      **
//**    every interval, with a 0.50 decrease in speed (so 15.00 then 14.50 then 14.00  **
//**    and so on). It will be knocked back at an angle of 270.00, which I&#039;m pretty    **
//**    sure is south, and it will knock down trees within a 150.00 radius around the  **
//**    unit.
//**                                                                                   **
//**    The bottom one of the two will do the exact same as the top, however you are   **
//**    able to choose your own special effect that will be attached to the unit. As   **
//**    you can see, the number for Area (destroying trees) is negative, therefore     **
//**    no trees will be knocked down, and the unit will stop moving if it comes in    **
//**    contact with a tree. There is also an extra boolean at the end, this is for    **
//**    allowing units to move while sliding. It is true, meaning units are allowed.   **
//**                                                                                   **
//***************************************************************************************

globals
    // CONFIGURABLES:
    private constant integer Dummy_id = &#039;h000&#039;           // This is the dummy unit.
    private constant real Period = 0.04                  // Recommended Interval.
    private constant real Radius = 150.00                // Radius for killing trees.
    private constant string Attachment_point = &quot;origin&quot;  // Attachment point for effects.
    private constant string Water_SFX = &quot;SlideWater.mdx&quot; // Water slide effect.
    private constant string Dirt_SFX = &quot;Dust.mdx&quot;        // Ground slide effect.
endglobals

//***************************************************************************************
//**                                                                                   ** 
//**          DO NOT TOUCH BELOW HERE UNLESS YOU KNOW WHAT YOUR ARE DOING!             **
//**                                                                                   **
//***************************************************************************************     

private keyword Data

globals
    private integer Total = 0
    private Data array DataArray
    private real Game_maxX = 0.00
    private real Game_minX = 0.00
    private real Game_maxY = 0.00
    private real Game_minY = 0.00
    private rect Rect1 = null
    private timer Timer = null
    private boolexpr Treefilt = null
    private boolean array BA
endglobals

// Used to destroy destructables.
private function KillEnumDestructables takes nothing returns nothing
    if BA[0] then
        call KillDestructable(GetEnumDestructable())
    else
        set BA[1] = true
    endif
endfunction

// Thanks to PitzerMike for this function. (Modified Slightly).
private function TreeCheck takes nothing returns boolean
    local destructable dest = GetFilterDestructable()
    local unit dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE),Dummy_id,GetDestructableX(dest),GetDestructableY(dest),0.00)
    local boolean result = false

    call UnitAddAbility(dummy,&#039;Ahrl&#039;)
    set result = IssueTargetOrder(dummy,&quot;harvest&quot;,dest)
    call RemoveUnit(dummy)

    set dest = null
    set dummy = null
    return result
endfunction

// Checks if a point is on the map boundaries.
private function IsPointOutside takes real x, real y returns boolean
    return (x &gt; Game_maxX or y &gt; Game_maxY or x &lt; Game_minX or y &lt; Game_minY)
endfunction

private struct Data
    unit targ
    
    real speed
    real decrease
    real sin
    real cos
    real radius
    
    effect SFX
    integer sfxmode
    boolean allowmove
    
    // Checking for terrain type.
    static method TerrainType takes unit u, string sfx returns integer
        local real x = GetUnitX(u)
        local real y = GetUnitY(u)
        
        if sfx != &quot;&quot; and sfx != null then
            return 0
        elseif IsTerrainPathable(x,y,PATHING_TYPE_FLOATABILITY) then
            return 1
        elseif not IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY) then
            return 2
        endif
        
        return 3
    endmethod
    
    static method create takes unit Target, real Startspeed, real Deceleration, real Angle, string Specialeffect, real Area, boolean Allowmove returns Data
        local Data d = Data.allocate()
        
        // Allocates struct members to user defined variables.
        set d.targ = Target
        set d.speed = Startspeed
        set d.decrease = Deceleration
        set d.sin = Sin(Angle)
        set d.cos = Cos(Angle)
        set d.radius = Area
        set d.allowmove = Allowmove
        set d.sfxmode = d.TerrainType(d.targ,Specialeffect)
        
        // Adding effects to the unit.
        if d.sfxmode == 0 then
            set d.SFX = AddSpecialEffectTarget(Specialeffect,d.targ,Attachment_point)
        elseif d.sfxmode == 1 then
            set d.SFX = AddSpecialEffectTarget(Dirt_SFX,d.targ,Attachment_point)
        elseif d.sfxmode == 2 then
            set d.SFX = AddSpecialEffectTarget(Water_SFX,d.targ,Attachment_point)
        endif
        
        return d
    endmethod
    
    private method onDestroy takes nothing returns nothing
        set .targ = null
        call DestroyEffect(.SFX) // Destroys effects if needed.
        set .SFX = null
        set BA[0] = false
        set BA[1] = false
    endmethod
endstruct

private function Execute takes nothing returns nothing
    local integer i = 1
    local Data d = 0
    local real x = 0.00
    local real y = 0.00
    local real newx = 0.00
    local real newy = 0.00
    local integer newmode = 0
        
    loop
        exitwhen i &gt; Total
        set d = DataArray<i>
        set newmode = d.sfxmode
       
        set x = GetUnitX(d.targ)
        set y = GetUnitY(d.targ)
        
        // Destroys trees if wanted, or stops the unit  &lt;------------------------ New
        if d.radius != 0.00 then
            set BA[0] = d.radius &gt; 0.00

            call SetRect(Rect1,x-d.radius,y-d.radius,x+d.radius,y+d.radius)
            call EnumDestructablesInRect(Rect1,Treefilt,function KillEnumDestructables)
        endif
         
        if d.speed &lt;= 0 or IsPointOutside(x,y)or BA[1] then
            call d.destroy() // Finish knockback if speed == 0 or unit has hit map borders.
            set DataArray<i> = DataArray[Total]
            set Total = Total - 1
            set i = i - 1
        else
            set newx = x+d.speed*d.cos
            set newy = y+d.speed*d.sin
            
            // Allows unit to move while sliding, if specified. &lt;--------------------------- New.
            if d.allowmove then
                call SetUnitX(d.targ,newx)
                call SetUnitY(d.targ,newy)
            else
                call SetUnitPosition(d.targ,newx,newy)
            endif
                
            if d.sfxmode == 0 then
                set d.sfxmode = d.TerrainType(d.targ,&quot;sfx&quot;)
            else
                set d.sfxmode = d.TerrainType(d.targ,&quot;&quot;) // Checks for pathing again.
            endif
                
            // Adds special effects.
            if d.sfxmode == 1 and newmode == 2 then
                call DestroyEffect(d.SFX)
                set d.SFX = AddSpecialEffectTarget(Dirt_SFX,d.targ,Attachment_point)
            elseif d.sfxmode == 2 and newmode == 1 then
                call DestroyEffect(d.SFX)
                set d.SFX = AddSpecialEffectTarget(Water_SFX,d.targ,Attachment_point)
            endif
                
            set d.speed = d.speed - d.decrease // Sets new speed.
        endif
            
        set i = i + 1
    endloop
    if Total &lt;= 0 then
        call PauseTimer(Timer)
        set Total = 0
    endif
endfunction

//***************************************************************************************
//** Only two functions used by this system. KBS_BeginEx and KBS_Begin.                **
public function BeginEx takes unit Target, real Startspeed, real Deceleration, real Angle, string SpecialEffect, real Area, boolean Allowmove returns boolean
    local Data d = 0
    
    if Target == null or Startspeed &lt;= 0.00 or Deceleration &lt;= 0.00 then
        call BJDebugMsg(&quot;Error: Invalid input in KBS_Begin(Ex)&quot;) // Error message.
        return false
    endif
    set d = Data.create(Target,Startspeed,Deceleration,(Angle*0.01745328),SpecialEffect,Area,Allowmove)
    set Total = Total + 1
    if Total == 1 then
        call TimerStart(Timer,Period,true,function Execute) // Starting timer.
    endif
    set DataArray[Total] = d
    
    return true
endfunction
//**                                                                                   **
public function Begin takes unit Target, real Startspeed, real Deceleration, real Angle, real Area returns nothing    
    call BeginEx(Target,Startspeed,Deceleration,Angle,&quot;&quot;,Area,false)
endfunction                                                                                                
//**                                                                                   **
//***************************************************************************************

// Sets map boundries and sets timer, rect and filter.
private function Init takes nothing returns nothing
    set Timer = CreateTimer()
    set Rect1 = Rect(0.00,0.00,1.00,1.00)
    set Treefilt = Condition(function TreeCheck)
    set Game_maxX = GetRectMaxX(bj_mapInitialPlayableArea)-64.00
    set Game_maxY = GetRectMaxY(bj_mapInitialPlayableArea)-64.00
    set Game_minX = GetRectMinX(bj_mapInitialPlayableArea)+64.00
    set Game_minY = GetRectMinY(bj_mapInitialPlayableArea)+64.00
    set BA[0] = false
    set BA[1] = false
endfunction

endlibrary</i></i>


I would like someone to take a quite look and see if it actually works as intended, as i have already done some testing and can find nothing wrong with it, but a second opinion cant hurt.

If everything is fine, i will be updating the test map and first post with the new version.
 

Kenny

Back for now.
Reaction score
202
Bump. Still looking for a second opinion, just to see if everything is in order.
 

emjlr3

Change can be a good thing
Reaction score
395
changelog doesnt seem very effective when left blank
 

Kenny

Back for now.
Reaction score
202
changelog doesnt seem very effective when left blank

My bad, i thought i would have time to do this, but i was wrong, I've been kinda busy.

Anywho, the update is here.

Version 2.00:

- New method of knocking down trees. Now uses a real value instead of boolean. Read green block of writing in the code for more information.

- Added an option to allow the player to move the knocked back unit while it's sliding.

- Added an option to check terrain height changes and stop the unit accordingly. Its pretty sketchy but it gets the job done in most maps. However it has problems when there are large/steep hills in the map.

- Some other coding changes to increase efficiency and stuff.

Download the map, give it a try and tell me what you think. Feedback and criticism is welcomed.
 

black.sheep

Active Member
Reaction score
24
Hmm, question, could you make a stopknockback function? To stop a unit from being knockbacked? Also a check if unit is being knockbacked would be kewl too.
 

Kenny

Back for now.
Reaction score
202
Hmm, question, could you make a stopknockback function? To stop a unit from being knockbacked? Also a check if unit is being knockbacked would be kewl too.

Um yes i could, it isn't too hard really. However they are already part of another knockback system, which i have been told is fairly similar to mine, probably better too :p. So i probably wont do it, just to ensure each of our systems still stay unique. I think this system can be found on www.wc3campaigns.net under code or system resources or something.
 

Viikuna

No Marlo no game.
Reaction score
265
You are leaving something out, because someone else already has that something? And because what? You want it to stay "unique" ??

Jesus..

People who need knockback systems are ( as far as I know ) those GUI users who have troubles with making a good knockback, so why dont you just focus on making this a good easy to use system which has all the functions they need?
 

CaptDeath

New Member
Reaction score
103
does it lag id u hit like 50 units?
cause i was playing COD and i hit like 50 units near simultaniously and the game crashed not even an error like it closed it self
and will this do the same thing?
 
General chit-chat
Help Users
  • No one is chatting at the moment.

      The Helper Discord

      Staff online

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top