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

[Snippet] [Needs work] Locust Enumerator (group) functions

Level 40
Joined
Dec 14, 2005
Messages
10,532
Less efficient than normal grouping functions, significantly, but...

-GroupEnumLocusts... functions ONLY pick up locusts
-GroupEnum...Ex functions pick up locusts and normal
-GroupEnumNormal... functions ONLY pick up non-locusts. (For GroupEnumUnitsOfPlayer and GroupEnumUnitsOfType)

Improvement suggestions and such are appreciated.


Requires JNGP

JASS:
library LocustEnumerators
globals
    private group G = CreateGroup()
endglobals

private function AntiLeak takes nothing returns boolean
    return true
endfunction

function GroupEnumLocustsInRange takes group g, real x, real y, real radius, boolexpr filter returns nothing
    local integer i = 0
    local unit u
    if filter == null then
        set filter = Filter( function AntiLeak )
    endif
    loop
        exitwhen i > 11
        call GroupEnumUnitsOfPlayer( G, Player( i ), filter )
        loop
            set u = FirstOfGroup(G)
            exitwhen u == null
            if IsUnitInRangeXY( u, x, y, radius ) and GetUnitAbilityLevel(u,'Aloc') > 0 then
                call GroupAddUnit( g, u )
            endif
            call GroupRemoveUnit(G,u)
        endloop
        set i = i + 1
    endloop
endfunction

function GroupEnumUnitsInRangeEx takes group g, real x, real y, real radius, boolexpr filter returns nothing
    local integer i = 0
    local unit u
    if filter == null then
        set filter = Filter( function AntiLeak )
    endif
    loop
        exitwhen i > 11
        call GroupEnumUnitsOfPlayer( G, Player( i ), filter )
        loop
            set u = FirstOfGroup(G)
            exitwhen u == null
            if IsUnitInRangeXY( u, x, y, radius ) then
                call GroupAddUnit( g, u )
            endif
            call GroupRemoveUnit(G,u)
        endloop
        set i = i + 1
    endloop
endfunction

function GroupEnumLocustsInRect takes group g, rect r, boolexpr filter returns nothing
    local integer i = 0
    local unit u
    local region re = CreateRegion()
    call RegionAddRect( re, r )
    if filter == null then
        set filter = Filter( function AntiLeak )
    endif
    loop
        exitwhen i > 11
        call GroupEnumUnitsOfPlayer( G, Player( i ), filter )
        loop
            set u = FirstOfGroup(G)
            exitwhen u == null
            if GetUnitAbilityLevel( u, 'Aloc' ) > 0 and IsUnitInRegion( re, u ) then
                call GroupAddUnit( g, u )
            endif
            call GroupRemoveUnit(G,u)
        endloop
        set i = i + 1
    endloop
    call RegionClearRect( re, r )
    call RemoveRegion( re )
    set re = null
endfunction

function GroupEnumUnitsInRectEx takes group g, rect r, boolexpr filter returns nothing
    local integer i = 0
    local unit u
    local region re = CreateRegion()
    call RegionAddRect( re, r )
    if filter == null then
        set filter = Filter( function AntiLeak )
    endif
    loop
        exitwhen i > 11
        call GroupEnumUnitsOfPlayer( G, Player( i ), filter )
        loop
            set u = FirstOfGroup(G)
            exitwhen u == null
            if IsUnitInRegion( re, u ) then
                call GroupAddUnit( g, u )
            endif
            call GroupRemoveUnit(G,u)
        endloop
        set i = i + 1
    endloop
    call RegionClearRect( re, r )
    call RemoveRegion( re )
    set re = null
endfunction

function GroupEnumNormalUnitsOfPlayer takes group g, player p, boolexpr filter returns nothing
    local unit u
    if filter == null then
        set filter = Filter( function AntiLeak )
    endif
    call GroupEnumUnitsOfPlayer( G, p, filter )
    loop
        set u = FirstOfGroup( G )
        exitwhen u == null
        if GetUnitAbilityLevel( u, 'Aloc' ) == 0 then
            call GroupAddUnit( g, u )
        endif
        call GroupRemoveUnit( G, u )
    endloop
endfunction

function GroupEnumNormalUnitsOfType takes group g, string unitName, boolexpr filter returns nothing
    local unit u
    if filter == null then
        set filter = Filter( function AntiLeak )
    endif
    call GroupEnumUnitsOfType( G, unitName, filter )
    loop
        set u = FirstOfGroup( G )
        exitwhen u == null
        if GetUnitAbilityLevel( u, 'Aloc' ) == 0 then
            call GroupAddUnit( g, u )
        endif
        call GroupRemoveUnit( G, u )
    endloop
