• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

PathingColor checker

Status
Not open for further replies.

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
This system extends the functionality of IsTerrainWalkable by vex, it can detect a location's pathing color (in terrain editor, pathing color can be seen by pressing 'p'). However, it couldn't be 100% accurate, it fails to detect correctly at the edge of pathing area, probably due to:
- Minimum pathing size of structure unit of 64 => shabby accuracy.
- Sometimes IsTerrainWalkable seems to return wrong result in very certain cases.

Any help to fix this issue will be highly appreciated, I find this system can be used to make highly advanced systems. How not? It can detect 8 different pathing types!

Here is the code and demo map:

JASS:
library PathingColor initializer onInit requires IsTerrainWalkable
    
    globals
    
        private constant integer FLYING_CHECKER = 'hgyr'
        private constant integer BUILDING_CHECKER = 'n000'
        private constant real COLLISION_SIZE = 64
        
    endglobals
    
    globals
        
        private rect TempRect
        
        private unit FlyChecker
        private unit BuildChecker
        
        private group DisableGroup = CreateGroup()
        private group EnableGroup  = CreateGroup()
        
        constant integer PATHING_COLOR_WHITE   = 0
        constant integer PATHING_COLOR_MAGENTA = 1
        constant integer PATHING_COLOR_CYAN    = 2
        constant integer PATHING_COLOR_BLUE    = 3
        constant integer PATHING_COLOR_YELLOW  = 4
        constant integer PATHING_COLOR_RED     = 5
        constant integer PATHING_COLOR_GREEN   = 6
        constant integer PATHING_COLOR_BLACK   = 7
        
    endglobals
    
    private function IsInRect takes real x, real y returns boolean
        return x > GetRectMinX(TempRect) and x < GetRectMaxX(TempRect) and y > GetRectMinY(TempRect) and y < GetRectMaxY(TempRect)
    endfunction
    
    function GetTerrainPathingColor takes real x, real y returns integer
        
        local real x2
        local real y2
        local unit fog
        local integer result = 0
        
        call MoveRectTo(TempRect, x, y)
        call GroupEnumUnitsInRect(DisableGroup, TempRect, null)
        loop
            set fog = FirstOfGroup(DisableGroup)
            exitwhen fog == null
            call GroupRemoveUnit(DisableGroup, fog)
            call GroupAddUnit(EnableGroup, fog)
            call SetUnitPathing(fog, false)
        endloop
        
        call SetUnitPosition(FlyChecker, x, y)
        call SetUnitPosition(BuildChecker, x, y)
        set x2 = GetUnitX(FlyChecker)
        set y2 = GetUnitY(FlyChecker)
        
        if (x-x2)*(x-x2)+(y-y2)*(y-y2) < 2 then
            set result = result + 1
        endif
        
        if IsTerrainWalkable(x, y) then
            set result = result + 2
        endif
        
        if IsInRect(GetUnitX(BuildChecker), GetUnitY(BuildChecker)) then
            set result = result + 4
        endif
        
        loop
            set fog = FirstOfGroup(EnableGroup)
            exitwhen fog == null
            call GroupRemoveUnit(EnableGroup, fog)
            call SetUnitPathing(fog, true)
        endloop
        
        return result
    endfunction
    
    private function onInit takes nothing returns nothing
        
        local player p = Player(PLAYER_NEUTRAL_PASSIVE)
        
        set TempRect = Rect(0, 0, COLLISION_SIZE, COLLISION_SIZE)
    
        set FlyChecker = CreateUnit(p, FLYING_CHECKER, 0, 0, 0)
        call SetUnitInvulnerable(FlyChecker, true)
        call PauseUnit(FlyChecker, true)
        call ShowUnit(FlyChecker, false)
    
        set BuildChecker = CreateUnit(p, BUILDING_CHECKER, 0, 0, 0)
        call SetUnitInvulnerable(BuildChecker, true)
        call PauseUnit(BuildChecker, true)
        call ShowUnit(BuildChecker, false)
        
    endfunction
    
