HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Knockback pathing

07-04-2009, 10:33 PM#1
cokemonkey11
Hey there, I'm making a knockback trigger for a speed map of mine and I could swear I've seen a trigger about how to check if a unit will be blocked. Right now units get knocked back straight through trees.

IIRC the thread had some way of placing an item and then checking if it was still in the placed position, so I tried that and it borked (so I commented it out).

My other question is, how do I properly make units 'bounce' off edges? Right now I just do set direction=direction+180, which doesn't exactly work correctly.

Here's the code:

Collapse JASS:

globals
    trigger tDDKB
    //item iChecker=CreateItem('shwd',1,-325)
endglobals

scope damageDetectedKnockback initializer i
    private struct kData
        unit u
        real direction
        integer power
    endstruct
    
    globals
        private timer time=CreateTimer()
        private kData array kDB
        private integer dbIndex=-1
    endglobals
    
    //private function CheckLoc takes real x, real y returns boolean
        //call SetItemPosition(iChecker,x,y)
        //call SetItemVisible(iChecker,true)
        //if GetItemX(iChecker)==x and GetItemY(iChecker)==y then
            //call SetItemVisible(iChecker,false)
            //return true
        //endif
        //call SetItemVisible(iChecker,false)
        //return false
    //endfunction
    
    private function p takes nothing returns nothing
        local integer index=0
        local kData tempDat
        local real x
        local real y
        loop
            exitwhen index>dbIndex
            set tempDat=kDB[index]
            set x=GetUnitX(tempDat.u)+tempDat.power*Cos(tempDat.direction*bj_DEGTORAD)
            set y=GetUnitY(tempDat.u)+tempDat.power*Sin(tempDat.direction*bj_DEGTORAD)
            if IsTerrainPathable(x,y,PATHING_TYPE_WALKABILITY)==false then // and CheckLoc(x,y) then
                call SetUnitX(tempDat.u,x)
                call SetUnitY(tempDat.u,y)
            else
                set tempDat.direction=tempDat.direction+180
                set tempDat.power=tempDat.power*3/4
            endif
            set tempDat.power=tempDat.power-1
            if GetUnitState(tempDat.u,UNIT_STATE_LIFE)<1 then
                set tempDat.power=tempDat.power-1
            endif
            if GetUnitMoveSpeed(tempDat.u)<270 then
                set tempDat.power=tempDat.power-1
            endif
            if tempDat.power<0 then
                call tempDat.destroy()
                set kDB[index]=kDB[dbIndex]
                set dbIndex=dbIndex-1
                if dbIndex==-1 then
                    call PauseTimer(time)
                endif
            endif
            set index=index+1
        endloop
    endfunction
    
    private function a takes nothing returns nothing
        local kData tempDat
        local unit source=GetEventDamageSource()
        local unit target=GetTriggerUnit()
        local location lS=GetUnitLoc(source)
        local location lT=GetUnitLoc(target)
        local real direction=AngleBetweenPoints(lS,lT)
        local real power=15+GetEventDamage()/2
        if power>65 then
            set power=65
        endif
        if GetUnitTypeId(source)=='hrif' or GetUnitTypeId(source)=='hgyr' or GetUnitTypeId(source)=='hgry' or GetUnitTypeId(source)=='hdhw' then
            set power=power/2
        endif
        if IsUnitType(target,UNIT_TYPE_FLYING)!=true and IsUnitType(target,UNIT_TYPE_STRUCTURE)!=true then
            set tempDat=kData.create()
            set tempDat.u=target
            set tempDat.direction=direction
            set tempDat.power=R2I(power)
            set dbIndex=dbIndex+1
            set kDB[dbIndex]=tempDat
            if dbIndex==0 then
                call TimerStart(time,.03,true,function p)
            endif
        endif
        call RemoveLocation(lS)
        call RemoveLocation(lT)
    endfunction
    
    private function i takes nothing returns nothing
        set tDDKB=CreateTrigger()
        call TriggerAddAction(tDDKB,function a)
    endfunction
endscope


Thanks,
07-04-2009, 11:10 PM#2
Anitarf
You mean this?

Bouncing is more tricky, though. You need to consider the possibility of bouncing off unpathable terrain as well as destructables, which makes the code kind of long and complicated.
07-05-2009, 12:35 AM#3
cokemonkey11
Yes! That's what I was looking for. Thanks much.

I just want the unit to bounce properly regardless of what's stopped it (in the else after it was checked for walkability, I want it to bounce regardless of what stopped it)

Could you show me the math I would use?
07-05-2009, 12:45 AM#4
Anitarf
Last time I did something like this was over three years ago. Aside from terrible amounts of gamecache usage, the principles of that spell should still be useful.