endfunction
endlibrary
 
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
Put them in the map's "Custom Script Section" (click on the map's picture in the trigger editor, and there's an area to place script)

Then, when you want to use them...

Let's say you have a group called

MyGroup

and a point called

MyLoc

then...

Custom script: call GroupEnum<rest of function name>(params)

Eg:

Custom script: call GroupEnumLocustsInRange( udg_MyGroup, GetLocationX( udg_MyLoc ), GetLocationY( udg_MyLoc ), 500, null )

Where 500 would be the range, and null the filter.

Then, you would do

Unit Group - Pick Every Unit in MyGroup and do actions

Adding filters in GUI is a little tricky (basically impossible without JASS knowledge), so I'd suggest you skip that out and use an if-statement to filter within the group loop instead.
 
Level 3
Joined
Sep 4, 2007
Messages
49
I was also under the impression that locust units could not be picked up in unit groups, guess I was wrong with GroupEnumUnitsOfPlayer and GroupEnumUnitsOfType.

I remember once I accidentally picked up projectile attacks from ranged units when making a spell, however I lost the spell and I couldn't manage to recreate what happened. I guess that means that ranged attacks could possibly be units with locust

If you want to make the functions more efficient you can use ForGroup function which is proven to be faster then using a loop, however then you would need to pass variables over through globals
 
Level 40
Joined
Dec 14, 2005
Messages
10,532
Yeah, I'd rather keep this un-vjassed - I doubt it makes very much of a difference, either way.

I'll probably look over them in a bit, I wrote these half a year or so ago.

Maybe I'll make a faster vJassed alternative version...

Ignitor, as for your <deleted> comment, if you're still wondering about it, the GroupEnumUnitsInRange/Rect functions don't pick up locust units, so that wouldn't work =/
 
Level 12
Joined
Aug 20, 2007
Messages
866
Hmmm

Yeah when I first started with movement triggers in GUI I noticed something along the lines of bugging with locust units

But, I haven't noticed that in a while, strange

I might use this anyway

By the way, you can set a new unit group, and set it to the units you would like to remove, and then remove said group from the locust group

That would be using boolexprs in GUI, although I'm not sure which is more efficient, using the If/Thens, or the secondary unit group (of course var + leak removal, goes w/o saying)
 
Level 12
Joined
Aug 20, 2007
Messages
866
Oh

Heh, I didn't know that :ugly:

Hmmm, you could definitely use the GroupRemoveGroup for groups in movement trigs, where you only set the group once, and it loops extremely often, in that case an If/Then would take off quite a bit more than the GroupRemoveGroup

Yeah, I think I could use this for a certain map I made a while ago :thumbs_up:

When you do GroupEnum's in GUI, which ones enum locusts, and which don't???
 
Level 12
Joined
Aug 20, 2007
Messages
866
Hmmm

I think you have that backwards

The only time I have ever had a real problem, was using that fucntion

Heres the map, + heres the original trigger, it was to be used with ghouls/banshees that were spawned

Don't judge me on the map I send you please, it was something I made a while ago and have been a bit busy to update

Hold on a sec, I need to find it ><

_________________________________
Edit #1

OOOOOOOOOO :week::week::week:

Nevermind, I guess that is the only way to do it

Yeah, I usually do movement triggers, BUT, I never need to use group enum functions, I only use the EnumUnit functions, where it adds only one to it, and then the "pick every..." will pick from the pre-enumerated group

Hmmm, that would be why this trigger didn't work when the units had Locust

  • Move Banshees
    • Events
      • Time - Every 5.00 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in (Units in Whole Swamp <gen> matching ((Unit-type of (Matching unit)) Equal to Ghoul)) and do (Actions)
        • Loop - Actions
          • Unit - Order (Picked unit) to Attack-Move To (Random point in Whole Swamp <gen>)

Yeah I made that when I had no knowledge of leaks X_x
 
Last edited:
Level 40
Joined
Dec 14, 2005
Messages
10,532
Yeah, this was written before libraries existed, hence the lack thereof. Updated to be in a library; I haven't compiled it (no WE at the moment) but it should be fine as I didn't do anything major. I'll probably rewrite these from scratch next time I have access to the WE (to use And/Or and skip the loops when possible).
 
Top