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

Find Nearest Tree

Status
Not open for further replies.
Hmm, alright then. I hope this doesn't corrupt my map or anything. I'll do a backup to be safe.

I do have another question though. Once I import the libraries, how do I make use of them? Like for instance if I need to pick the nearest tree in a trigger, how do I do it? What's the custom script line to do it, etc.
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
Hmm, alright then. I hope this doesn't corrupt my map or anything. I'll do a backup to be safe.

I do have another question though. Once I import the libraries, how do I make use of them? Like for instance if I need to pick the nearest tree in a trigger, how do I do it? What's the custom script line to do it, etc.

I am sure it won't ;)

According to the documentation:

JASS:
/*       function GetClosestDestructable takes real x, real y, boolean treeOnly, boolexpr filter returns destructable
*          - Gets single destructable, nearest passed coordinates*/

so to use it you will do it like this

  • Custom script: set udg_Dest = GetClosestDestructable(GetLocationX(udg_Point), GetLocationY(udg_Point), true, null)
with udg_Dest as the result tree (destructable variable) and udg_Point as the unit's location according to what you said.
 
So it's working so far if for a few issues I'm having. I'd like to be able to exclude dead trees from being picked, and also exclude certain trees that are already being 'harvested' or targeted for harvesting.

This is how it works: a locusted unit enters map and targets nearest tree with an ability that once used initiates the harvesting. After X seconds, the tree dies and a treant is spawned in its place. The treant is ordered to cast a spell on the nearest townhall and waddles it way to it, and as it casts its spell the player gains lumber (through triggers) and dies. This creates a new unit that starts the cycle all over again.

The problems here are:
1. The restarting cycle is picking the closest tree, which is dead, and so the new unit can't cast its spell, which means it just stays there.
2. Two of the locusted units could target the same tree and consequently spawn two treants from 1 tree.
3. A tree picked for harvest could be destroyed before the unit has reached it, which would mean I need to find a way for the tree's death to trigger an event that can identify which unit was coming to harvest it and thus give it a new target. This would also be useful to redirect a unit who's tree was killed mid-harvest.
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
So it's working so far if for a few issues I'm having. I'd like to be able to exclude dead trees from being picked, and also exclude certain trees that are already being 'harvested' or targeted for harvesting.

This is how it works: a locusted unit enters map and targets nearest tree with an ability that once used initiates the harvesting. After X seconds, the tree dies and a treant is spawned in its place. The treant is ordered to cast a spell on the nearest townhall and waddles it way to it, and as it casts its spell the player gains lumber (through triggers) and dies. This creates a new unit that starts the cycle all over again.

The problems here are:
1. The restarting cycle is picking the closest tree, which is dead, and so the new unit can't cast its spell, which means it just stays there.
2. Two of the locusted units could target the same tree and consequently spawn two treants from 1 tree.
3. A tree picked for harvest could be destroyed before the unit has reached it, which would mean I need to find a way for the tree's death to trigger an event that can identify which unit was coming to harvest it and thus give it a new target. This would also be useful to redirect a unit who's tree was killed mid-harvest.

Ah right. I should have completed my answer. Here is the solution to your problems.

1/ We will use this code to filter dead destructables.

JASS:
function FilterDest takes nothing returns boolean
    return GetDestructableLife(GetEnumDestructable()) > 0
endfunction

and in the custom script

  • Custom script: set udg_Dest = GetClosestDestructable(GetLocationX(udg_Point), GetLocationY(udg_Point), true, function FilterDest)
I am writing this code freehand so there may be some syntax error. Please forgive me if there is.

2/ I don't really know if there is a way to solve this since you just can't group destructables. Sorry =/

3/ There is a way to detect when a destructable dies but getting what unit is coming to harvest it would be too bulky (the only way that comes to mind is through hashtable. You save the ordered-to-harvest unit in an order and load it later). I may be wrong though so please take this with a pinch of salt.
 
The code isn't working (I'm not even sure I'm doing the first part right lol; I copied the function you gave me in a new trigger just like I did when pasting the libraries), and when I save WE tells me there's an undefined function FilterDest, and it cannot convert code to boolexpr, which I guess is one error causing the other.

For targeting different trees I could get around this by using the Wisp's lumber harvesting but I can't find the order ID when it actively latches on to a tree.

As for dying trees, I might as well use hashtables since I can't for the life of me figure anything around this. Maybe create a dummy unit (which will be like the key) that every time a tree is targeted it is store in a hashtable. Then, every time a tree dies, the trigger checks if this tree isn't stored in that hashtable, and if it is, find the corresponding harvester, and order it to find a new tree.

Boy this got complicated quick >.<
 
I would like to point out that JNGP makes backups for your maps all the time.
I once lost my map and I was so frustrated, then I found like 40 backups in the JNGP folder and I was so frickin' happy man.

The code isn't working (I'm not even sure I'm doing the first part right lol; I copied the function you gave me in a new trigger just like I did when pasting the libraries), and when I save WE tells me there's an undefined function FilterDest, and it cannot convert code to boolexpr, which I guess is one error causing the other.

