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

[JASS] GetClosestUnit problem

Status
Not open for further replies.
Level 13
Joined
Nov 22, 2006
Messages
1,260
Does anyone know what's wrong with this function:

JASS:
scope GetClosestUnit

globals
    player P = Player(0)
    unit closest
endglobals

private function GetClosestUnit_Filter takes nothing returns boolean
    return IsUnitEnemy(GetFilterUnit(), P)
endfunction

function GetClosestUnit takes real x, real y returns unit
    local real md = 1000000000000
    local real d
    local group g = CreateGroup()
    local boolexpr b = Condition(function GetClosestUnit_Filter)
    local unit u
    local real dx
    local real dy
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, b)
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        call GroupRemoveUnit(g, u)
        set dx = GetUnitX(u) - x
        set dy = GetUnitY(u) - y
        if (dx * dx + dy * dy < md) then
            set closest = u
            set md = dx * dx + dy * dy
        endif
    endloop
    call DestroyGroup(g)
    call DestroyBoolExpr(b)
    set g = null
    set b = null
    return closest
endfunction

endscope


I know there's no need for destroying boolexprs that are not generated with And() or Or(), so you don't have to tell me that :).

The error occurs: "uninitialized variable blabla_closest in function GetClosestUnit"
 
Last edited:
Level 13
Joined
Nov 22, 2006
Messages
1,260
Thanks

EDIT: Btw:

PurplePoot said:
I don't see how that would happen, but that's the only explanation I can think of...

Very much possible in my case.

EDIT: It still doesn't work!!! It returns null always! Could you maybe post a working GetClosestUnit function in the JASS functions Pooty? I think that's a very basic and useful JASS function.
 
