• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

KB3D - Knock back 3D

Status
Not open for further replies.
The System has 180+ comments! within just 12 days!!
*Ahem* Just like any other WEHZ group thread, KB3D got some off topic comments about japan, how the day was, and other things. So the number of comments don't really make it popular.

Anyways, Jad, go finish that function. I need it. Thanks.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
JASS:
function GetNearestUnitInGroupFromXY takes real x1, real y1, group g returns unit
    local unit u=FirstOfGroup(g)
    local real x2=GetUnitX(u)-x1
    local real y2=GetUnitY(u)-y1
    local real dist1=SquareRoot(x2*x2+y2*y2)
    local real dist2
    
    set bj_ghoul[0]=u // Replace with a global variable you defined
    
    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        set x2=GetUnitX(u)-x1
        set y2=GetUnitY(u)-y1
        set dist2=SquareRoot(x2*x2+y2*y2)
        if (dist1>dist2) then
            set dist1=dist2
            set bj_ghoul[0]=u // Replace with a global variable you defined
        endif
        call GroupRemoveUnit(g,u)
    endloop
   
    set u=null
    return bj_ghoul[0] // Replace with a global variable you defined
endfunction

EDIT: I still don't like FirstOfGroup loops, there's a critical bug with that method but it doesn't affect instant groups like this one.
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
can't it be like this:
JASS:
function GetNearestUnitInGroupFromXY takes real x1, real y1, group g returns unit
    local unit u=FirstOfGroup(g)
    local real x2=GetUnitX(u)-x1
    local real y2=GetUnitY(u)-y1
    local real dist1=SquareRoot(x2*x2 + y2*y2) // there should be a 'space' here to prevent the (x2*x2) to be added to y2 and then the sum will be multiplied by y2
    local real dist2
    local unit U=u
   
    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        set x2=GetUnitX(u)-x1
        set y2=GetUnitY(u)-y1
        set dist2=SquareRoot(x2*x2+y2*y2)
        if (dist1>dist2) then
            set dist1=dist2
            set U=u
        endif
        call GroupRemoveUnit(g,u)
    endloop
   
    set u=null
    return U
endfunction
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
You don't need to initialize dist2 upon declaration, it's initialized in the loop. And U will leak the reference (handle id) it's holding, you need to use a global variable to not leak the reference.

EDIT: Error's like that occur if you use the variable in math ops or conditional statements. May I ask who taught you that?
EDIT: No spaces are needed, multiplication and division is always evaluated first before addition and subtraction. I remember that's called precedence, I believe this is also true for c and c++.
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
I edited the post, removing the dist 2 init :p
okay for the U
I saw in the JPAG i think bribe saying that maths operations that are separated by a space will execute last, but maybe it will act like you said

maybe like this:
JASS:
function GetNearestUnitInGroupFromXY takes unit U, real x1, real y1, group g returns unit
    local unit u=FirstOfGroup(g)
    local real x2=GetUnitX(u)-x1
    local real y2=GetUnitY(u)-y1
    local real dist1=SquareRoot(x2*x2 + y2*y2)
    local real dist2
   
    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        set x2=GetUnitX(u)-x1
        set y2=GetUnitY(u)-y1
        set dist2=SquareRoot(x2*x2+y2*y2)
        if (dist1>dist2) then
            set dist1=dist2
            set U=u
        endif
        call GroupRemoveUnit(g,u)
    endloop
   
    set u=null
    return U
endfunction

function Call takes group g returns nothing
    local unit U
    local real x = 0
    local real y = 0
    local unit u = GetNearestUnitInGroupFromXY(U, x, y, g)
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Not that, JPAG standard suggests that you provide spaces in them for readability, so you should follow it if you're going to submit it here.

JASS:
function Call takes group g returns nothing
    local real x = 0
    local real y = 0
    local unit u = GetNearestUnitInGroupFromXY(u, x, y, g)

That's valid too, one less variable. If only jass allowed pointers lol.

EDIT: yeah, I forgot to tell you in my previous post that you should also initialize variables that are going to be passed to functions (passed as arguments). Malhorne must be busy...
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
Here:
JASS:
// First unit argument can be any null unit
// Final argument group (g) is the group where the function is called (something like this [the explanation]
function GetNearestUnitInGroupFromXY takes unit U, real x1, real y1, group g returns unit
    local unit u=FirstOfGroup(g)
    local real x2=GetUnitX(u)-x1
    local real y2=GetUnitY(u)-y1
    local real dist1=SquareRoot(x2*x2 + y2*y2)
    local real dist2
   
    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        set x2=GetUnitX(u)-x1
        set y2=GetUnitY(u)-y1
        set dist2=SquareRoot(x2*x2+y2*y2)
        if (dist1>dist2) then
            set dist1=dist2
            set U=u
        endif
        call GroupRemoveUnit(g,u)
    endloop
   
    set u=null
    return U
endfunction

//Example Usage:

function Call takes group g returns nothing
    local unit U
    local real x = 0
    local real y = 0
    set U = GetNearestUnitInGroupFromXY(U,x,y,g)