Put that code he posted in your map's JASS header and use this line instead:

  • Custom script: set udg_Dest = GetClosestDestructable(GetLocationX(udg_Point), GetLocationY(udg_Point), true, Filter(function FilterDest))
I fixed the error. A code was being passed. That function expected a boolexpr, so I passed the code to the Filter function to get a boolexpr.
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
The code isn't working (I'm not even sure I'm doing the first part right lol; I copied the function you gave me in a new trigger just like I did when pasting the libraries), and when I save WE tells me there's an undefined function FilterDest, and it cannot convert code to boolexpr, which I guess is one error causing the other.

If you are using JNGP, just wrap the function in
JASS:
library DerpyLib
endlibrary
and you are good to go ;)

And yeah about that I forgot that you need to write it as Filter(function FilterDest) because normal WE is a bit bitchy :p

edit

Mag was here eh? Damn... x)

For targeting different trees I could get around this by using the Wisp's lumber harvesting but I can't find the order ID when it actively latches on to a tree.

http://www.hiveworkshop.com/forums/jass-resources-412/repo-order-ids-197002/

There you go :)

As for dying trees, I might as well use hashtables since I can't for the life of me figure anything around this. Maybe create a dummy unit (which will be like the key) that every time a tree is targeted it is store in a hashtable. Then, every time a tree dies, the trigger checks if this tree isn't stored in that hashtable, and if it is, find the corresponding harvester, and order it to find a new tree.

Boy this got complicated quick >.<

I wish you the best of luck :D
 
Made the changes, and the errors are gone, though now the unit isn't moving at all :(

As for the OrderID (grabtree?) I might have gotten a bit ahead of myself... what's the event trigger to know when the order takes place? I tried with Unit is Issued an Order Targeting an Object but that doesn't work... maybe because no order is actively being issued and it's just... happening?

I also tried with detecting if the Wisp's gather skill triggers with Unit Starts the Effect of an Ability, but that's a bust as well.

Any ideas there?
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
Made the changes, and the errors are gone, though now the unit isn't moving at all :(

As for the OrderID (grabtree?) I might have gotten a bit ahead of myself... what's the event trigger to know when the order takes place? I tried with Unit is Issued an Order Targeting an Object but that doesn't work... maybe because no order is actively being issued and it's just... happening?

I also tried with detecting if the Wisp's gather skill triggers with Unit Starts the Effect of an Ability, but that's a bust as well.

Any ideas there?

Right. You should change from GetEnumDestructable to GetFilterDestructable in my function.

I think you should try GetIssuedOrderId() in the trigger. Sorry but I am using a phone atm so I can't write any code :(
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
Woo! Dead trees are no longer being targeted! :D

Still not quite sure in what context to utilise the GetIssuedOrderId()
I'll wait until you have a better way of typing code. No rush :)

  • Untitled Trigger 001
    • Events
      • Unit - A unit Is issued an order targeting an object
    • Conditions
    • Actions
      • Custom script: if GetIssuedOrderId() == <order_id> then
      • -------- Your trigger lines here --------
      • Custom script: endif
So you can replace the <order_id> part with the order you need and the lines inside the custom scripts will be executed.
 
That still didn't work but I think I found a way around it which may use a lot of hashtables lol (well, that method of lumber-harvesting doesn't require a lot of workers so I think we'll be safe from the 255 limit even if there are 12 players)... unless I can use custom values properly... I'll try something and give an update.

Also is there a way I can filter out a specific destructible from being selected? Like one stored in a variable?

Side question: what is the highest number of values a hastable can store?
 
Level 16
Joined
Dec 15, 2011
Messages
1,423
That still didn't work but I think I found a way around it which may use a lot of hashtables lol (well, that method of lumber-harvesting doesn't require a lot of workers so I think we'll be safe from the 255 limit even if there are 12 players)... unless I can use custom values properly... I'll try something and give an update.

Also is there a way I can filter out a specific destructible from being selected? Like one stored in a variable?

Side question: what is the highest number of values a hastable can store?

What do you mean by "selected"?

Iirc, it is 2^31 - 1 or 2147483647
 
I meant picked, like picked by the GetClosestWidget trigger. I'm trying to see if I can make it ignore trees that are stored in a specific variable. The reasoning here is that when the harvester enters the map, it's ordered to pick a tree to move to. That tree is then stored in a variable which has for array the custom value of the harvester so that when the GetClosestWidget is used again it excludes trees that are equal to udg_Tree[customvalue]. The problem then is, how do I find out what custom value this is? I could just make the library to exclude up to the highest the custom values that are being used on the map (I'm using Bribe's Unit Indexer btw).

Idk if that made any sense lol.
 
Yeah, I should, kinda too lazy to though :p

Btw, how about swapping out the targeted tree for a custom tree that doesn't get targeted? I read in the IsDestructibleTree description that it can target custom destructibles, so maybe there's a way to exclude the later from being picked? (possibly by modifying the IsDestructibleTree library itself)
 
Status
Not open for further replies.
Top