• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

call KillUnit() inside an Enumeration call

Status
Not open for further replies.
Level 1
Joined
May 27, 2011
Messages
3
JASS:
function DoThings takes nothing returns boolean
call KillUnit(GetFilterUnit())
return false
endfunction

function My_Function takes real x, real y returns nothing
call GroupEnumUnitsInRange (udg_GROUP, x, y, 1000.00, Condition(function DoThings))
call DisplayTextToForce( GetPlayersAll(), "Work Done" )
endfunction

It meant to be a trigger that kills all unit in range of 1000 yards around a point with coordinates x, y.

I choose to use "call GroupEnumUnitsInRange (udg_GROUP, x, y, 1000.00, Condition(function DoThings))" to avoid leaks problems in storing the unit in a group. This is a pattern that will run several times (leaking of groups are a unsolved problem for me) in my map and so I prefer not to create billion of leaking groups^^.
Well, the point is it doesen't work. Function "My_Function" starts enumerating units, DoThing takes the first unit (i put around 300 test units at x, y to be sure that THERE ARE units in range), it kills the first GetFilterUnit() and then it stop running and it print out "Work Done". It doesen't kill other units. WorldEditor seams to be too kind^^, but I want a really mass KillUnit()^^.
Why it stops?
Whats wrong with him?

Now I talk more in general.
I found that if I put an operation like KillUnit() or UnitDamageTargetBJ() into a Condition function (like in the example) it leads to a interruption of the Enumerating operation of the generic GroupEnumUnitsIn*Range/Rect/ecc...* function.

Someone has comment, suggestion or whatever about this?
Thanks a lot.
I hope you have not made any stupid mistake.
P.S. Sry for my bad english^^

EDIT 1: main was a generic name. Changed to My_Function.
EDIT 2: there was a syntax error (now correct); GroupEnumUnitInRange() is obviously GroupEnumUnitsInRange()
 
Last edited:
Level 13
Joined
May 11, 2008
Messages
1,198
JASS:
function DoThings takes nothing returns boolean
call KillUnit(GetFilterUnit())
return false
endfunction

function main takes real x, real y returns nothing
call GroupEnumUnitInRange (udg_GROUP, x, y, 1000.00, Condition(function DoThings))
call DisplayTextToForce( GetPlayersAll(), "Work Done" )
endfunction

It meant to be a trigger that kills all unit in range of 1000 yards around a point with coordinates x, y.

I choose to use "call GroupEnumUnitInRange (udg_GROUP, x, y, 1000.00, Condition(function DoThings))" to avoid leaks problems in storing the unit in a group. This is a pattern that will run several times (leaking of groups are a unsolved problem for me) in my map and so I prefer not to create billion of leaking groups^^.
Well, the point is it doesen't work. Function "main" starts enumerating units, DoThing takes the first unit (i put around 300 test units at x, y to be sure that THERE ARE units in range), it kills the first GetFilterUnit() and then it stop running and it print out "Work Done". It doesen't kill other units. WorldEditor seams to be too kind^^, but I want a really mass KillUnit()^^.
Why it stops?
Whats wrong with him?

Now I talk more in general.
I found that if I put an operation like KillUnit() or UnitDamageTargetBJ() into a Condition function (like in the example) it leads to a interruption of the Enumerating operation of the generic GroupEnumUnitsIn*Range/Rect/ecc...* function.

Someone has comment, suggestion or whatever about this?
Thanks a lot.
I hope you have not made any stupid mistake.
P.S. Sry for my bad english^^
i don't think you're using the group correctly...
i mean, is it possible someone wrote a function with that name? because there is no plural in the name. as you can tell by the fact that the function name color, it is as a variable name, or normal text.

also, i can't see your variable list, but does it look anything like this?
group DESTROYGROUP=CreateGroup()
if i do =null or something like that, it wouldn't work.
 
Level 1
Joined
May 27, 2011
Messages
3
EDIT 1: main was a generic name. Changed to My_Function. The problem is not in the function name^^
EDIT 2: there was a syntax error (now correct); GroupEnumUnitInRange() is obviously GroupEnumUnitsInRange()

I've posted a simpler version of my trigger, a sample focused on the topic that I wanted to treat. The point is that if the GetFilterUnit() dies during the Condition(function DoThings) the triggers immediatly stops to check or operate on other units.

Writing this post I've assumed all the variables declared in the correct way somewhere.
I'm quite sure that it isn't a problem of variables or naming function since I've intensively used this kind of triggers.

call DestroyGroup() is a joke. Don't trust him. He lies...

So, did you ever experienced somthing similar? If you try to implement somthing like this, can you see it working?
Thanks again. :)
 
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
The most obvious potential issue would be if you have a trigger that fires on EVENT_UNIT_DEATH or EVENT_PLAYER_UNIT_DEATH that makes use of udg_GROUP. Other than that nothing comes to mind.

(On an unrelated note, I strongly suggest BJDebugMsg("foo") for debugging and Display<Timed>TextToPlayer(GetLocalPlayer(), x, y, <time, > "foo") for displaying messages to all players in a release version).
 
Level 18
Joined
Jan 21, 2006
Messages
2,552
GroupEnumUnitsInRange is found in the vJass library GroupUtils. GroupEnumUnitsInArea is the native function.

You got that quite backwards. The problem was that he had GroupEnumUnitInRange instead of GroupEnumUnitsInRange.

