• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

[General] Is there a tree nearby?

Status
Not open for further replies.
Level 15
Joined
Oct 29, 2012
Messages
1,474
^ Just Detailing the idea, I am not sure whether from this works but it's worth to try :

  • Actions
    • Set YourUnit_Point = (Position of (Triggering unit))
    • Destructible - Pick every destructible within 256.00 of YourUnit_Point and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Picked destructible) Equal to No destructible
          • Then - Actions
            • - Your Trigger -
          • Else - Actions
  • Actions
    • Set YourUnit_Point = (Position of (Triggering unit))
    • Destructible - Pick every destructible within 256.00 of YourUnit_Point and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • ((Picked destructible) is alive) Equal to True
          • Then - Actions
          • Else - Actions
  • Actions
    • Set YourUnit_Point = (Position of (Triggering unit))
    • Destructible - Pick every destructible within 256.00 of YourUnit_Point and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Distance between YourUnit_Point and (Position of (Picked destructible))) Less than or equal to 256.00
          • Then - Actions
          • Else - Actions
  • Actions
    • Set TreeType = Ashenvale Tree Wall
    • Set YourUnit = (Triggering unit)
    • Set YourUnitPoint = (Position of YourUnit)
    • Set DestructibleCounter = 0
    • Destructible - Pick every destructible within 256.00 of YourUnitPoint and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Destructible-type of (Picked destructible)) Equal to TreeType
          • Then - Actions
            • Set DestructibleCounter = (DestructibleCounter + 1)
          • Else - Actions
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • DestructibleCounter Greater than 0
      • Then - Actions
        • - Setting Boolean that you found a tree -
      • Else - Actions
        • - Setting Boolean that you didn't find a tree -
 
You could make use of GetClosestWidget with destructable-module on. With such, it's much easier for you:
JASS:
// where x, y mark coords while filter being a filter function - check for "trees-only"
set tree = GetClosestDestructable(x, y, Filter(function filter))
IsDestructable tree (from wc3c or the one from hive) might also be usefull for you.
 
Level 15
Joined
Aug 7, 2013
Messages
1,338
I believe jonhysone's GUI will work for your need (I think the fourth one works correctly).

Bannar said:
You could make use of GetClosestWidget with destructable-module on.

This is a useful library, but AFAIK it just finds the example gets the closest widget, or in the OP's case, the closest tree / destructable. The meaning of "nearby," however, is tied to a quantity, namely, how close is nearby? If the closest tree is 10000.0 units away, then that definitely is not nearby (unless the map involves Godzilla-esque giants).

Use "pick every destructible in range of point" and check if they are trees.

This is what you should do. For the location / point, use GetUnitLoc(ation) of the unit in question, and then for range, define how far away is nearby. Is it super close (100-200) or perhaps can be a bit further away (500-1000)?
 
Last edited:

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,258
I do recall there being some limit to the number of destructibles picked by the enumeration. As such there is a chance such simple approaches will malfunction if ever run with a large search area or in areas with a high destructible density. The error will manifest as choosing a destructible that is not the closest to the point tested.
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,258
limit of how many boss?
32 or something. I forget.

I don't think that would occur if my radius is only as big as 350 right?
Depends. Nothing stops you stacking 1,000 Destructible objects into that tiny area next to common sense. If you are sure that your map does not have a high density and if it does not really mater if results are not 100% perfect (who cares if in 1-2 spots it picks something that is not the closest in a tiny area?) then it is certainly not a problem. However if you were doing something like finding the nearest trees to harvest from a building out of all trees on the map then this limit is a huge problem.
 
Level 15
Joined
Aug 7, 2013
Messages
1,338
64 is Max amount of Dest Enum AFAIR. Rest are dismissed.

Thanks for confirming this daffa.

I was worried but it's not a big deal if you want to know if at least one destructable is in range of a point, since only need to count one.
 
