HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Most Stable-Multiinstance-FillInTheBlank-Knockback Script You Know Of?

11-22-2007, 07:30 PM#1
Brash
I'm in trouble. I have made knockback triggers before for one player in gui and have also tried toying with scripts others have made for moving units around circles.. but i dont know if i can handle this one.. because i need to make a trig that knockbacks a unit with a buff anywhere's from one to several (maybe hundreds) of these little units around until they bump into something.. and then are to be ordered to die.


heh

So i was wondering if any of you know of either a way to do this or know of a simple script i can copy, paste and edit easily that is totally multi-instance and is leak-free.

it's a 10 player map. as each player walks up to one of these little units, they can target it with a spell (or maybe some other way) and the unit will instantly move away from them.
so since there are many players and many of these little units.. i need this to be able to handle the possibility of a bunch of units being kicked around at a time independantly.

example: i kick the one critter.. and whle that is flying at my opponent, i may kick another one before the other finishes and player 2 might also kick a few during that time.

Thank you for your time.
11-22-2007, 07:44 PM#2
TEC_Ghost
Here's my Knockback script. You just call the knockback function and enter whatever values you want and you're good to go.

Sorry it isn't more documented / commented, wasn't planning on anyone else figuring it out :P if you need help with it let me know.
Hidden information:
Collapse JASS:
library KnockBackLib


//===============================================================MISC PATHABILITY FUNCTIONS
function CheckPathabilityTrickGet takes nothing returns nothing
    set bj_rescueChangeColorUnit = bj_rescueChangeColorUnit or (GetEnumItem()!=bj_itemRandomCurrentPick)
endfunction

function CheckPathabilityTrick takes item p, real x, real y returns boolean
    local integer i=30
    local rect r
    call SetItemPosition(p,x,y)
    if ((Pow(GetItemX(p)-x,2)+Pow(GetItemY(p)-y,2))<=100) then
        return true
    endif
    set r=Rect(x-i,y-i,x+i,y+i)
    set bj_itemRandomCurrentPick=p
    set bj_rescueChangeColorUnit=false
    call EnumItemsInRect(r,null,function CheckPathabilityTrickGet)
    call RemoveRect(r)
    set r=null
    return bj_rescueChangeColorUnit
endfunction

function CheckPathability takes real x, real y returns boolean
    local item it = CreateItem('ciri',x,y)
    local boolean b = CheckPathabilityTrick(it,x,y)
    call SetItemVisible(it,false)
    call RemoveItem(it)
    set it=null
    return b
endfunction

function Knockback_TreeFilter takes nothing returns boolean
    local integer d = GetDestructableTypeId(GetFilterDestructable())
    return d == 'ATtr' or d == 'BTtw' or d == 'KTtw' or d == 'YTft' or d == 'JTct' or d == 'YTst' or d == 'YTct' or d == 'YTwt' or d == 'JTwt' or d == 'JTwt' or d == 'FTtw' or d == 'CTtr' or d == 'ITtw' or d == 'NTtw' or d == 'OTtw' or d == 'ZTtw' or d == 'WTst' or d == 'LTlt' or d == 'GTsh' or d == 'Xtlt' or d == 'WTtw' or d == 'Attc' or d == 'BTtc' or d == 'CTtc' or d == 'ITtc' or d == 'NTtc' or d == 'ZTtc'
endfunction
//====================================================================================


//=================STRUCT DECLARE
struct Knockback_Data
    unit u
    real d1
    real d2

    real sin
    real cos

    real r

    string s = ""
    effect e = null
endstruct
//=============================

//================Global Blocks====
globals
    timer Tim = CreateTimer()
    Knockback_Data array Ar
    integer Total = 0
    integer Totalmove = 0
    real Intervalr = .04
endglobals
//==============================


//=================Timer Interval===
constant function Interval takes nothing returns real
    return 0.04
endfunction
//===============================



