• 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.

[JASS] GroupEnumUnitsInRangeOfXYEx which count Locusted units is useful ? :o

Status
Not open for further replies.
Level 4
Joined
Jan 29, 2007
Messages
98
Sorry for the long title, and also for that really long and annoying function name... Couldn't think of a better one :p

Anyways, this is something I cooked up now but I'm unsure if it already exists :S
It uses GroupEnumUnitsOfPlayer to do all other stuff like the one in the title, and here's the code:
JASS:
library LocustGroup

    globals
        private group ENUM = CreateGroup()
        private group TEMP
        
        private real range = 0.0
        private real xe
        private real ye
        private real xe1
        private real ye1
    endglobals
    
    private function EnumActions_Range takes nothing returns nothing
        local unit u = GetEnumUnit()
        
        if IsUnitInRangeXY( u, xe, ye, range ) then
            call GroupAddUnit( TEMP, u )
        endif
        
        set u = null
    endfunction
    
    private function EnumActions_Rect takes nothing returns nothing
        local unit u = GetEnumUnit()
        
        if ( GetUnitX( u ) <= xe1 or GetUnitX( u ) >= xe ) and ( GetUnitY( u ) <= ye1 or GetUnitY( u ) >= ye ) then
            call GroupAddUnit( TEMP, u )
        endif
        
        set u = null
    endfunction
    
    function GroupEnumUnitsInRangeOfXYEx takes group g, real x, real y, real r, boolexpr b returns nothing
        local integer i = 0
        
        set range = r
        set xe = x
        set ye = y
        set TEMP = g
        
        loop
            call GroupEnumUnitsOfPlayer( ENUM, Player( i ), b )
            call ForGroup( ENUM, function EnumActions_Range )
            
            set i = i + 1
            exitwhen i >= 16            
        endloop
        
        set TEMP = null
    endfunction
    
    function GroupEnumUnitsInRangeOfLocEx takes group g, location l, real r, boolexpr b returns nothing
        local integer i = 0
        
        if l != null then
            set range = r
            set xe = GetLocationX( l )
            set ye = GetLocationY( l )
            set TEMP = g
            
            loop
                call GroupEnumUnitsOfPlayer( ENUM, Player( i ), b )                
                call ForGroup( ENUM, function EnumActions_Range )
                
                set i = i + 1
                exitwhen i >= 16            
            endloop
        
            set TEMP = null
        endif
        
    endfunction
    
    function GroupEnumUnitsInRangeOfUnitEx takes group g, unit u, real r, boolexpr b returns nothing
        local integer i = 0
        
        if u != null then
            set range = r
            set xe = GetUnitX( u )
            set ye = GetUnitY( u )
            set TEMP = g
            
            loop
                call GroupEnumUnitsOfPlayer( ENUM, Player( i ), b )                
                call ForGroup( ENUM, function EnumActions_Range )
                
                set i = i + 1
                exitwhen i >= 16            
            endloop
        
            set TEMP = null
        endif
        
    endfunction
    
    function GroupEnumUnitsInRectEx takes group g, rect r, boolexpr b returns nothing
        local integer i = 0
        
        if r != null then
            set xe = GetRectMinX( r )
            set ye = GetRectMinY( r )
            set xe1 = GetRectMaxX( r )
            set ye1 = GetRectMaxY( r )
            set TEMP = g
            
            loop
                call GroupEnumUnitsOfPlayer( ENUM, Player( i ), b )                
                call ForGroup( ENUM, function EnumActions_Rect )
                
                set i = i + 1
                exitwhen i >= 16            
            endloop
        
            set TEMP = null
        endif
        
    endfunction

endlibrary

So, I'm just wondering:
Is this efficient to do it this way :S
If not, then is there another more efficient way of doing it ?
Has it been done before ? :eek:
 
Level 9
Joined
Nov 28, 2008
Messages
704
Optimizing the oval into a wheel is a perfectly good idea though. But is ForGrouping that much better than FirstOfGroup? Likely not enough to justify this. BVut I make my own systems and never uses anything by anyone else, so I can't talk on that note.
 