It is not true. The limit is none. Limit exists only if you use TriggerRegisterDestDeathInRegionEvent:
JASS:
function RegisterDestDeathInRegionEnum takes nothing returns nothing
    set bj_destInRegionDiesCount = bj_destInRegionDiesCount + 1
    if (bj_destInRegionDiesCount <= bj_MAX_DEST_IN_REGION_EVENTS) then
        call TriggerRegisterDeathEvent(bj_destInRegionDiesTrig, GetEnumDestructable())
    endif
endfunction

function TriggerRegisterDestDeathInRegionEvent takes trigger trig, rect r returns event
    set bj_destInRegionDiesTrig = trig
    set bj_destInRegionDiesCount = 0
    call EnumDestructablesInRect(r, null, function RegisterDestDeathInRegionEnum)
    return trig
endfunction
And the most important part:constant integer bj_MAX_DEST_IN_REGION_EVENTS = 64If such limit would restrict all of enum functions, then all of my dest-related resources were trash.

This is a useful library, but AFAIK it just finds the closest widget, or in the OP's case, the closest tree / destructable. The meaning of "nearby," however, is tied to a quantity, namely, how close is nearby? If the closest tree is 10000.0 units away, then that definitely is not nearby (unless the map involves Godzilla-esque giants).
Have you even read the lib's description? You can choose varienty of function (related to dest, item, unit and group), thus you could call for example: GetClosestDestructableInRange. By specifing radius value, you can check if a e.g tree exists within circle 10000.0 units away from point "p". Read before posting false opinions.
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
^ Just Detailing the idea, I am not sure whether from this works but it's worth to try :

  • Actions
    • Set YourUnit_Point = (Position of (Triggering unit))
    • Destructible - Pick every destructible within 256.00 of YourUnit_Point and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Picked destructible) Equal to No destructible
          • Then - Actions
            • - Your Trigger -
          • Else - Actions
  • Actions
    • Set YourUnit_Point = (Position of (Triggering unit))
    • Destructible - Pick every destructible within 256.00 of YourUnit_Point and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • ((Picked destructible) is alive) Equal to True
          • Then - Actions
          • Else - Actions
  • Actions
    • Set YourUnit_Point = (Position of (Triggering unit))
    • Destructible - Pick every destructible within 256.00 of YourUnit_Point and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Distance between YourUnit_Point and (Position of (Picked destructible))) Less than or equal to 256.00
          • Then - Actions
          • Else - Actions
  • Actions
    • Set TreeType = Ashenvale Tree Wall
    • Set YourUnit = (Triggering unit)
    • Set YourUnitPoint = (Position of YourUnit)
    • Set DestructibleCounter = 0
    • Destructible - Pick every destructible within 256.00 of YourUnitPoint and do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Destructible-type of (Picked destructible)) Equal to TreeType
          • Then - Actions
            • Set DestructibleCounter = (DestructibleCounter + 1)
          • Else - Actions
    • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
      • If - Conditions
        • DestructibleCounter Greater than 0
      • Then - Actions
        • - Setting Boolean that you found a tree -
      • Else - Actions
        • - Setting Boolean that you didn't find a tree -

only the last one will work afaik, because if you try to enumerate trees, there is no way you will get "No destructable" in enumeration, if you dont pick any trees, it will not run the loop body even once, so the last approach is the only correct one

Alternativelly, if you have/are willign to use vJass, you can use Bannar's solution
 

Deleted member 219079

D

Deleted member 219079

Gcw is not useful in this case. Just make a global variable true on the enum event. Before it, set it to false. This way if a single dest is picked, it returns true.

I think there's a GUI method of is destructable tree, try googling it.
 
It is not true. The limit is none. Limit exists only if you use TriggerRegisterDestDeathInRegionEvent:
JASS:
function RegisterDestDeathInRegionEnum takes nothing returns nothing
    set bj_destInRegionDiesCount = bj_destInRegionDiesCount + 1
    if (bj_destInRegionDiesCount <= bj_MAX_DEST_IN_REGION_EVENTS) then
        call TriggerRegisterDeathEvent(bj_destInRegionDiesTrig, GetEnumDestructable())
    endif
endfunction