Last edited:
Level 13
Joined
Nov 22, 2006
Messages
1,260
Actually, on my map, the maximum number of units would be around 8, so I guess using SquareRoot isn't so bad. And also, I don't completely understand that dividing method, but that's probably because I don't know much math.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Actually, on my map, the maximum number of units would be around 8, so I guess using SquareRoot isn't so bad. And also, I don't completely understand that dividing method, but that's probably because I don't know much math.
Well, if 1<2, then 1/10<2/10, right? So if you divide the init value by, say, 10000 (so that it doesn't glitch up), just divide the calculation by the same amount. (10000 or so again)
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
there is a get nearest unit here

That's the code I modified. The code you linked is not working I think, because of this thing:

JASS:
set dist = SquareRoot(dx*dx+dy*dy)
if (dist < maxDist) then
set closest = u
set maxDist = dist


This is a big mistake, because then maxDist is always equal to dist, so if dist changes, maxDist changes also, that's why this is the better way:

JASS:
if (SquareRoot(dx*dx+dy*dy) < maxDist) then
set closest = u
set maxDist = SquareRoot(dx*dx+dy*dy)


Correct me if I'm wrong.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
:p is not always necessary, do you think I was joking?? Huh??

With "K then" I meant "ok, I will avoid using SquareRoot". Though I don't understand the However*2 thing.
Emoticons are very useful to express emotion, due to the lack of tone of voice over the internet >_> (no duh you were joking :p)

As for the K then, I was confused because a lot of people use that as saying "I'll try but I don't get it", or "If you say so", and such.
 
Level 2
Joined
Sep 4, 2006
Messages
29
GUI Trigger?

can someone tell me how to "find the closest unit in unit group" with GUI Triggers? please ^^; i am not really much for learning JASS no matter how much better everyone think it is... -_-
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
When you become a GUI pro, you will start learning JASS eventually, because GUI pros already use a little JASS for cleaning leaks. I know all you GUIers say: "JASS is crap, I'm never gonna use it!", believe me, I was telling the same thing when I was a GUIer. Later you'll want to try JASS and then you won't regret it.

Now, the GetClosestUnit in GUI, no! There is no way to make that completely. The only reason you can't do it is because GUI doesn't have loops (apart from Integer A/B) like JASS does (you will understand why when/if you start learning JASS)
 
Level 2
Joined
Sep 4, 2006
Messages
29
When you become a GUI pro, you will start learning JASS eventually, because GUI pros already use a little JASS for cleaning leaks. I know all you GUIers say: "JASS is crap, I'm never gonna use it!", believe me, I was telling the same thing when I was a GUIer. Later you'll want to try JASS and then you won't regret it.

Now, the GetClosestUnit in GUI, no! There is no way to make that completely. The only reason you can't do it is because GUI doesn't have loops (apart from Integer A/B) like JASS does (you will understand why when/if you start learning JASS)
it's not that i don't like JASS... i just don't understand it that well... and i don't wanna use time looking at it just to find out that the only thing it does is kill a unit is another unit is killed... or the like... and well... i am not a pro GUI user... i am not even a pro map maker... i just think it's fun to make maps... ^^;

well... there's no way to make it in GUI?... well... then what should i do?... here is a link to what i need it for... finding closest unguarded Sheep? maybe someone could help me make it as a JASS code i can use if it is... but well... i don't... well... thanks for the help anyway ^^;
 
Level 13
Joined
Nov 22, 2006
Messages
1,260
This is very simple JASS, I will explain you how to do it, and you won't make a mistake, here's the code:

JASS:
function GetClosestUnit_Filter takes nothing returns boolean
    if udg_Player != null then
        return IsUnitEnemy(GetFilterUnit(), udg_Player)
    endif
    return true
endfunction

function GetClosestUnit takes real x, real y returns nothing
    local real md = 100000
    local real d
    local group g = CreateGroup()
    local boolexpr b = Condition(function GetClosestUnit_Filter)
    local unit u
    local real dx
    local real dy
    call GroupEnumUnitsInRect(g, bj_mapInitialPlayableArea, b)
    loop
        set u = FirstOfGroup(g)
        exitwhen u == null
        call GroupRemoveUnit(g, u)
        set dx = GetUnitX(u) - x
        set dy = GetUnitY(u) - y
        if (dx * dx + dy * dy) / 100000 < md then
            set udg_Closest = u
            set md = (dx * dx + dy * dy) / 100000
        endif
    endloop
    call DestroyGroup(g)
    call DestroyBoolExpr(b)
    set g = null
    set b = null
endfunction


First step: Copy that code in your map header (the map header is the thing on the top of trigger tree. In trigger editor there are folders and triggers, the map header is on the top then, it has a TFT icon and it holds the name of the map (there will be a custom script section there and just copy the code there).

Second step: Make 2 variables: the first one is a player variable named Player, the second one is a unit variable named Closest.

Third step: Now, this step involves just 1 line of custom script! Pretty simple if you ask me :p. Now, what you need to do to detect the closest unit is this:

  • SomeTrigger
  • Events
    • Unit - Casts a spell (for example)
  • Conditions
  • Actions
    • Set Blabla = Triggering unit
    • Set Loc = Position of Blabla
    • Set Player = Player 1
    • Custom script: call GetClosestUnit(GetLocationX(udg_Loc), GetLocationY(udg_Loc))
    • Unit - Order Blabla to Attack Closest
    • Custom script: call RemoveLocation(udg_Loc)

Note: this is just an example trigger.

Explanation:

  • Blabla - the casting unit (in your case, a wolf - a unit from where you need the closest unit)
  • Loc - pretty obvious :p
  • Player - in most of the times, set this variable to the owner of Blabla, because that variable represents the player to which the closest unit must not belong to (so the closest unit will be the enemy of that player)
  • The custom script thingy - I think this is pretty simpe: GetLocationX and GetLocationY are functions that extract the x/y coordinate of the given point (in this case Loc). So in the parenthesis you put the name of your location variable, but with the prefix udg_, because all the global variables have a prefix udg_ in JASS
  • Closest - this is a variable the closest unit is stored to, so the closest unit is in that variable (similar to using "Last created unit" after using "Unit - Create unit"). In this action I just ordered the wolf (in this case) to attack the closest unit
  • The second custom script thingy - I know I said there will be only one custom script line, but this is just for cleaning leaks (you have to put udg_ + variable name again). Put that line in the end of the trigger

Is everything clear? :p

P.S. Just a message to Pooty: Are there any errors in the function?
 
Last edited:
Level 2
Joined
Sep 4, 2006
Messages
29
ooh tanks you

cool! ^^

just... shouldn't the GUI trigger have a "Trigger - Run Trigger" for the JASS trigger? ^^; whatever... i'll play with this when i have the time ^^ thanks
 
Last edited:
Level 13
Joined
Nov 22, 2006
Messages
1,260
You misunderstood something, GetClosestUnit is not a trigger, it's just a function. So the answer would be: no :p

EDIT:
i'll play with this when i have the time ^^

That's what people usually say when they won't do it :), so it doesn't turn up like I was helping you for nothing. Please try it sometime, it's really simple.
 
Level 2
Joined
Sep 4, 2006
Messages
29
busy ^^;

well... it's not that i won't... i just have to find the time... i am busy with school and... well... i rarely do any mapping... ^^;
 
Status
Not open for further replies.
Top