• 🏆 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!

Check Walkability

Introduction

Premise/Information

Triggers

Demo

Implementation

A GUI version of:
http://www.wc3c.net/showthread.php?t=103862

No credits are needed. If you do give credits, then give credits to Rising_Dusk or Vexorian for the original implementation of the pathing check.

This is to help spells when checking for pathing. I noticed that some knockbacks and such have poor checking, as they only check if the terrain walkability is off. That only checks the default pathing (cliffs and such), but the unit will slide through buildings and destructables. I know people won't use the vJASS version, so I made a GUI implementation.

There are two common methods for checking pathing:

(1) Move an item there. (Vexorian/Rising_Dusk) Check if the item's position is close to the destination point. If it isn't close, then that means that the wc3 engine repositioned it because that point isn't pathable. Seems simple, right? Well, there are some issues:
- Items are similar to unit pathing is most ways... except units can walk through items. Items can't be positioned near other items, however. This is why the enumeration is necessary--it hides items so that it accurately determines whether the point is walkable for a unit.
- There may be some issues in really crowded areas (a.k.a. when the wc3 engine desperately has to find the nearest pathable point).
The pros is that this method is clean, fast, and handles most cases quite nicely. And one thing is for sure, it is definitely more accurate than checking if the walkability is off (it actually combines that check + the item check).

(2) Set a unit's position there. (Bob666 [N-a-z-g-u-l]/Nestharus) Then you perform similar checks based on that. That fixes the problem mentioned in the second point above (in really crowded areas). However, the reason why I chose the first implementation is that SetUnitPosition() fires a "stop" order and moving the unit may fire region enter events. In the end, it may be more problematic for GUI users than it is worth.

  • Check Walkability Setup
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set CP_Rect = (Region(0.00, 0.00, 128.00, 128.00))
      • Custom script: set udg_CP_Item = CreateItem('wtlg', 0, 0)
      • Item - Hide CP_Item
      • -------- Variables For Copy and Paste --------
      • Set CP_HiddenItemsIndex = 0
      • Set CP_HiddenItems[0] = No item
      • Set CP_Point = (Target point of ability being cast)
      • Set CP_PointIsWalkable = False
  • Check Walkability
    • Events
    • Conditions
    • Actions
      • Custom script: local real x = GetLocationX(udg_CP_Point)
      • Custom script: local real y = GetLocationY(udg_CP_Point)
      • Custom script: local real x2 = 0
      • Custom script: local real y2 = 0
      • Custom script: call MoveRectTo(udg_CP_Rect, x, y)
      • Item - Pick every item in CP_Rect and do (Actions)
        • Loop - Actions
          • Custom script: if IsItemVisible(GetEnumItem()) then
          • Set CP_HiddenItems[CP_HiddenItemsIndex] = (Picked item)
          • Custom script: call SetItemVisible(udg_CP_HiddenItems[udg_CP_HiddenItemsIndex], false)
          • Set CP_HiddenItemsIndex = (CP_HiddenItemsIndex + 1)
          • Custom script: endif
      • Custom script: call SetItemPosition(udg_CP_Item, x, y)
      • Custom script: set x2 = GetItemX(udg_CP_Item)
      • Custom script: set y2 = GetItemY(udg_CP_Item)
      • Custom script: call SetItemVisible(udg_CP_Item, false)
      • Custom script: loop
      • Custom script: exitwhen udg_CP_HiddenItemsIndex <= 0
      • Custom script: set udg_CP_HiddenItemsIndex = udg_CP_HiddenItemsIndex - 1
      • Custom script: call SetItemVisible(udg_CP_HiddenItems[udg_CP_HiddenItemsIndex], true)
      • Custom script: set udg_CP_HiddenItems[udg_CP_HiddenItemsIndex] = null
      • Custom script: endloop
      • Custom script: set udg_CP_PointIsWalkable = ((x2-x)*(x2-x) + (y2-y)*(y2-y) <= 100) and (not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY))
  • Example
    • Events
      • Unit - A unit Is issued an order targeting a point
    • Conditions
    • Actions
      • -------- Set CP_Point to the point you want to check for walkability --------
      • Set CP_Point = (Target point of issued order)
      • -------- Run "Check Walkability" --------
      • Trigger - Run Check Walkability <gen> (ignoring conditions)
      • -------- If CP_PointIsWalkable is true, then the point is walkable --------
      • -------- If it is false, then it isn't pathable. --------
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • CP_PointIsWalkable Equal to True
        • Then - Actions
          • Game - Display to (All players) the text: Pathable!
        • Else - Actions
          • Game - Display to (All players) the text: Not Pathable!
      • Custom script: call RemoveLocation(udg_CP_Point)

  • Go to File -> Preferences and check Automatically create unknown variables while pasting trigger data
  • Copy and paste the category "CheckWalkability"
  • (Optional) Delete the code after "Variables for Copy and Paste"
  • Use it as shown in the demo. You just set CP_Point to the point you want to check for pathability. Then you run the trigger. CP_IsPointWalkable will return whether the point is walkable.
  • Note: You may want to remove the location after using it if you no longer need it, just to prevent leaking.
