| 02-23-2004, 11:21 PM | #1 |
How do you choose the unit closest to another? |
| 02-24-2004, 01:10 AM | #2 |
Thanks for posting this for me... I didn't think it was THAT hard... |
| 02-24-2004, 01:25 AM | #3 | |
Quote:
Whats with you latly linkmaster!? ur spamming and crap all the time for the past few days... lol as for the question, I would run a loop that keeps searching in differnt ranges until it finds a unit. |
| 02-24-2004, 01:32 AM | #4 |
With difficulty. There is a function in the JASS vault, but it leaks memory... I think I'll write a new function to detect the closest unit. |
| 02-24-2004, 01:34 AM | #5 |
is my method really leaky or sumthing? I would expect it to lag though..., well it depends on the range intervals. |
| 02-24-2004, 01:44 AM | #6 |
In GUI please... lol. |
| 02-24-2004, 01:45 AM | #7 |
If the only way is in Jass, then it might be wise to accept it... |
| 02-24-2004, 01:58 AM | #8 |
I will go as far as Custom Text Action... |
| 02-24-2004, 02:18 AM | #9 |
Okay, this sort of problem just cries out for JASS, so I wrote a function. I'll explain exactly how to use it too. Code:
function FindClosestUnit takes group g, real x, real y, boolean destroyGroup returns unit
local real dx
local real dy
local group tempGroup
local real maxDist=999999.0
local real dist
local unit u = null
local unit closest = null
if (destroyGroup == false) then
set tempGroup = CreateGroup()
call GroupAddGroup(g, tempGroup)
else
set tempGroup = g
endif
loop
set u = FirstOfGroup(tempGroup)
call GroupRemoveUnit(tempGroup, u)
exitwhen (u == null)
set dx = GetUnitX(u) - x
set dy = GetUnitY(u) - y
set dist = SquareRoot(dx*dx+dy*dy)
if (dist < maxDist) then
set closest = u
set maxDist = dist
endif
endloop
call DestroyGroup(tempGroup)
return closest
endfunction
function FindClosestUnitLoc takes group g, location loc, boolean destroyGroup returns unit
return FindClosestUnit(g,GetLocationX(loc),GetLocationY(loc),destroyGroup)
endfunctionCopy-paste the above code into the map header, that is, click on the map name at the top of the list of triggers, you'll get a nice empty box titled "Custom Script Code", paste it there. Now for the trigger itself you should create some global variables, I'm going to assume: TempGroup (Unit Group) TempLoc (Point) TempUnit (Unit) Now to find the unit in TempGroup closest to TempLoc and put it in TempUnit simply use the following Custom Script action: Code:
Custom script: set udg_TempUnit = FindClosestUnitLoc(udg_TempGroup,udg_TempLoc,false) For example, if you wanted to do a corpse explosion ability: Code:
Actions
Set TempLoc = (Target point of ability being cast)
Set TempGroup = (Units within 600.00 of TempLoc matching (((Matching unit) is alive) Equal to False))
Custom script: set udg_TempUnit = FindClosestUnitLoc(udg_TempGroup,udg_TempLoc,true)
Unit - Replace TempUnit with a Goblin Sapper using The new unit's default life and mana
Unit - Order (Last replaced unit) to Neutral - Kaboom! (Position of (Last replaced unit))Edit: For interested users the "true/false" part means whether you want the unit group to be destroyed true = do destroy, false = don't destroy I want to use it again!. If in doubt, use "false" Edit2: Fixed the code to make the unit group destroying behaivour work as stated. |
| 02-24-2004, 02:40 AM | #10 |
Could set it so it picks the 5 closest units within 1500 of the main point and then runs another trigger? The other trigger is so the rest of the spell can be done in GUI. Thanks for your help. |
| 02-24-2004, 03:31 AM | #11 |
First I want to mention I made a couple of bug fixes to the code I posted above. To get the 5 closest, basically just keep rerun the function 5 times, removing the closest unit from the main group each time. The trigger below will use my function to put the 5 closest units in the variable ClosestUnits Code:
Actions
Set TempLoc = (Your Point Here)
Set TempGroup = (Units within 1500.00 of TempLoc Matching (Your condition here))
Unit Group - Remove all units from ClosestUnits
For each (Integer A) from 1 to 5, do (Actions)
Loop - Actions
Custom script: set udg_TempUnit = FindClosestUnitLoc(udg_TempGroup,udg_TempLoc,false)
Unit Group - Add TempUnit to ClosestUnits
Unit Group - Remove TempUnit from TempGroup
-------- Informative Debug Message --------
Unit Group - Pick every unit in ClosestUnits and do (Actions)
Loop - Actions
Game - Display to (All players) the text: (String((Unit-type of (Picked unit))))
-------- The 5 units are now in ClosestUnits -------- |
| 02-24-2004, 04:06 AM | #12 |
Grater I understood your function up to this point. Code:
set dx = GetUnitX(u) - x
set dy = GetUnitY(u) - yWhat are the x and y? they aren't local reals declared by you, are they something that just exists in JASS? |
| 02-24-2004, 04:18 AM | #13 |
They are the parameters the function takes, you'll note there are actually two functions: FindClosestUnit : that takes co-ordinates in the form of two reals and FindClosestUnitLoc which is a fluff function. Some JASS users (including myself) prefer to not use location variables at all for many tasks, but it's inconvienent to use two reals in the GUI. |
| 02-24-2004, 04:23 AM | #14 |
I'm sorry for asking such a stupid question. I should have looked at parameters taken. I am going to go shoot myself now, j/k. I really do feel dumb, I know that stuff. Geez. *slaps himself* |
| 02-24-2004, 11:34 AM | #15 |
It's not too hard to find just the closest unit in GUI. But if you ask me to find the 5 closets units one by one, i'd be pressed :) Edit: Added support for finding the 5 closest units. Here's to find just the closest: Code:
Closest unit
Events
Conditions
Actions
Set [color=red]Caster[/color] = (Triggering unit)
Set [color=red]ClosestUnit[/color] = (Random unit from (Units within 1500.00 of (Position of [color=red]Caster[/color]) matching ((Matching unit) Not equal to [color=red]Caster[/color])))
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 1500.00 of (Position of [color=red]Caster[/color]) matching ((Matching unit) Not equal to [color=red]Caster[/color])) and do (Actions)
Loop - Actions
If ((Distance between (Position of [color=red]Caster[/color]) and (Position of (Picked unit))) Less than (Distance between (Position of [color=red]Caster[/color]) and (Position of [color=red]ClosestUnit[/color]))) then do (Set [color=red]ClosestUnit[/color] = (Picked unit)) else do (Do nothing)5 closest units: Code:
Closest 5 units
Events
Conditions
Actions
Unit Group - Remove all units from [color=red]AddingGroup[/color]
Set [color=red]Caster[/color] = (Triggering unit)
For each (Integer A) from 1 to 5, do (Actions)
Loop - Actions
Set [color=red]ClosestUnit[/color] = (Random unit from (Units within 1500.00 of (Position of [color=red]Caster[/color]) matching ((Matching unit) Not equal to [color=red]Caster[/color] and (((Matching unit) is in [color=red]AddingGroup[/color]) Equal to False))))
Custom script: set bj_wantDestroyGroup = true
Unit Group - Pick every unit in (Units within 1500.00 of (Position of [color=red]Caster[/color]) matching ((Matching unit) Not equal to [color=red]Caster[/color] and (((Matching unit) is in [color=red]AddingGroup[/color]) Equal to False))) and do (Actions)
Loop - Actions
If ((Distance between (Position of [color=red]Caster[/color]) and (Position of (Picked unit))) Less than (Distance between (Position of [color=red]Caster[/color]) and (Position of [color=red]ClosestUnit[/color]))) then do (Set [color=red]ClosestUnit[/color] = (Picked unit)) else do (Do nothing)
Unit Group - Add [color=red]ClosestUnit[/color] to [color=red]AddingGroup[/color] |
