HomeUser Control Panel (unavailable in archive)ForumsTutorialsArt GalleryResourcesMaps

Stupid JASS script seeming to have a timer on it, its weird. help

02-26-2004, 11:28 PM#1
Narwanza
Here is my little JASS script to find the closest unit, and it works beautifully, the first time. For some reason it is very very spotty after the first use, sometimes it does return sometimes it doesn't. Can anyone help me figure out why its not returning properly?

Code:
function GetClosestUnit takes unit who, group pool returns unit
    local location temploc = GetUnitLoc(who)
    local real x = 0
    local real distance = 9999999.0
    local location temploc01 = null
    local unit u = null
    local unit actualunit = null
    local real distance01 = 0
    call GroupRemoveGroup(pool, GetUnitsOfPlayerAll(GetOwningPlayer(who)))
    call GroupRemoveUnitSimple(who, pool)
    loop
        set u = FirstOfGroup(pool)
        exitwhen u == null
        set temploc01 = GetUnitLoc(u)
        call GroupRemoveUnitSimple(u, pool)
        set x = DistanceBetweenPoints(temploc01,temploc)
        set distance01 = x
        if (distance01 < distance) then
            set distance = x
            set actualunit = u
        endif
        call RemoveLocation(temploc01)
        set temploc01 = null
        set u = null
    endloop
    call DestroyGroup(pool)
    call RemoveLocation(temploc)
    set temploc = null
    set distance = 9999999.0
    set pool = null
    return actualunit
endfunction

[edit] oh and how does FirstOfGroup() vary from GroupPickRandomUnit()?
02-27-2004, 12:34 AM#2
Vidstige
FirstOfGroup is a native from common.j, the otherone is probably from Blizzard.j. When I handle groups of units I usually use these functions form common.j.
Code:
native CreateGroup                          takes nothing returns group
native DestroyGroup                         takes group whichGroup returns nothing
native GroupAddUnit                         takes group whichGroup, unit whichUnit returns nothing
native GroupRemoveUnit                      takes group whichGroup, unit whichUnit returns nothing
native GroupClear                           takes group whichGroup returns nothing
native FirstOfGroup                         takes group whichGroup returns unit

FirstOfGroup probably returns the same unit if called multiple times, GroupPickRandomUnit probably returns different units each time.
02-27-2004, 12:41 AM#3
dataangel
FirstOfGroup is consistent, GroupPickRandomUnit is not.

That said, the reason your script is probably failing is because there's a maximum amount of time War3 will let a trigger run before it assumes the trigger has fallen into an infinite loop and kills it. Your function, being rather cpu intensive, probably goes over it. However, sing FirstOfGroup would optimize your function a ton, so I'd try it.
02-27-2004, 02:23 AM#4
Narwanza
Thanks dataangel, that really helped clear it up. I fixed it up above. There is one thing that really mistyfies me though, it finds the closest unit in a fraction of a second, but it won't work again unit about 2 seconds after it has been used. It would seem that after it had found the closest unit, wouldn't it take a fraction of a second to run the rest?

[edit]Umm, you know the filter units owned by triggering unit part? For some reason it isn't working and I can't figure out why.

[edit#2]I optimized the function and got it down to 1 function now, but it still has the same problem of about a 2 second cooldown.
02-27-2004, 10:12 AM#5
Cubasis
I can only see a few qualms:

1. This function is not neeeded: call GroupRemoveUnitSimple(who, pool)

2. You're setting the Distance between the units to a integer value before setting it to real value, thus, losing some precision (btw, why didn't you just set it directly to the real variable?). However, you may have some wacky reason for this.

3. You are Destroying the Group that is passed to this....this is not reccomended, atleast if you wanna release this function, as then if a user passes to it some group he's using for other things, it gets destroyed. So, unless this is only for your private use and you know about this, I would reccomend you to only Destroy the group if some boolean is set to true (like bj_wantdestroygroup or sumtin)

However, i can't see why it wouldn't work the second time....unless you're reusing the same groups, which you Destroy after the first time.

Cubasis
02-27-2004, 09:19 PM#6
Narwanza
1. Sorry about that mistake. I imported it into WC last night to see if it had improved performance, and it gave me the integer != real bit, but it was late so I forgot to change the integer to a real here.

2. That function is needed or else the the unit will always be picked. Now if the person passing args was smart and removed him before hand then it won't matter, but if you just pass GetUnitsWithinRangeOfLocAll() then you have a problem.

3. I fixed this by creating a new local group.

But after all of this, for some stupid reason, it still takes about 3 seconds before it will work again. It will always work, but it takes a long time to cooldown. Its stupid. It seems to have some other oddities about it. It seems to 'fire' quicker when I am facing the closest unit, or when I am very close to the unit. The thing that doesn't make sense is, it find the closest unit nearly instantly, but why does it take so long to be called again? The rest of the trigger should be run in a matter of nanoseconds compared to finding the actual unit.
02-27-2004, 11:01 PM#7
Narwanza
I finally found the answer!!!!
Okay, so it is not something to do with my function, it is blizzards fault. I was testing the map unsing heros for some reason and then exploding the closest one. Well, after multiple debugging tests I figured out what the problem is. The heros aren't really gone when you think they are. They last there for about 3 more seconds, so I was using explode on the heros thinking it would immediatly remove them, however it still said that the exploded hero was the closest one for about 3 seconds. My function runs so fast I don't even notice it. I tested it with normal units now, and it runs like a beauty. Does anyone know how to work around the dumb hero thing?
02-27-2004, 11:37 PM#8
weaaddar
use remove unit.
02-28-2004, 09:50 PM#9
Narwanza
Right... that would work in some cases, but since it is going to be a function used in every instance possible where you need it. If there was a hero killed in the area and then you tried to use this, it would return the dying hero. Same way if a unit is killed not exploded, as long as his corpse is there it returns him. I need to find a way around this.

Nevermind about my last post, I figured it out. Thanks for helping me guys.