endfunction
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
set dist2=SquareRoot(x2*x2 + y2*y2) for the JPAG stuff.

EDIT: You forgot this:
JASS:
    local real dist2
    set U=FirstOfGroup(g)
    call GroupRemoveUnit(g,u)
    loop
        set u=FirstOfGroup(g)

You need to set the first unit, so that when it is the nearest, it won't return null, I added the remove from group call to avoid redundancy.
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
this can easily be done also by this:
JASS:
// First unit argument can be any null unit
// Final argument group (g) is the group where the function is called (something like this [the explanation]
function GetNearestUnitInGroupFromXY takes unit U, real x1, real y1, group g returns unit
    local unit u=FirstOfGroup(g)
    local real x2=GetUnitX(u)-x1
    local real y2=GetUnitY(u)-y1
    local real dist1=9999999999
    local real dist2
   
    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        set x2=GetUnitX(u)-x1
        set y2=GetUnitY(u)-y1
        set dist2=SquareRoot(x2*x2+y2*y2)
        if (dist1>dist2) then
            set dist1=dist2
            set U=u
        endif
        call GroupRemoveUnit(g,u)
    endloop
   
    set u=null
    return U
endfunction

//Example Usage:

function Call takes group g returns nothing
    local unit U
    local real x = 0
    local real y = 0
    set U = GetNearestUnitInGroupFromXY(U,x,y,g)
endfunction
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
My solution just looks ugly since you need to pick the first unit as the default choice, but in truth it doesn't do a needless comparison.

If you use that one, the first comparison is useless(this was the needless comparison I was talking about), as it will always be set as the first nearest unit. It just looks clean but it actually isn't.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Yes, you're wrong, the loop will actually loop N-1 times in the group list, while that thing would loop N times.

lets say the group has 5 units.

my method:
  1. compute dist; 1st unit is default;
  2. loop
  3. compute dist; compare 1 to 2
  4. compute dist; compare 1 to 3
  5. compute dist; compare 1 to 4
  6. compute dist; compare 1 to 5

that method:
  1. set dist=9999999999
  2. loop
  3. compute dist; compare 9999999 to 1; set 1 as default
  4. compute dist; compare 1 to 2
  5. compute dist; compare 1 to 3
  6. compute dist; compare 1 to 4
  7. compute dist; compare 1 to 5

You've wasted one comparison operation. Yes, I was a speed freak in my youth.

EDIT: Oh I forgot to add that the second method also wastes a set operation, you've set dist1 to 9999999.

JASS:
function GetNearestUnitInGroupFromXY takes unit U, real x1, real y1, group g returns unit
    local unit u=FirstOfGroup(g)
    local real x2=GetUnitX(u)-x1
    local real y2=GetUnitY(u)-y1
    local real dist1=SquareRoot(x2*x2 + y2*y2)
    local real dist2

    set U=u
    call GroupRemoveUnit(g,u)

    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        set x2=GetUnitX(u)-x1
        set y2=GetUnitY(u)-y1
        set dist2=SquareRoot(x2*x2 + y2*y2)
        if (dist1>dist2) then
            set dist1=dist2
            set U=u
        endif
        call GroupRemoveUnit(g,u)
    endloop
   
    set u=null
    return U
endfunction

//Example Usage:

function Call takes group g returns nothing
    local unit U
    local real x = 0
    local real y = 0
    set U = GetNearestUnitInGroupFromXY(U,x,y,g)
endfunction
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Nah, but you can if you want to, I revised it:
JASS:
function GetNearestUnitInGroupFromXY takes unit U, real x1, real y1, group g returns unit
    local unit u=FirstOfGroup(g)
    local real x2=GetUnitX(u)-x1
    local real y2=GetUnitY(u)-y1
    local real dist1=SquareRoot(x2*x2 + y2*y2)
    local real dist2

    set U=u
    call GroupRemoveUnit(g,u)

    loop
        set u=FirstOfGroup(g)
        exitwhen u==null
        set x2=GetUnitX(u)-x1
        set y2=GetUnitY(u)-y1
        set dist2=SquareRoot(x2*x2 + y2*y2)
        if (dist1>dist2) then
            set dist1=dist2
            set U=u
        endif
        call GroupRemoveUnit(g,u)
    endloop
   
    set u=null
    return U
endfunction

//Example Usage:

function Call takes group g returns nothing
    local unit U
    local real x = 0
    local real y = 0
    set U = GetNearestUnitInGroupFromXY(U,x,y,g)
endfunction
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Could you post the error here? I was serious when I said there were no errors when I tried using it.
 
Level 16
Joined
Jul 31, 2012
Messages
2,217
okay:
From KB3D v. 1.7.1
vtNTZfl.png

from KB3D v. 1.8.0 Beta
xbij.png
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
what loop problems? The map I attached has none when I save it. Here's the map I attached on the thread...

EDIT: I'm using the latest version of warcraft III.
 
Status
Not open for further replies.
Top