Level 13
Joined
Mar 16, 2008
Messages
941
Optimizing the oval into a wheel is a perfectly good idea though. But is ForGrouping that much better than FirstOfGroup? Likely not enough to justify this. BVut I make my own systems and never uses anything by anyone else, so I can't talk on that note.
ForGroup is told to be faster, didn't do benchmarks.
Also, ForGroup cares for shadow references,
although there shouldn't be any shadow references in a group
that's instantly enumed (and the RefreshGroup function
just makes it much slower).
 
Level 4
Joined
Jan 29, 2007
Messages
98
Honestly, I had never seen a "system" (Snippet) like this before, so don't assume I took the idea from 'PurplePoot'...

And, this is still better than his current system, so I'd say either approve this, or someone contact 'PurplePoot' and tell him to update his system like mine, and give creds to me...
 
Level 11
Joined
Apr 29, 2007
Messages
826
But is ForGrouping that much better than FirstOfGroup?
JASS:
library ForGroupTest initializer init

    globals
        private constant integer TEST_ITERATIONS = 200
    
        private group TEST_GROUP
        
        private integer stopwatch1 = 0
        private integer stopwatch2 = 0
        
        private real ForGroupResult = 0.
        private real FirstOfGroupResult = 0.
    endglobals

    native StopWatchCreate  takes nothing returns integer
    native StopWatchMark    takes integer stopwatch returns real
    native StopWatchDestroy takes integer stopwatch returns nothing
    
    private function callback takes nothing returns nothing
        call ShowUnit(GetEnumUnit(), true)
        call ShowUnit(GetEnumUnit(), false)
    endfunction
    
    private function ForGroupTest takes nothing returns nothing
        set stopwatch1 = StopWatchCreate()
        
        call ForGroup(TEST_GROUP, function callback)
        
        set ForGroupResult = StopWatchMark(stopwatch1)
        
        call StopWatchDestroy(stopwatch1)
    endfunction
    
    private function FirstOfGroupTest takes nothing returns nothing
        local unit u
    
        set stopwatch2 = StopWatchCreate()
        
        loop
            set u = FirstOfGroup(TEST_GROUP)
            exitwhen u == null
            
            call ShowUnit(u, true)
            call ShowUnit(u, false)
            
            call GroupRemoveUnit(TEST_GROUP, u)
        endloop
        
        set FirstOfGroupResult = StopWatchMark(stopwatch2)
        
        call StopWatchDestroy(stopwatch2)
        
        set u = null
    endfunction
    
    private function init takes nothing returns nothing
        local unit u
        local integer i = 0
        
        set TEST_GROUP = CreateGroup()
        
        loop
            set u = CreateUnit(Player(0), 'hfoo', 0, 0, 0)
            call GroupAddUnit(TEST_GROUP, u)
            call ShowUnit(u, false)
            
            set i = i + 1
            exitwhen i >= TEST_ITERATIONS
        endloop
        
        set u = null
        
        call TriggerSleepAction(2.0)
        
        call ExecuteFunc(SCOPE_PRIVATE+"ForGroupTest")
        call ExecuteFunc(SCOPE_PRIVATE+"FirstOfGroupTest")
        
        call TriggerSleepAction(2.0)
        
        call BJDebugMsg("ForGroup Result: " + R2S(ForGroupResult))
        call BJDebugMsg("FirstOfGroup Result: " + R2S(FirstOfGroupResult))
    endfunction
    
endlibrary
Tested it somewhen although I don't have the screenshot anymore. But I remember it being only a minor difference.
 
Level 4
Joined
Jan 29, 2007
Messages
98
Yeah, but still, if you remove a unit using the "RemoveUnit" native, it will return null in a FirstOfGroup loop, and will break that loop...

That will never happen with the ForGroup method !

Som if stuff can be done with ForGroup, it should always be done that way !
 
Level 4
Joined
Jan 29, 2007
Messages
98
Half.
Shadow references only "stay" in a group and if you enum the group completly new it can't happen. However, I'm used to ForGroup now :D
Don't let the people get you down, it can be that yours is better or not. Just be proud that you did it and use it :p

Yeah, but still this will work in every case...
I mean, wouldn't anyone use a "guaranteed-to-work" solution, rather than a "wil-work-under-certain-circumstances" solution... ? :eek:

ForGroup was faster btw iirc.

Thought so :p
Thanks ;)
 
Status
Not open for further replies.
Top