EDIT 2: there was a syntax error (now correct); GroupEnumUnitInRange() is obviously GroupEnumUnitsInRange()

Seems he pointed that out before I could.

I'm curious, what happens if you have it as:

JASS:
function DoThings takes nothing returns boolean
    call KillUnit(GetFilterUnit())
    return false
endfunction

function main takes real x, real y returns nothing
    set udg_GROUP = CreateGroup()
    call GroupEnumUnitInRange (udg_GROUP, x, y, 1000.00, Condition(function DoThings))
    call DisplayTextToForce( GetPlayersAll(), "Work Done" )
endfunction

I also do not know where you're getting your X and Y values. They could be improper. I'm almost certain that you're just not creating your group, because if you were to do this in GUI:

JASS:
function GetUnitsInRangeOfLocMatching takes real radius, location whichLocation, boolexpr filter returns group
    local group g = CreateGroup()
    call GroupEnumUnitsInRangeOfLoc(g, whichLocation, radius, filter)
    call DestroyBoolExpr(filter)
    return g
endfunction

Notice in this function they create the group, and since you're using udg_GROUP I'm going to assume you made it in the variable editor. If that's the case, you're probably unaware that the variables defined there (such as groups) are not instantiated, they're simply memory references.

Well, the point is it doesen't work. Function "My_Function" starts enumerating units, DoThing takes the first unit (i put around 300 test units at x, y to be sure that THERE ARE units in range), it kills the first GetFilterUnit() and then it stop running and it print out "Work Done"

What happens (as PurplePoot suggested) when you put debug messages in the enumeration function? Perhaps the group has not been created and therefore it only takes the first enumerated unit (without having a group handle). If the group has been instantiated then I find it very odd the enumeration would stop. I have re-created the exact same thing you're describing but I didn't experience problems. I'll upload a test-map in a second.

Sorry got side-tracked. This script seems to work fine for me:
JASS:
//! zinc
library KillUnitsIn1000 {
    group G = CreateGroup();
    private function onEscape() {
        GroupEnumUnitsInRange(G, 0, 0, 1000, Filter(function () -> boolean {
            KillUnit(GetFilterUnit());
            return false;
        }));
    }
    private function onInit() {
        trigger t = CreateTrigger();
        TriggerRegisterPlayerEvent(t, Player(0), EVENT_PLAYER_END_CINEMATIC);
        TriggerAddAction(t, function onEscape);
    }
}
//! endzinc

Not really sure why I decided to do it in Zinc, but that is the exact same thing you're doing (given you create your group). Try out the test-map and see. I'm leaning towards it being some sort of interruption caused by trigger-events related to unit's being damaged or dying.
 

Attachments

  • KillUnitEnum.w3m
    16.3 KB · Views: 32
Last edited:
Level 18
Joined
Jan 21, 2006
Messages
2,552
Oh actually you're right. In the InitGlobals functions. That's strange I wonder why they would have the CreateGroup() in the initialization and then on each GetUnitsInRange call. Though it's Blizzard so it's not like -that- surprising, perhaps there is a usefulness that I am overlooking.

If his description is accurate the only problem I can think of is a trigger on the unit's death interfering.

Yea it's seeming to me like that's the problem. Should've just left it up to you :smile:
 
I always use this...
JASS:
function DoThings takes nothing returns boolean
    call KillUnit(GetFilterUnit())
    return true
endfunction
function main takes real x, real y returns nothing
    call GroupEnumUnitsInRange (bj_lastCreatedGroup, x, y, 1000.00, Filter(function DoThings))
    call DisplayTextToForce( GetPlayersAll(), "Work Done" )
endfunction

Bribe said that the bj_lastCreatedGroup doesnt need to be created nor be destroyed...
 
Level 1
Joined
May 27, 2011
Messages
3
Thanks you all, guys!

Berb, I've tested your map and it works properly.
Thank you for yours advices.

I'm curious, what happens if you have it as:

JASS:
function DoThings takes nothing returns boolean
    call KillUnit(GetFilterUnit())
    return false
endfunction

function main takes real x, real y returns nothing
    set udg_GROUP = CreateGroup()
    call GroupEnumUnitInRange (udg_GROUP, x, y, 1000.00, Condition(function DoThings))
    call DisplayTextToForce( GetPlayersAll(), "Work Done" )
endfunction

I've tryed this but doesn't change anything.

It seams the solution is to us every time different udg_Group variables beacause it may conflict with other triggers.

I think we can close this discussion.
Thank you again^^, I'm really grateful.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Oh actually you're right. In the InitGlobals functions. That's strange I wonder why they would have the CreateGroup() in the initialization and then on each GetUnitsInRange call. Though it's Blizzard so it's not like -that- surprising, perhaps there is a usefulness that I am overlooking.
Because of GroupAddUnit. People don't usually put groups from enums in variables in GUI.

It seams the solution is to us every time different udg_Group variables beacause it may conflict with other triggers.
Yes, a trigger on unit death was presumably being fired. New triggers execute before the current thread finishes.
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
does no one here know what the word plural means? what post #6 said was what i said back in my first post here. and who said destroygroup()? not me, destroygroup was simply the name of a variable, not a function.
The typo wasn't the main problem here, and if you're basing the accuracy of your post off its similarity to post #6 you may want to rethink that since #6 was pretty much entirely wrong.
 
Status
Not open for further replies.
Top