endlibrary

(Updated.
Now the inaccuracy only occurs at very edge of the pathing area and for specific colors only (yellow, white, and magenta). I noticed that the problem occurs when TerrainWalkablity is false.)
 

Attachments

  • CheckPathingColor.w3x
    32.5 KB · Views: 44
Last edited:

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Okay.

Btw, I think I have fixed the issue. But how come IsTerrainWalkable returns "false" when I walked on snow terrain. :/

EDIT:
Update. Now the only problem is why IsTerrainWalkable returns false on black and green pathing color? It seems that the item won't be moved to exactly targeted point whereas the point is completely walkable.
 

Attachments

  • CheckPathingColor.w3x
    32.5 KB · Views: 46
Level 26
Joined
Aug 18, 2009
Messages
4,097
? Terrain pathing is what you receive by the GetTerrainPathable function. You do not need to place widgets for that. Also why would you use the color name in code? Ultimately you would want to check if a spot possesses pathing characteristics like flyability or not. The color is only to visualize it in the World Editor terrain view.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Terrain pathing is what you receive by the GetTerrainPathable function. You do not need to place widgets for that.
Native function for getting terrain pathability is unable to detect pathability caused by doodads (blocker) (and maybe units), that's why we need widget to check it. And we need different widgets for every pathing type.

Also why would you use the color name in code? Ultimately you would want to check if a spot possesses pathing characteristics like flyability or not. The color is only to visualize it in the World Editor terrain view.
Using color, we can extend pathing types from 3 (walk, fly, build) into 8 (black - white). It's true that it visualize the pathing characteristic, but it's not "only" useful for that. This is just one example where we can apply this feature: in a sliding map, usually we will have different terrain characteristic for every tile type, e.g. no sliding for rocky ground, fast sliding on ice, slower sliding on ice cracks, etc. But using this, we can determine those characteristic based on the pathing color: e.g. no slide if pathing color is black, fast sliding if blue, slow sliding if cyan, kill the slider if red, etc. while we can still variate the tile type. We can draw the pathing color using doodads (blockers), examples are available in the demo map.

I have tried to use this in my map, it's very easy to use and the result seems very elegant.

However, the system looks very heavy because of SetUnitPosition, I'm currently trying to find a faster way.
 
Level 26
Joined
Aug 18, 2009
Messages
4,097
Native function for getting terrain pathability is unable to detect pathability caused by doodads (blocker) (and maybe units), that's why we need widget to check it. And we need different widgets for every pathing type.

That's because destructables and units do not count as terrain pathing.

... usually we will have different terrain characteristic for every tile type, e.g. no sliding for rocky ground, fast sliding on ice, slower sliding on ice cracks, etc. But using this, we can determine those characteristic based on the pathing color...

Okay, for using in parallel with terrain editor painting. But dunno, why not make it an alias then or at least provide conversion functions/an all-inclusive solution.

However, the system looks very heavy because of SetUnitPosition, I'm currently trying to find a faster way.

You can convert it to terrain pathing or cache the spots yourself. That is if you keep it static, not moving it around ingame.

edit: Also it's faster if you make a function for checking the pathing color at a spot because then you can skip on the first mismatch.
 

Kazeon

Hosted Project: EC
Level 33
Joined
Oct 12, 2011
Messages
3,449
Only red (no walk), green (no fly) and blue (no build) are elemental. White is red+green+blue. So if you want to check for white but not even blue is found, it cannot become white anymore, you can stop at this point.
I didn't even notice that. Let's see what I can do with this information. Thanks!

EDIT:
So did you mean the function should be "IsTerrainPathingColor(real x, real y, integer color)" that returns boolean? I get it now! And it could be better indeed.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
You could also keep some function to load the color out of the position, because it is easier for the end user to call one function and get the color, so delegate the work to you, than to try checking 8 different combinations of colors until hitting one.
 
Status
Not open for further replies.
Top