[JASS] Pathability Checker

Status
Not open for further replies.
Level 7
Joined
Mar 24, 2008
Messages
184
So, i made this Pathability Check function for my charge spell, it seems to work fine, except in the case where there are items on the ground. Even though i made a check for items, the checked area is too big but if i reduce it even by 1, it doesn't work anymore in some points...

The problem is if i make an area covered by items, and put a wall in the middle of this items covered area, then it counts the wall as walkable area (in my charge spell, the caster will charge through the walls, which shouldn't happen). I know is a very unlikely to happen situation, but this bug pisses me up :p

I'm posting the code, the pathchecker unit is a dummy unit invulnerable, locusted and with no model, plus it has a permanent windwalk casted on it.
Any idea on how to improve this function?

You can see the function at work here (if you move on the right part of the map i put another hero and an area covered with items just for testing this feature): http://www.hiveworkshop.com/forums/spells-569/vjass-charge-0-92-a-135134/

JASS:
//**************************************************************************
// ** **
// ** Check Pathability Function **
// ** ————————————— **
// ** **
// ** A Function that checks if a unit can walk over a certain area **
// ** (Ignores other units but not buildings, trees and other obstacles) **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************

library Walkable initializer init requires ChargeConfig
    globals
        unit pathchecker
        boolean iteminrect=false
    endglobals
    
    function GetItems takes nothing returns nothing
            set iteminrect = true 
    endfunction

    function IsPointWalkable takes real x, real y returns boolean
        local integer i=65
        local rect r
        local boolean b
        call SetUnitPosition(pathchecker,x,y)
        set b=(RAbs(GetUnitX(pathchecker)-x)<=1) and (RAbs((GetUnitY(pathchecker)-y))<=1) 
        if (b==false) then
            set r=Rect(x-i,y-i,x+i,y+i)
            call EnumItemsInRect(r,null,function GetItems)
            set b=iteminrect
            set iteminrect=false
            call RemoveRect(r)
            set r=null
        endif
        return b
    endfunction

    function init takes nothing returns nothing
        set pathchecker=CreateUnit( Player(PLAYER_NEUTRAL_PASSIVE), PATHCHECKERID, 0, 0, 0)
        call UnitAddAbility(pathchecker, SPELLPATHID)
        call IssueImmediateOrder( pathchecker, "windwalk" )
    endfunction
endlibrary
 
Level 7
Joined
Mar 24, 2008
Messages
184
EDIT: Nah, it doesn't work, i still have that problem...if i set the area too big it can cross some obstacles, if i set it too small it cannot go through the item covered area in some points.

Though it's a very unlikely to happen situation (charging through items) i still would like to make a function that could do that
 
Last edited:
Level 9
Joined
Nov 28, 2008
Messages
704
I have mine, which detects if it is a horizontal wall or vertical, or if your in a corner.. it might help.

JASS:
    function HideItem takes nothing returns nothing
        if IsItemVisible(GetEnumItem()) == true then
            set NumItems = NumItems + 1
            set Items[NumItems] = GetEnumItem()
            call SetItemVisible(Items[NumItems], false)
        endif
    endfunction
    
    function CheckPathability takes real x, real y returns integer
        local real x2
        local real y2
        local boolean CheckX = false
        local boolean CheckY = false
        call MoveRectTo(ItemRect, x, y)
        call EnumItemsInRect(ItemRect, null, function HideItem)
        call SetItemPosition(ItemCheck, x, y)
        call SetItemPosition(ItemCheck, x, GetItemY(ItemCheck))
        set x2 = GetItemX(ItemCheck)
        if x  + CheckLeeway > x2 and x  - CheckLeeway < x2 then
            set CheckX = true
        endif
        call SetItemPosition(ItemCheck, x, y)
        call SetItemPosition(ItemCheck, GetItemX(ItemCheck), y)
        set y2 = GetItemY(ItemCheck)
        if y2 + CheckLeeway > y and y2 - CheckLeeway < y then
            set CheckY = true
        endif
        loop
            exitwhen NumItems < 0
            call SetItemVisible(Items[NumItems], true)
            set NumItems = NumItems - 1
        endloop
        call SetItemPosition(ItemCheck, x, y)
        call SetItemVisible(ItemCheck, false)
        if CheckX == false and CheckY == false then
            return 3
        elseif CheckX == false then
            return 2
        elseif CheckY == false then
            return 1
        endif
        return 0
    endfunction

Looking it over, I forgot to include variables.. oh well. Check leeway is 45.0, and the item rect is about 100 x 100.

I don't know if it helps you, but it is a method of doing it *shrug*.

3 means your in a corner, 2 means your on a vertical, N to S) wall, 1 means a horizontal (9W to E) and 0 means it is pathable.
 
Level 9
Joined
Nov 28, 2008
Messages
704
Then hide the item with a simple EnumItemsInRect. My code up there actually has that :). It is just missing the actual declaration of the item rect and item array.
 
