| 12-30-2008, 04:57 AM | #1 |
TerrainPathability Library Background: This is a library of code that allows users to detect whether a given point of terrain is land, shallow water, deep water, or walkable with great simplicity. Requirements:
Library:library TerrainPathability initializer Init //****************************************************************************** //* BY: Rising_Dusk //* //* This script can be used to detect the type of pathing at a specific point. //* It is valuable to do it this way because the IsTerrainPathable is very //* counterintuitive and returns in odd ways and aren't always as you would //* expect. This library, however, facilitates detecting those things reliably //* and easily. //* //****************************************************************************** //* //* > function IsTerrainDeepWater takes real x, real y returns boolean //* > function IsTerrainShallowWater takes real x, real y returns boolean //* > function IsTerrainLand takes real x, real y returns boolean //* > function IsTerrainPlatform takes real x, real y returns boolean //* > function IsTerrainWalkable takes real x, real y returns boolean //* //* These functions return true if the given point is of the type specified //* in the function's name and false if it is not. For the IsTerrainWalkable //* function, the MAX_RANGE constant below is the maximum deviation range from //* the supplied coordinates that will still return true. //* //* The IsTerrainPlatform works for any preplaced walkable destructable. It will //* return true over bridges, destructable ramps, elevators, and invisible //* platforms. Walkable destructables created at runtime do not create the same //* pathing hole as preplaced ones do, so this will return false for them. All //* other functions except IsTerrainWalkable return false for platforms, because //* the platform itself erases their pathing when the map is saved. //* //* After calling IsTerrainWalkable(x, y), the following two global variables //* gain meaning. They return the X and Y coordinates of the nearest walkable //* point to the specified coordinates. These will only deviate from the //* IsTerrainWalkable function arguments if the function returned false. //* //* Variables that can be used from the library: //* [real] TerrainPathability_X //* [real] TerrainPathability_Y //* globals private constant real MAX_RANGE = 10. private constant integer DUMMY_ITEM_ID = 'wolg' endglobals globals private item Item = null private rect Find = null private item array Hid private integer HidMax = 0 public real X = 0. public real Y = 0. endglobals function IsTerrainDeepWater takes real x, real y returns boolean return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) endfunction function IsTerrainShallowWater takes real x, real y returns boolean return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) and IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY) endfunction function IsTerrainLand takes real x, real y returns boolean return IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) endfunction function IsTerrainPlatform takes real x, real y returns boolean return not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) and not IsTerrainPathable(x, y, PATHING_TYPE_BUILDABILITY) endfunction private function HideItem takes nothing returns nothing if IsItemVisible(GetEnumItem()) then set Hid[HidMax] = GetEnumItem() call SetItemVisible(Hid[HidMax], false) set HidMax = HidMax + 1 endif endfunction function IsTerrainWalkable takes real x, real y returns boolean //Hide any items in the area to avoid conflicts with our item call MoveRectTo(Find, x, y) call EnumItemsInRect(Find ,null, function HideItem) //Try to move the test item and get its coords call SetItemPosition(Item, x, y) //Unhides the item set X = GetItemX(Item) set Y = GetItemY(Item) static if LIBRARY_IsTerrainWalkable then //This is for compatibility with the IsTerrainWalkable library set IsTerrainWalkable_X = X set IsTerrainWalkable_Y = Y endif call SetItemVisible(Item, false)//Hide it again //Unhide any items hidden at the start loop exitwhen HidMax <= 0 set HidMax = HidMax - 1 call SetItemVisible(Hid[HidMax], true) set Hid[HidMax] = null endloop //Return walkability return (X-x)*(X-x)+(Y-y)*(Y-y) <= MAX_RANGE*MAX_RANGE and not IsTerrainPathable(x, y, PATHING_TYPE_WALKABILITY) endfunction private function Init takes nothing returns nothing set Find = Rect(0., 0., 128., 128.) set Item = CreateItem(DUMMY_ITEM_ID, 0, 0) call SetItemVisible(Item, false) endfunction endlibrary Function List: This library provides the following functions to the user.
Backwards Compatibility: In the event that you used IsTerrainWalkable in your map, the following backwards compatibility library has been provided for your convenience. Simply replace the old library with the library below and it will work fine. IsTerrainWalkable:library IsTerrainWalkable requires TerrainPathability globals public real X public real Y endglobals endlibrary Enjoy! |
| 12-30-2008, 10:51 AM | #2 |
Nice resource. Few points : - You should add a constant dummy player. - What about move the unit outside the playable map area if it was moved ? I mean she is insivible, with no collision and all, but the unit still can be enumed. |
| 12-30-2008, 12:58 PM | #3 |
JASS:not (not IsTerrainPathable(x, y, PATHING_TYPE_FLOATABILITY) huh...don't they cancel out, like a double negative? |
| 12-30-2008, 01:05 PM | #4 | |
emjlr3 double check that expression ... -- I think the bunch of other things to detect are a little useless. All that was needed was walkable, the rest we already had natives for, I think it is simpler to just call IsTerrainPathable in cases when we want to detect land or water. Just saying this so it could just remain 'IsTerrainWalkable' but using the new method so that migration would be easy, both things do the same and detecting true on deep water was just a bug so, it is natural to "fix it" by using this new method. Though I think that having to use a dummy ability is a little too much, aren't there passive abilities that do the same windwalk does? Or you could add the IsTerrainWalkable function to what you have now and also a library library IsTerrainWalkable that requires this new one that has all these constants. Quote:
|
| 12-30-2008, 01:58 PM | #5 | |
yea I figured I had missed the other ) Quote:
or 'Aloc' it (not sure what 'Avul' does - i assume its for invulnerability) |
| 12-30-2008, 03:49 PM | #6 |
Use 'Aloc' will not work since an unit witch have this ability can be on every pathing, that would be a nice function witch always return true, but hide/unhide the unit is the way to go i think. Hmm but for some reasons if a player use a group for filter hidden units in a range R on X/Y, then the hidden unit would be enumed so. And if you place the unit outside the playable map area, i don't see any problem, but correct me if i'm wrong. |
| 12-30-2008, 04:59 PM | #7 |
doesn't that crash maps online? - thus the needed for map border checks when using SetUnitX/Y |
| 12-30-2008, 05:01 PM | #8 | |||||||
Quote:
Quote:
Quote:
Quote:
Quote:
Quote:
Vex, it seems you want an IsTerrainWalkable function, but I thought we didn't want to have function name conflicts in the database? I was originally going to separate walkable from the rest, but I remember once you got angry for me using a function name already in the database. I am not sure. Quote:
|
| 12-30-2008, 05:33 PM | #9 |
No you don't get it i said outside the playable map area not the entire map JASS:library GetWorldBoundsMin initializer init globals private real Xmin private real Ymin endglobals public function init takes nothing returns nothing local rect r= GetWorldBounds() set Xmin= GetRectMinX(r) set Ymin= GetRectMinY(r) call RemoveRect(r) set r=null endfunction endlibrary And with the function SetUnitX/Y the unit will be outside the playable map area with no crash, i already used it for other stuff. |
| 12-30-2008, 06:20 PM | #10 |
That does not fix the enumeration issue, though, it only makes it less likely. Hiding it will fix the enumeration problem, I believe. |
| 12-30-2008, 06:25 PM | #11 |
With only adding and removing 'Aloc' you can enumerate units... |
| 12-30-2008, 06:27 PM | #12 |
Aloc interferes with the collisional properties of the dummy unit, though. |
| 12-30-2008, 06:52 PM | #13 | |
Quote:
|
| 12-30-2008, 06:56 PM | #14 |
I want to avoid as much unnecessary unit handling as possible. I think I will hide the unit only. |
| 12-30-2008, 07:01 PM | #15 |
Just a question, is it possible to know with a native fuction if an unit is hidden by an ability or by the action ShowUnit ? Yes i know we could link a boolean to the unit, or add it in a group when we hide it with ShowUnit, and after check if the unit is in or not, and so one, that's not the question. |
