HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Best way to get nearest/farthest unit

03-04-2005, 05:48 PM#1
Xaran Alamas
What's the best, most efficient way of finding the nearest or furthest unit in relation to another unit? Like for faking resource gathering movement.
Thanks
03-04-2005, 07:50 PM#2
OrcishSpacesuit
Blizzard.j already has this functionality -- if limited strictly to gold mines. I've successfully adapted the functions for use similar to what you want, though.

Here's functions as they are in blizzard.j:
Code:
//===========================================================================
function MeleeEnumFindNearestMine takes nothing returns nothing
    local unit enumUnit = GetEnumUnit()
    local real dist
    local location unitLoc

    if (GetUnitTypeId(enumUnit) == 'ngol') then
        set unitLoc = GetUnitLoc(enumUnit)
        set dist = DistanceBetweenPoints(unitLoc, bj_meleeNearestMineToLoc)
        call RemoveLocation(unitLoc)

        // If this is our first mine, or the closest thusfar, use it instead.
        if (bj_meleeNearestMineDist < 0) or (dist < bj_meleeNearestMineDist) then
            set bj_meleeNearestMine = enumUnit
            set bj_meleeNearestMineDist = dist
        endif
    endif
endfunction

//===========================================================================
function MeleeFindNearestMine takes location src, real range returns unit
    local group nearbyMines

    set bj_meleeNearestMine = null
    set bj_meleeNearestMineDist = -1
    set bj_meleeNearestMineToLoc = src

    set nearbyMines = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(nearbyMines, src, range, null)
    call ForGroup(nearbyMines, function MeleeEnumFindNearestMine)
    call DestroyGroup(nearbyMines)

    return bj_meleeNearestMine
endfunction
So if you want to find the nearest gold mine within 700 distance of your town hall, you do something like:
Code:
local unit myMine
local unit myTownHallLoc
set myTownHallLoc = <code to get the player's start location>
set myMine = MeleeFindNearestMine(myTownHallLoc, 700)
If you just want to find the nearest gold mine, that's enough. If you want to find a different kind of unit, you need to duplicate these functions, changing them so they find what you want.. Here's what you do:
  1. Copy the two functions from Blizzard.j into the general scripting area for your map.
  2. Rename the functions to something like FindNearestPeon and EnumFindNearestPeon.
  3. In the non-enum function, be sure to replace the reference to "MeleeEnumFindNearestMine" in the line that starts "call ForGroup(...." to whatever you named the other function.
  4. If you just want to find one particular kind of unit (say, the nearest footman instead of the nearest gold mine), change the 'ngol' in the enum function, to the code for whatever unit you're trying to seek.
  5. If you want this to be a universal function, where you tell it what kind of unit to seek, you'll need to add a parameter to the non-enum function, and set it up so that the unittype parameter gets passed on to the enum function. And then set it up to use that parameter instead of 'ngol'.
  6. You can leave the rest of the function alone - it's fine to use the bj_meleeNearestMine, etc, variables even if it's not technically mines that you're looking for. For code clarity, though, you may want to rename the local variables to something more applicable.

Now, you asked what's the best, most efficient way. I don't know if that's the best way, but if it's good enough for Blizzard, it'll likely be fine. And it reuses globals that otherwise just take up space. As for the best way to 'fake resource gathering', the best method of that depends on exactly what you're trying to accomplish.
03-04-2005, 08:21 PM#3
Xaran Alamas
Thanks, I'll try it out later.
03-04-2005, 08:32 PM#4
PitzerMike
http://kattana.users.whitehat.dk/script/?script=67
03-04-2005, 08:43 PM#5
Xaran Alamas
I knew there was somewhere I didn't think to check... thanks Mike