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

[Solved] How to check Region buildability?

Status
Not open for further replies.

ISL

ISL

Level 13
Joined
Nov 7, 2014
Messages
238
It is possible to check Terrain Pathing at a Point,
but how does one do the same with a Region?

P.S.
I need to check if a structure can be built at a unit's position or not.
 

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
Maybe I'm misunderstanding but you can set the Point to be the center of your region. Or the Point could be the position of your unit.

Then you check the terrain pathing at that point.

  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
    • If - Conditions
      • (Terrain pathing at (Position of Footman 0001 <gen>) of type Buildability is off) Equal to False
    • Then - Actions
      • -------- You can build there --------
    • Else - Actions
 

ISL

ISL

Level 13
Joined
Nov 7, 2014
Messages
238
Maybe I'm misunderstanding but you can set the Point to be the center of your region. Or the Point could be the position of your unit.

Then you check the terrain pathing at that point.
Yes, but it will only check the center of said region.
What if the rest of the region is unbuildable?
upload_2021-1-3_7-32-58.png

Somehow I need to check every Pathing Cell inside of a square region, but I don't know how to do it.
 
Last edited:

Uncle

Warcraft Moderator
Level 64
Joined
Aug 10, 2018
Messages
6,557
I think this would work. So you first determine the pathing size of your structure, a farm for example is 4x4 or 128x128 units long. You could store this information in an Array or Hashtable.

Then move your region to the position of the unit (the region will snap to the grid).

Then create an array of Points offset from the center of the Region that will be used to check pathability.

Farm (128x128) example:

set point[0] = center of region
set point[1] = point[0] offset by -128, 128
set point[2] = point[0] offset by -96, 128
set point[3] = point[0] offset by -64, 128
etc...

You could simplify this with a loop and some extra variables, something like:

Set variable IsPathable = True
Set variable x = -128, Set variable y = 128
Set variable point[0] = center of region
For loop (int A):
Set point[A] = point[0] offset by x, y
Set x = x + 32
If Terrain is pathable at point[A] equal to False then Set IsPathable = False
Remove point[A]
If x > 128 then Set x = -128 and Set y = y - 32
If y < -128 then end the loop

Finally you can check: If IsPathable equal to True then -> You can build the structure there.

You may have to use smaller increments like 16 instead of 32.
 
Last edited:
  • Like
Reactions: ISL

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
I think issuing a unit with a point placement order to build the desired building will return false if the order fails because the building foundation could not be placed. If this is the case it could be used for a much more accurate placement test since it will factor in the placement requirements of the actual building footprint rather than some rectangle of pathing that does not even account for buildings and destructables in it.
 

ISL

ISL

Level 13
Joined
Nov 7, 2014
Messages
238
You need to iterate over the whole region, checking each pathing square for pathability. AFAIK, there's no built in way to do this.
That is the conclusion I have reached;
I think this would work. So you first determine the pathing size of your structure, a farm for example is 4x4 or 128x128 units long. You could store this information in an Array or Hashtable.

Then move your region to the position of the unit (the region will snap to the grid).

Then create an array of Points offset from the center of the Region that will be used to check pathability.

Farm (128x128) example:

set point[0] = center of region
set point[1] = point[0] offset by -128, 128
set point[2] = point[0] offset by -96, 128
set point[3] = point[0] offset by -64, 128
etc...

You could simplify this with a loop and some extra variables, something like:

Set variable IsPathable = True
Set variable x = -128, Set variable y = 128
Set variable point[0] = center of region
For loop (int A):
Set point = point[A] offset by x, y
Set x = x + 32
If Terrain is pathable at point[A] equal to False then Set IsPathable = False
Remove point[A]
If x > 128 then Set x = -128 and Set y = y - 32
If y < -128 then end the loop

Finally you can check: If IsPathable equal to True then -> You can build the structure there.

You may have to use smaller increments like 16 instead of 32.
That is where I am currently at;
I think issuing a unit with a point placement order to build the desired building will return false if the order fails because the building foundation could not be placed. If this is the case it could be used for a much more accurate placement test since it will factor in the placement requirements of the actual building footprint rather than some rectangle of pathing that does not even account for buildings and destructables in it.
And that is exactly why my trigger did not work; It did not account for other buildings or destructables (plus I did not know the exact size of a Pathing cell)


Orders can return booleans?
This seems to be the fastest and the easiest possible way to check it,
But how exactly do I get a 'False' from a failed order?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,201
But how exactly do I get a 'False' from a failed order?
You evaluate the return value.
JASS:
native IssueBuildOrderById takes unit whichPeon,integer unitId,real x,real y returns boolean
native IssuePointOrderById takes unit whichUnit,integer order,real x,real y returns boolean
Most of the order natives return a boolean that should represent if the order could be issued successfully.
 

ISL

ISL

Level 13
Joined
Nov 7, 2014
Messages
238
After issuing the order, check the current order of the unit. If it's current order is something like (null) then you know it failed to do the order.
I suppose the current order will still be 'null' even if the issued order was successful.

You evaluate the return value.
JASS:
native IssueBuildOrderById takes unit whichPeon,integer unitId,real x,real y returns boolean
native IssuePointOrderById takes unit whichUnit,integer order,real x,real y returns boolean
Most of the order natives return a boolean that should represent if the order could be issued successfully.
Thank you! Worked like a charm.
 
Status
Not open for further replies.
Top