//====Kills trees when you hit them
function Knockback_KillTree takes nothing returns nothing
    call KillDestructable(GetEnumDestructable())
endfunction
//====


//==================Knockback Execution===========
function Knockback_Execute takes nothing returns nothing
    local Knockback_Data kd
    local integer i = 0
    local real x
    local real y
    local rect r
    local boolexpr b


    loop
        exitwhen i >= Total
        set kd = Ar[i]

        if kd.s != null and kd.s != null then
            set x = GetUnitX(kd.u)
            set y = GetUnitY(kd.u)

            call DestroyEffect(AddSpecialEffect(kd.s, x, y))

            set x = x + kd.d1 * kd.cos
            set y = y + kd.d1 * kd.sin
        else

        set x = GetUnitX(kd.u) + kd.d1 * kd.cos
        set y = GetUnitY(kd.u) + kd.d1 * kd.sin

        endif

        if kd.r != 0 then
            set r = Rect(x - kd.r, y - kd.r, x + kd.r, y + kd.r)
            set b = Filter(function Knockback_TreeFilter)
            call EnumDestructablesInRect(r, b, function Knockback_KillTree)
            call RemoveRect(r)
            call DestroyBoolExpr(b)
        endif


       if CheckPathability(x, y) then
        call SetUnitX(kd.u, x)
        call SetUnitY(kd.u, y)
       endif


        set kd.d1 = kd.d1 - kd.d2

        if kd.d1 <= 0 or not CheckPathability(x, y) then
            if kd.e != null then
                call DestroyEffect(kd.e)
            endif
            call PauseUnit(kd.u, false)
            set Ar[i] = Ar[Total - 1]
            set Total = Total - 1
            call kd.destroy()
        endif


        set i = i + 1
    endloop

    if Total == 0 then
        call PauseTimer(Tim)
    endif
endfunction
//======================================

//========================Knockback Function you will call to trigger the knockback
function Knockback takes unit u, real d, real a, real w, real r, integer t, string s, string p returns nothing
    local Knockback_Data kd = Knockback_Data.create()

    local integer q = R2I(w / Interval())

    set kd.u = u
    set kd.d1 = 2 * d / (q + 1)
    set kd.d2 = kd.d1 / q

    set kd.sin = Sin(a)
    set kd.cos = Cos(a)

    set kd.r = r

    if s != "" and s != null then
        if t == 2 then
            if p != "" and p != null then
                set kd.e = AddSpecialEffectTarget(s, u, p)
            else
                set kd.e = AddSpecialEffectTarget(s, u, "chest")
            endif
        elseif t == 1 then
            set kd.s = s
        endif
   endif


call SetUnitPosition(u, GetUnitX(u), GetUnitY(u))
call PauseUnit(u, true)

    if Total == 0 then
        call TimerStart(Tim, Interval(), true, function Knockback_Execute)
    endif

    set Total = Total + 1
    set Ar[Total - 1] = kd

endfunction
//==========================END KNOCKBACK


endlibrary
11-22-2007, 09:53 PM#3
MaD[Lion]
or u could always use my system, but nvm it now :P
11-23-2007, 12:12 AM#4
Pyrogasm
Actually, Silvenon made a tutorial for this very thing. I think you will find it to be rather useful: Coding an Efficient Knockback (vJASS)
11-23-2007, 12:28 AM#5
Brash
Quote:
Originally Posted by TEC_Ghost
You just call the knockback function and enter whatever values you want and you're good to go.

thanks a lot. i will give it a try.

How do you mean call it? you mean have another trig set up to tell it when to launch? or something in the map script to set it up?

i'm rather a noob at jassing, though i've had some successful moments with small amounts of script. also been a few months away from comp.

so, if i had a hero with a certain ability that casts on another unit to be knocked back, what things do i change in this?
11-23-2007, 03:27 AM#6
TEC_Ghost
Yup, make a new trigger and copy/paste that library, then when you want to use the knock back have whatever conditions on a new trigger then run the function. Here's the function.

