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!
Hi, How to order a unit to go to the nearest specific thing? (something like: specific unit-type, specific terrain-type, nearest region, etc.)
I mean something like we do in pour life:
Event:
A unit gets Covid-19
Action:
Order triggering unit move to nearest hospital
I don't have access to an editor atm, but can answer the method how to do it.
Do you know about memory leaks from thing such as points?
The Kill Nearest Unit link shows you how to find the closest unit from another unit.
You can check distance (real-typed-variable) between 2 points with:
Set distance = (Distance between temp_position and temp_position_2)
But you want to fins the closest terrain-type.
I believe that you will have to search points until you find the correct terrain-type, then order unit to move to that point.
It is easier to search in a grid from top-left to bottom-right and take note of the closest than to do a more effective search (Breadth-first search).
Something along the line of this should work:
Code:
set unit_pos = position of unit( the unit )
set closest_found_point_distance = 99999
for x_integer from -20 to 20
for y_integer from -20 to 20
set temp_x_offset_real = (integer to real (x_integer) * 75)
set temp_y_offset_real = (integer to real (y_integer) * 75)
set temp_pos = Position with offset (unit_pos) offset by x (temp_x_offset_real), y (temp_y_offset_real )
if (<I need to have access to an editor to know what to do here, but temp_pos is the "correct terrain type"
AND distance between unit_pos and temp_pos is less than closest_found_point_distance )
destroy closest_found_point //This is the "old closest point".
closest_found_point_distance = distance between unit_pos and temp_pos is less than closest_found_point_distance
closest_found_point = temp_pos
else
destroy temp_point
if(closest_found_point_distance is less than 99999)
order <unit> to move to closest_found_point
destroy unit_pos
destroy closest_found_point
This searches every 75 range-units (a fairly short distance) for <the correct terrain type>. It only searches 1000 range-units (About the range of a ballista), but can be increased by changing the "20" in the for-loops.
The "75" might be possible to increase, but I don't know how big the smallest texture-patch is in 100 or 200.
I don't have access to an editor atm, but can answer the method how to do it.
Do you know about memory leaks from thing such as points?
The Kill Nearest Unit link shows you how to find the closest unit from another unit.
You can check distance (real-typed-variable) between 2 points with:
Set distance = (Distance between temp_position and temp_position_2)
But you want to fins the closest terrain-type.
I believe that you will have to search points until you find the correct terrain-type, then order unit to move to that point.
It is easier to search in a grid from top-left to bottom-right and take note of the closest than to do a more effective search (Breadth-first search).
Something along the line of this should work:
Code:
set unit_pos = position of unit( the unit )
set closest_found_point_distance = 99999
for x_integer from -20 to 20
for y_integer from -20 to 20
set temp_x_offset_real = (integer to real (x_integer) * 75)
set temp_y_offset_real = (integer to real (y_integer) * 75)
set temp_pos = Position with offset (unit_pos) offset by x (temp_x_offset_real), y (temp_y_offset_real )
if (<I need to have access to an editor to know what to do here, but temp_pos is the "correct terrain type"
AND distance between unit_pos and temp_pos is less than closest_found_point_distance )
destroy closest_found_point //This is the "old closest point".
closest_found_point_distance = distance between unit_pos and temp_pos is less than closest_found_point_distance
closest_found_point = temp_pos
else
destroy temp_point
if(closest_found_point_distance is less than 99999)
order <unit> to move to closest_found_point
destroy unit_pos
destroy closest_found_point
This searches every 75 range-units (a fairly short distance) for <the correct terrain type>. It only searches 1000 range-units (About the range of a ballista), but can be increased by changing the "20" in the for-loops.
The "75" might be possible to increase, but I don't know how big the smallest texture-patch is in 100 or 200.
I really don't know anything from codes, even I don't know GUI well,But I know If you could fix this code in condition part, that would be really great
But this won't cause crash or something? because almost 100 units must get the order just in a single moment.
Look, in my map (that is a copy of the mobile game: Tower Dwellers) buildings spawn units, and must fight against enemies that come from road, and I want something to order units go to road,
and of course they aren't too far from road.
And with your helps till now, I can make it tonight and I will share a 5-wave beta here to use your ideas, if you are interested in it.
Thank you all for your helps, if I get a problem, I will share it here. Thank you again
I really don't know anything from codes, even I don't know GUI well,But I know If you could fix this code in condition part, that would be really great
But this won't cause crash or something? because almost 100 units must get the order just in a single moment.
Unit Group - Pick every unit in (Units within 200.00 of (Position of (Picked unit))) and do (Actions)
Loop - Actions
Set SO_unit_pos = (Position of (Picked unit))
Set SO_leaset_found_distance = 2000.00
For each (Integer SO_x) from -5 to 5, do (Actions)
Loop - Actions
For each (Integer SO_y) from -5 to 5, do (Actions)
Loop - Actions
Set SO_temp_x_offset = (200.00 x (Real(SO_x)))
Set SO_temp_y_offset = (200.00 x (Real(SO_y)))
Set SO_temp_pos = (SO_unit_pos offset by (SO_temp_x_offset, SO_temp_y_offset))
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Terrain type at SO_temp_pos) Equal to Lordaeron Summer - Dirt
(Distance between SO_temp_pos and SO_unit_pos) Less than SO_leaset_found_distance
Then - Actions
Set SO_leaset_found_distance = (Distance between SO_unit_pos and SO_temp_pos)
Set SO_closest_found_point = SO_temp_pos
Else - Actions
Unit - Order (Picked unit) to Attack-Move To SO_closest_found_point
This is what you said with my needs, and it works clean.
When I tried to add those custom scripts, I faced this:
And as I don't know anything from codes and custom scripts, removed them and tested the trigger, and there wasn't any leak till now, but if you know how I can add them for less leak, please tell me how.
And as I don't know anything from codes and custom scripts, removed them and tested the trigger, and there wasn't any leak till now, but if you know how I can add them for less leak, please tell me how.
That's why I asked about if you knew about memory leaks such as those from points in my initial response.
Anyways: Points, along with other things, are created each time you basically gets any point.
If you don't do anything about it, the map will run slower, and slower over time and possibly crash.
What you do about it is to destroy the created location.
Custom script: call RemoveLocation(udg_loc)
This is if your variable name is loc
the "udg_"-part is used for all variables accessible from GUI.
In your case, you would want to use "call RemoveLocation(udg_SO_closest_found_point)"
You need to do something similar for many other things.
For more information, check out a tutorial about it: Memory Leaks
Sorry for not being exact, but I did not have access to an editor.
Also, I see that you check every 200-units in your trigger. @HerlySQR said that the smallest texture patch is 128 (and I'm pretty sure that's correct), meaning that you have the possibility to miss them if you use 200.
But as long as you only search for bigger texture patches, it's ok.
Look, in my map (that is a copy of the mobile game: Tower Dwellers) buildings spawn units, and must fight against enemies that come from road, and I want something to order units go to road,
and of course they aren't too far from road.
And with your helps till now, I can make it tonight and I will share a 5-wave beta here to use your ideas, if you are interested in it.
Thank you all for your helps, if I get a problem, I will share it here. Thank you again
If you only wanna do for your lines (I saw your 2nd map) just find the coordinates of the points of the region of your line, divide it in cells of 128x128 and do the function that @ThompZon said but just for that area using the left-down corner of that area as a initial point.
And for that custom scripts, if you use a variable that you create in the trigger editor you, previously write udg_ in its exact names.
Also, I see that you check every 200-units in your trigger. @HerlySQR said that the smallest texture patch is 128 (and I'm pretty sure that's correct), meaning that you have the possibility to miss them if you use 200.
But as long as you only search for bigger texture patches, it's ok.
Actually I didn't want unit move to edge of terrain, I want they get in, so I set it to 200 for larger grid that has a bigger chance to lead them to the terrain, not its edge.
If you only wanna do for your lines (I saw your 2nd map) just find the coordinates of the points of the region of your line, divide it in cells of 128x128 and do the function that @ThompZon said but just for that area using the left-down corner of that area as a initial point.
And for that custom scripts, if you use a variable that you create in the trigger editor you, previously write udg_ in its exact names.
This for my 3rd map that you will see it in beta forum in 3-5 days.
After reading that link, I understood I knew nothing from leaks, that slowed down my previous maps, but now I think I know enough. Anyway I have some questions:
Unit Group - Pick every unit in (Units of type Barracks) and do (Actions)
This will leak, yeah? And it is permanent? As I read in the guild.
Unit Group - Pick every unit in (Units in (Playable map area) matching ((Unit-type of (Matching unit)) Equal to Barracks)) and do (Actions)
But this one's leak is okay and can destroy by scripts? I mean if you have to use first one, can you replace it with second one and there will not any leak?
Unit - Create 1 Footman for Player 1 (Red) at (Random point in (Playable map area)) facing Default building facing degrees
Will this cause leak just like "Center of Region"?
Set UG_barracks = (Units in (Playable map area) matching ((Unit-type of (Matching unit)) Equal to Barracks))
Unit Group - Pick every unit in UG_barracks and do (Actions)
Loop - Actions
Set UG_barracks_pos = (Position of (Picked unit))
Set UnitNumber = (Number of units in (Units within 575.00 of UG_barracks_pos matching ((Unit-type of (Matching unit)) Equal to Blacksmith)))
Set UnitNumber = (UnitNumber + ((Number of units in (Units within 575.00 of UG_barracks_pos matching ((Unit-type of (Matching unit)) Equal to Archery Range))) x 4))
Set UnitNumber = (UnitNumber + ((Number of units in (Units within 575.00 of UG_barracks_pos matching ((Unit-type of (Matching unit)) Equal to Mage School))) x 13))
Unit - Create 2 UnitByNumber[UnitNumber] for Player 1 (Red) at UG_barracks_pos facing Default building facing degrees
After adding scripts and some changes to get least leak, and testing the trigger, I understood that a short screen stop will cause when the trigger run, so I tried changing grid size:
with 126 * 10 it cause something about 4-5 second screen stop
with 256 * 4 that was 1-2 second
with 512 * 2 that is about 0.5 second
512 * 2 is good and seems normal but you know it's really a big number for grid,
Is there any other way to make that stop shorter?
This trigger, to do the search once for each barracks, for each unit on the map(!!), search nearby terrain, order it to attack-move to pos.
So if you have many barracks, you check each unit on the map one time for each barracks!
Maybe you get (newly created) units near the barracks instead of using ALL units in Playable map area? (I.E. "Units in range 350 (or something like that) from UG_barracks_pos"
Maybe you can do ONE search for all units near a barracks and let them attack-move to the same spot? (I.E. move the "search"-loops outside the UG_moving_units)
If you have many units on the map, this will be a very significant performance improvement.
Also, you don't destroy the UG_bacckars unit-group atm.
Also the " (Units within 575.00 of UG_barracks_pos matching X)" will create a new unit-group that you will leak.
You should set this to a variable that you can destroy instead of having it on "the same line" as something else (looking at the "Set UnitNumber"-part)
Maybe you can do ONE search for all units near a barracks and let them attack-move to the same spot? (I.E. move the "search"-loops outside the UG_moving_units)
This one is same as old one but only with some minor changes, this one works, and even with 256 * 4 for grid it doesn't stop screen as I can see. Please take a look to this too for leaks.
As I said, Second one is clean and nice and I can use it, but now as much as I want to create this map, I want to know why that trigger doesn't work?
Ok. So a Point is <something in the memory> that is created whenever you create a point ("position of unit", "center of region", or anything else).
A variable actually only points to that memory. It is NOT the content of that memory.
So when you find a new closest point (in the "if" in the "search-for-terrain-type"-part), your "SO_closest_found_point" points to the same memory as "SO_temp_pos", then you destroy/release that memory.
This destroys/release the memory for both variables that now points to nothing.
The solution is to remove the "Custom script: call RemoveLocation(udg_SO_temp_pos)" there.
Because you keep track of, and destory the "SO_closest_found_point" before you set it to a new variable, you won't leak.
This one is same as old one but only with some minor changes, this one works, and even with 256 * 4 for grid it doesn't stop screen as I can see. Please take a look to this too for leaks.
You destroy "UG_moving_units" inside the loop where you loop over the unit group, this should probably cause something strange to happen... It should probably be moved after the loop.
You also don't clean "SO_temp_pos" in this one. Be careful how you do it or you will have the same issue as the other version.
You destroy "UG_moving_units" inside the loop where you loop over the unit group, this should probably cause something strange to happen... It should probably be moved after the loop.
It worked, as you said, but I have a question: It's leak will remove by destroying closest found point? I mean in your image if we destroy super important point in 3rd part, it will destroy all of it too?
Now both versions working, which one will cause less lag or leak? Actually there isn't any difference for me that 2 units move together or not, but lag is a important thing and I have to choose better version, which one is it?
It's leak will remove by destroying closest found point? I mean in your image if we destroy super important point in 3rd part, it will destroy all of it too?
Now both versions working, which one will cause less lag or leak? Actually there isn't any difference for me that 2 units move together or not, but lag is a important thing and I have to choose better version, which one is it?
I'd say the first version should be less laggy (because you reduce the number of searches).
All leaks should be taken care of, so both should be fine in that regard.
You mean when you have a jass-function that only has "return Location(435.00, 985.00)" in it?
Well... It creates and returns a new location (aka Point) to you. You will have to deal with it when you are finished with it, or else it will leak, yes.
Good question. It seems like the function that returns a point returns a NEW Location with the coordinates of the start-location.
If you're fine with only the X, Y reals of the start location, it's possible to get them "leakless" (calling funtions that returns reals instead of locations)
This means that you get a location that you will have to clean-up or it will leak.
This also means that if you destroy that location, you are not destroying the start-location (So I guess it's a good thing).
You mean when you have a jass-function that only has "return Location(435.00, 985.00)" in it?
Well... It creates and returns a new location (aka Point) to you. You will have to deal with it when you are finished with it, or else it will leak, yes.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.