function TriggerRegisterDestDeathInRegionEvent takes trigger trig, rect r returns event
    set bj_destInRegionDiesTrig = trig
    set bj_destInRegionDiesCount = 0
    call EnumDestructablesInRect(r, null, function RegisterDestDeathInRegionEnum)
    return trig
endfunction
And the most important part:constant integer bj_MAX_DEST_IN_REGION_EVENTS = 64If such limit would restrict all of enum functions, then all of my dest-related resources were trash.

Have you even read the lib's description? You can choose varienty of function (related to dest, item, unit and group), thus you could call for example: GetClosestDestructableInRange. By specifing radius value, you can check if a e.g tree exists within circle 10000.0 units away from point "p". Read before posting false opinions.

I see I mistaken my memories somehow. Thanks for correction.
 
Level 15
Joined
Aug 7, 2013
Messages
1,338
Bannar said:
Have you even read the lib's description? You can choose varienty of function (related to dest, item, unit and group), thus you could call for example: GetClosestDestructableInRange. By specifing radius value, you can check if a e.g tree exists within circle 10000.0 units away from point "p". Read before posting false opinions.

I didn't read the full API which is my fault. I should have addressed only the example and not the library, which I'll fix now. But I am not the only one of this opinion, that GCW may be shooting a sparrow with a cannon with regards to the OP (that is a Russian idiom for overkill).

jondrean said:
Gcw is not useful in this case.

Bannar said:
JASS:
// where x, y mark coords while filter being a filter function - check for "trees-only"
set tree = GetClosestDestructable(x, y, Filter(function filter))

edo494 said:
you know you can check the distance from the x, y points and the tree,

As I pointed out, this just returns the closest tree, but the OP wants to tell whether a tree is nearby, which is different from finding the closest tree. Of course this can be used to do determine it (get the distance between the closest tree and the unit), but then it would have been easier to just have used GetClosestDestructableInRange which was unfortunately absent from the example you gave :p.

johnysone's solution (the fourth GUI sample) seems more than adequate for the OP's needs. Also I think the OP would benefit more from understanding how it's done before using a high level interface that GCW provides.

sethmachine said:
I believe jonhysone's GUI will work for your need (I think the fourth one works correctly).

edo494 said:
only the last one will work afaik, because if you try to enumerate trees, there is no way you will get "No destructable" in enumeration, if you dont pick any trees, it will not run the loop body even once, so the last approach is the only correct one
 
Level 23
Joined
Apr 16, 2012
Messages
4,041
no, if you know what is nearby(lets say 350 units), you just do

JASS:
function IsTree_impl takes nothing returns boolean
    return IsTree(GetEnumDestructable())
    //I imagine you pass in enum destructable
    //there is resource for this
endfunction

function IsTreeNearby takes real x, real y, real nearby returns boolean
    local destructable d = GetClosestDestructable(x, y, Filter(function IsTree))
    local real xDist = 0
    local real yDist = 0
    
    if (d == null) then
        return false
    endif

    set xDist = GetDestructableX(d) - x
    set yDist = GetDestructableY(d) - y

    return nearby * nearby < (xDist * xDist + yDist * yDist)
endfunction

As I pointed out, this just returns the closest tree, but the OP wants to tell whether a tree is nearby

So what? a bit of math, and a null check, and you know if tree is nearby. While this is less effective(it has to perform some kind of sort, or check at least to see which tree is closest), it is quite clean one.

On the other node, I wonder Bannar, what happens when I pass in filter for trees, but the closest destructable is not a tree but lets say, a bridge or something?
 
Nothing strange really. GWC uses Enum Items/Destructables InRect which are declared as:
native EnumDestructablesInRect takes rect r, boolexpr filter, code actionFunc returns nothingYou can provide both, filter and code function.

If you call GetClosestDestructableInRange(x, y, null), script will provide you closest dest, regardless of it's kind. However, if you do:
JASS:
static method istree takes nothing returns boolean
	return IsDestructableTree(GetFilterDestructable())
endmethod

// some random print function
call print("closest tree: ", GetClosestDestructable(x, y, Filter(function thistype.istree)))
it will only retrieve a tree or null if none has been found.
 
Status
Not open for further replies.
Top