Collapse JASS:
function Knockback takes unit u, real d, real a, real w, real r, integer t, string s, string p returns nothing

So you'd supply the info like...

Collapse JASS:
call Knockback(GetEnumUnit(), 400, AngleBetweenPoints(GetUnitLoc(GetTriggerUnit()), GetUnitLoc(GetEnumUnit()))*0.01745, 4, 90, 0, "", "")

Pretty much I'm giving Unit,Distance,Angle they travel,Time you want them to travel,collision size,type of special effect to add to the 0 = none 1 = entered string 2 = chest, special effect name, where to attach it if entered 1.
11-23-2007, 07:08 AM#7
grim001
Stop using Vexorian's pathability check script people, that thing is years old and will lag like hell if you're moving "hundreds of units"
11-23-2007, 08:43 AM#8
Silvenon
Quote:
Originally Posted by grim001
Stop using Vexorian's pathability check script people, that thing is years old and will lag like hell if you're moving "hundreds of units"

Not if it's modified to move a single global item instead of creating one each time (thanks to you and Pyrogasm I managed to fix it).

Quote:
Originally Posted by TEC_Ghost
Here's my Knockback script.

I'm glad that my tut has actually helped someone.
11-23-2007, 09:16 AM#9
grim001
It's still using a null boolexpr and doesn't detect collisions with other units (only unpathable terrain), and could be easily inlined if all of the wasted operations were removed
11-23-2007, 09:30 AM#10
Toadcop
Quote:
Originally Posted by grim001
Stop using Vexorian's pathability check script people, that thing is years old and will lag like hell if you're moving "hundreds of units"
if you use SetUnitPosition() it's anyway laggy =)
(to move unit in such way takes more time than calc all the math for (particle or something) movement)
it's a pure perf killer
GetLocationZ() is also a weak point in algorithms (it's doesnt have "constant" calc rate)
11-23-2007, 07:10 PM#11
Silvenon
Quote:
It's still using a null boolexpr and doesn't detect collisions with other units (only unpathable terrain), and could be easily inlined if all of the wasted operations were removed

Why don't you write the code then? (Yes, this is an excuse so you can make me a better function )
11-23-2007, 07:21 PM#12
Pyrogasm
He wrote a very good collision detection algorithm used in this code that creates a shockwave that bounces from unit-to-unit and dies if it hits too steep terrain or a destructable... if you want to decipher it:
Expand JASS:
11-23-2007, 09:26 PM#13
MaD[Lion]
grim001 is master of collision detection algoritm ^^ at least he have made it to life
11-23-2007, 10:58 PM#14
grim001
Oh god, looking at that code reminds me of how ugly standard JASS is.

that was just a test to see if I could make a shockwave which bounces off terrain, destructables and units while reflecting at the correct angle and knocking back the target as well. turned out to be possible but extremely ugly. that code isn't multi-instancable, though, would need to change it to arrays and add an allocator/deallocator...

Anyway, a long time ago I thought that using a dummy unit and SetUnitPositionLoc was the best way to notice a unit blocking knockback path, but now I would only do it with GroupEnumUnitsInRange.

With that method you could set it up so that some of the knockback force transfers to units that you're knocked into, or you take damage based on the force of collision when you run into a destructable/building/terrain.

Trying to do all of those things using standard knockback scripts is lame though. Might as well go all the way to a physics engine.

Quote:
Originally Posted by Silvenon
Why don't you write the code then? (Yes, this is an excuse so you can make me a better function )
Guess I'll do that tonight just so I can post it every time a knockback thread comes up.
11-24-2007, 01:51 AM#15
Pyrogasm
Quote:
Originally Posted by grim001
that was just a test to see if I could make a shockwave which bounces off terrain, destructables and units while reflecting at the correct angle and knocking back the target as well. turned out to be possible but extremely ugly. that code isn't multi-instancable, though, would need to change it to arrays and add an allocator/deallocator...
That's why I said he could try to decipher it :P