Contents

Walkability Check (Map)

Reviews
Check Walkability | Reviewed by Maker | 9th Jul 2013 APPROVED [tr] This is a very useful system, I can seet it being used widely. There could be a variable for the tolerance.

Moderator

M

Moderator


Check Walkability | Reviewed by Maker | 9th Jul 2013
APPROVED


126248-albums6177-picture66521.png



  • This is a very useful system, I can seet it being used widely.
    There could be a variable for the tolerance.
[tr]
 
mckill description? XD

How about cacheing first GetEnumUnit then index it?

You mean GetEnumItem()? Eh, I thought of that, it *could* be a minor speed increase but it won't be anything in an actual scenario.

Anyway, most of the time that part won't even fire. It is just for the odd scenarios when there happens to be an item laying on the ground. :)

Thanks for the comments guys.
 
That's a very misleading screenshot. :p

Haha, I had to make it look epic. It reels you in, thinking that I made an awesome test map featuring a crazy duel between a tauren and a blood elf mage. Nope. muahaha

Not really about your system, but I just find it somewhat lame to have to emulate function calls using triggers and global variables just so that GUIers minimize their use of custom scripts.

I agree. It isn't really that efficient, either (TriggerExecute() calls). But ah well. GUI'ers find custom scripts scary. I can't really blame them either, since the default syntax checker for regular WE will slap you left and right for any mistake you make in the code (it'll throw 5-6 errors and disable the trigger, pretty annoying stuff).

But I agree, it is a pretty weird method and only promotes GUI even more. However, it is better than having them code things poorly (a lot of GUI spells have poor pathing checks). So in the end I decided to make this for them :[

P.S. Nice to see you back :D
 
Level 10
Joined
Aug 21, 2010
Messages
316
Maybe I'm wrong but this only supports location [udg_CP_Point] (missing coordinates)

With this, it is only possible to use this

JASS:
set udg_CP_Point = GetOrderPointLoc()
JASS:
set udg_CP_Point = GetSpellTargetLoc()
and so on...
[Very limited possibilities]

What if someone wants to use something like this
Example:

JASS:
set udg_CP_X = GetOrderPointX()
JASS:
set udg_CP_Y = GetOrderPointY()
JASS:
set udg_CP_X = GetSpellTargetX()
JASS:
set udg_CP_Y = GetSpellTargetY()
JASS:
set udg_CP_X = GetUnitX(whichUnit)
JASS:
set udg_CP_Y = GetUnitY(whichUnit)
JASS:
set udg_CP_X = GetItemX(whichItem)
JASS:
set udg_CP_Y = GetItemY(whichItem)
and so on...


Definitely, the system should support both options
This would make the system much more complete
 
@zv27: I'll add support for coordinates when I get back to my modding comp (probably won't get back until around Tuesday/Wednesday). I didn't really accommodate for coordinates since there aren't any GUI functions that really use them (or not much, aside from Point()). But I suppose it wouldn't hurt.

P.S. If you have any knowledge of JASS, I highly recommend using Rising_Dusk's version. It is far better for all intents and purposes since my method relies on a TriggerExecute per function call (to support easy usage with GUI). In most cases, the performance shouldn't matter since it is still a lightweight function, but it is still wiser to use the vJASS version if you know how.
 
Level 3
Joined
Dec 8, 2013
Messages
51
Hey @PurgeandFire. It's pretty nice system, but I wonder: does it detect through the unit position? For example When U order unit to move on place that already contains someone near.
 
Hey @PurgeandFire. It's pretty nice system, but I wonder: does it detect through the unit position? For example When U order unit to move on place that already contains someone near.

I don't think it checks for units, but I am not 100% sure. Best way would be to test it.

There is a way to check for units using build orders, but it involves JASS.
 
Top