Level 7
Joined
Mar 24, 2008
Messages
184
Yes, the problem is your code does unnecessary things for me :). i used your approach with my function, and i ended up with this:

JASS:
// **************************************************************************
// ** **
// ** Check Pathability Function **
// ** ————————————— **
// ** **
// ** A Function that checks if a unit can walk over a certain area **
// ** (Ignores other units but not buildings, trees and other obstacles) **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************

library Walkable initializer init requires ChargeConfig
    globals
        unit pathchecker
    endglobals
    
    function HideItems takes nothing returns nothing
        call SetItemVisible(GetEnumItem(), false)    
    endfunction
    
    function UnHideItems takes nothing returns nothing
        call SetItemVisible(GetEnumItem(), true)    
    endfunction
    
    function IsPointWalkable takes real x, real y returns boolean
        local real i=100
        local rect r
        local boolean b
        call SetUnitPosition(pathchecker,x,y)
        set b=(RAbs(GetUnitX(pathchecker)-x)<=1) and (RAbs((GetUnitY(pathchecker)-y))<=1) 
        if (b==false) then
            set r=Rect(x-i,y-i,x+i,y+i)
            call EnumItemsInRect(r,null,function HideItems)
            call SetUnitPosition(pathchecker,x,y)
            set b=(RAbs(GetUnitX(pathchecker)-x)<=1) and (RAbs((GetUnitY(pathchecker)-y))<=1) 
            call EnumItemsInRect(r,null,function UnHideItems)
            call RemoveRect(r)
            set r=null
        endif
        return b
    endfunction

    function init takes nothing returns nothing
        set pathchecker=CreateUnit( Player(PLAYER_NEUTRAL_PASSIVE), PATHCHECKERID, 0, 0, 0)
        call UnitAddAbility(pathchecker, SPELLPATHID)
        call IssueImmediateOrder( pathchecker, "windwalk" )
    endfunction
endlibrary

I still rather a unit with windwalk rather than an item as path checker since it's more precise, though more sensitive...but i rather the charge being stopped by the most little obstalce rather than going through wall corners :) thanks now my function works fine
 
Level 7
Joined
Mar 24, 2008
Messages
184
This may be what you are looking for.

I've discovered why that function wasn't working...since my test map was bigger once and i reduced, coordinates are screwed up, hence creating a rect at 0.0 0.0 will create an invalid rect. Indeed i was modifying my function to use a global rect instead of creating and destroying rects all the time, and i discovered this.

weird uh?

so, the final (hopefully) version of my Path Checker function is:

JASS:
// **************************************************************************
// ** **
// ** Check Pathability Function **
// ** ————————————— **
// ** **
// ** A Function that checks if a unit can walk over a certain area **
// ** (Ignores other units but not buildings, trees and other obstacles) **
// ** **
// ** By: Majin **
// ** 
// ** **
// **************************************************************************

library Walkable initializer init requires ChargeConfig
    globals
        unit pathchecker
        rect pathrect
        filterfunc truefilter
    endglobals
    
    function HideItems takes nothing returns nothing
        call SetItemVisible(GetEnumItem(), false)    
    endfunction
    
    function UnHideItems takes nothing returns nothing
        call SetItemVisible(GetEnumItem(), true)    
    endfunction
    
    function IsPointWalkable takes real x, real y returns boolean
        local boolean b
        call SetUnitPosition(pathchecker,x,y)
        set b=((GetUnitX(pathchecker)-x)*(GetUnitX(pathchecker)-x)+((GetUnitY(pathchecker)-y)*(GetUnitY(pathchecker)-y))<=1)
        if (b==false) then
            call MoveRectTo(pathrect, x, y)
            call EnumItemsInRect(pathrect,truefilter,function HideItems)
            call SetUnitPosition(pathchecker,x,y)
            set b=((GetUnitX(pathchecker)-x)*(GetUnitX(pathchecker)-x)+((GetUnitY(pathchecker)-y)*(GetUnitY(pathchecker)-y))<=1)
            call EnumItemsInRect(pathrect,truefilter,function UnHideItems)
        endif
        return b
    endfunction

    function init takes nothing returns nothing
        local real x = GetRectMinX(bj_mapInitialPlayableArea)
        local real y = GetRectMinY(bj_mapInitialPlayableArea)
        set pathrect=Rect(x,y,x+200.00,y+200.00)
        set pathchecker=CreateUnit( Player(PLAYER_NEUTRAL_PASSIVE), PATHCHECKERID, 0, 0, 0)
        set truefilter=Filter(function AntiLeak)
        call UnitAddAbility(pathchecker, SPELLPATHID)
        call IssueImmediateOrder( pathchecker, "windwalk" )
    endfunction
endlibrary
 
Last edited:
Status
Not open for further replies.
Top