| 08-21-2006, 09:47 PM | #1 |
Okay, made a 'GetNearestUnitMatching()' function for a few spells. Here is the function: JASS:function GetNearestUnitMatching takes real range, location source, boolexpr cond returns unit local group g=CreateGroup() local location ul local unit u local unit n local real dist call GroupEnumUnitsInRangeOfLoc(g,source,range,cond) loop set u=FirstOfGroup(g) exitwhen u==null set ul=GetUnitLoc(u) set dist=DistanceBetweenPoints(source,ul) call RemoveLocation(ul) if dist<range then set n=u set range=dist endif call GroupRemoveUnit(g,u) endloop call DestroyGroup(g) set ul=null set g=null set u=null return n endfunction And here is the quick test: Trigger: It works great the first time I press Esc, but after that, it gets all screwy and units won't die when they are in certain areas, or they only die when in the range on certain coordinates. It's really bothering me and I'm not sure why it's happening. |
| 08-21-2006, 10:08 PM | #2 |
Probably because it's hitting dead units and trying to kill them again. You have to explicitly check for GetWidgetLife(u) > .405. BTW you can fix that set to null leak with a little return bugging. Add a local integer ni and change the bottom to something that resembles JASS:set ul=null set g=null set u=null set ni = HtoI(n) set n = null return ni return null endfunction |
| 08-21-2006, 10:17 PM | #3 | |
Quote:
Ah thanks. Can't believe I forgot to skip dead units, especially when I just did a corpse explosion spell >_>. And I was wondering about the return leak, do I have to return an integer now, and yeah,,,I can't grasp it I'm brain dead now... ADD: Okay, now it works once, then it killed a unit when there was obviously another unit closer to the center(floating text at center). Then after those two, it no longer killed any of the units. This is really bugging me now... |
| 08-21-2006, 10:31 PM | #4 |
you could also try either adding takes unit n and always pass it as null, or set a global used by blizzard.j (bj_lastCreatedUnit etc) to n and return it instead using x, y values instead of locations might also be a good idea, if you feel like improving |
| 08-21-2006, 10:43 PM | #5 |
>>you could also try either adding takes unit n and always pass it as null, or set a global used by blizzard.j (bj_lastCreatedUnit etc) to n and return it instead I don't see how this would fix the annoying bug :( >>using x, y values instead of locations might also be a good idea, if you feel like improving Locations are faster :) |
| 08-21-2006, 10:57 PM | #6 |
H2I is much slower than just doing this JASS:set bj_lastCreatedUnit = n set n = null return bj_lastCreatedUnit endfunction You hadn't edited your post when I read the thread, try using a lower value for range. ok, how could locations possibly be faster? first you create a location, hen you pass DistanceBetweenPoints() , which you'll see is a bj function that uses GetLocationX/Y to do the calculation, then you destroy the location |
| 08-21-2006, 11:09 PM | #7 | |
Quote:
Locations are still faster, just maybe not in this function . Tell the truth, I didn't want to spend more than 2 minutes on this, so I used locations and a bj >_>. I'll fix now. |
| 08-24-2006, 03:10 PM | #8 |
Okay, I got really annoyed so I just remade the function. JASS:function GetNearestUnitMatching takes real sourceX, real sourceY, real range, boolexpr cond, boolean considerdead returns unit local group g=CreateGroup() local unit current local unit nearest local real currentX local real currentY local real dist call GroupEnumUnitsInRange(g,sourceX,sourceY,range,cond) loop set current=FirstOfGroup(g) exitwhen current==null set currentX=GetWidgetX(current)-sourceX set currentY=GetWidgetY(current)-sourceY set dist=SquareRoot(currentX*currentX+currentY*currentY) if dist<=range then set range=dist if considerdead==false and GetWidgetLife(current)>0 then set nearest=current else set nearest=current endif endif call GroupRemoveUnit(g,current) endloop set bj_lastHauntedGoldMine=nearest call DestroyGroup(g) set g=null set current=null set nearest=null return bj_lastHauntedGoldMine endfunction Trigger: It works MUCH better, but it still needs some prodding to get it to work all the time. It seems that if a unit is standing still, nothing happens to it, but when I make it move and press ESC it dies. So, can someone possibly tell me why it doesn't work 100% of the time, because as of now I don't trust it with triggers that need to function correctly. |
| 08-24-2006, 03:23 PM | #9 |
I see no actual bug, but you have something weird there. You set nearest = current whether current is alive or dead (and you must check for GetWidgetLife() > 0.405 for living/dead). You can also make it more efficient by removing the squareroot. Before your loop, set range = range * range and then remove the SquareRoot function. |
| 08-24-2006, 03:32 PM | #10 |
That bit about the "GetWidgetLife() > 0.405" always intrigued me.. Does that mean checking if "GetUnitState(u, UNIT_STATE_LIFE) > 0" is entirely innaccurate? Sorry if this seems slightly off-topic, but it just strikes me as odd. Is .405 the cutoff where WC3 registers a unit as dead? |
| 08-24-2006, 03:32 PM | #11 | ||
Quote:
JASS:if considerdead==false and GetWidgetLife(current)>0.405 then set nearest=current elseif considerdead set nearest=current endif Quote:
It still doesn't work 100% of the time either way. Maybe someone can put it into a test map, and see if you can find the bug. It would be much appreciated! |
| 08-24-2006, 03:33 PM | #12 | |
I dont see why this function should have the GetWidgetLife() > 0.405 anyway. It should be in the conditionfunc, not inside the function. You may want to get the closest corpse once, and you would not be able to use this func. (Or, you can I just saw, but a boolean for that is... well.. not a good way ithink) Quote:
|
| 08-24-2006, 03:35 PM | #13 | |
Quote:
Yes. No idea why, but it is. Zomg infrane made teh ninja editz! |
| 08-24-2006, 03:37 PM | #14 |
That's so weird... Oh well, guess I should go update my map to adjust. :/ Thanks you two. Actually.. Another question. Does it matter if I use GetWidgetLife(u) or GetUnitState(u, UNIT_STATE_LIFE)? |
| 08-24-2006, 03:41 PM | #15 |
No. I would think GetWidgetLife could be a little faster, due to excluding checks to make sure that the handle is a unit, but that is only a possibility. If there is any difference, it is negligible anyway. |
