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

[JASS] Help with this function

Status
Not open for further replies.
Level 3
Joined
Sep 9, 2009
Messages
658
I wrote a function that will return a random unit. However, I don't know how to make it so that the unit array gets nulled at the end. I'm also thinking of making the function create a copy group so the original group doesn't get it's units removed in case it's still needed. But I also don't know how to that. Using FirstOfGroup loop seems to defeat the purpose and doing set CopyGroup = g doesn't add the units of g to CopyGroup. (Or does it? Doesn't seem likely though)


JASS:
function GetRandomUnit takes group g returns unit
    local integer i
    local unit f
    local unit array r[]
    
    loop
        set f = FirstOfGroup(g)
        exitwhen f == null
            set i = i + 1
            set f = r[i]
            call GroupRemoveUnit(g, f)
    endloop
    
    return r[GetRandomInt(1, i)]
endfunction
 
Level 9
Joined
Jun 21, 2012
Messages
432
try this
JASS:
globals
    private unit array randomUnit
    private unit returnedUnit=null
endglobals

function GetRandomUnit takes group g returns unit
    local integer i=0
    
    loop
        set randomUnit[i]=FirstOfGroup(g)
        exitwhen randomUnit[i]==null
        set i=i+1
        call GroupRemoveUnit(g,randomUnit[i])
    endloop
    
    set returnedUnit=randomUnit[GetRandomInt(0,i)]
    
    //You need null arrays
    set i=0
    loop
        exitwhen randomUnit[i]==null
        set randomUnit[i]=null
        set i=i+1
    endloop
    
    return returnedUnit
endfunction
 
Level 19
Joined
Mar 18, 2012
Messages
1,716
or this, which does not leak and keeps the handle reference counter,
as low as possible. However requires any UnitIndexer.
JASS:
    function GroupPickRandomUnitEx takes group whichGroup returns unit
        local integer array index// ! Can also be global array.
        local integer counter = 0
        local unit u
              
        loop
            set u = FirstOfGroup(whichGroup)
            exitwhen u == null
            call GroupRemoveUnit(whichGroup, u)
       
            set counter = counter + 1
            set index[counter] = GetUnitUserData(u)
        endloop
       
        if counter == 0 then
            return null
        endif
        return UnitIndex(index[GetRandomInt(1, counter)]).unit// Depends on UnitIndexer API.
    endfunction

Keep in mind that this approach clears the group completly.

If you wish to keep the group you have to loop through it ( use another function call) and
add all units within to a second group. You will need the ForGroup native for this operation.
 
Level 3
Joined
Sep 9, 2009
Messages
658
@Thelordmarshall returnedUnit is only null during initiation right? It doesn't get nulled after every instance, I think.

@BPower Yes, I want to do it without clearing the group. So I do it like this?

JASS:
globals
    group CopyGroup = CreateGroup()
endglobals

function ForG takes nothing returns nothing
    call GroupAddUnit(CopyGroup, GetEnumUnit())     
endfunction

function GetRandomUnit takes group g returns nothing
    local unit f

    call ForGroup(f, function ForG)
    
    loop
        set f = FirstOfGroup(CopyGroup)
        exitwhen f == null
        //Do the counting here
    endloop

    //return the random unit
endfunction

Also, is there a way to do it and null the unit variables without using a unit indexer?
 
When you are using a global variable, you do not need to null it. Nulling is only for local variables. You can also use bj_lastCreatedGroup, if you want to save some variables, but this will look more ugly and is perhaps not desireable.

If all you want to do is to pick a random unit out of a group, there is already a BJ function for this called GroupPickRandomUnit().
 
Level 3
Joined
Sep 9, 2009
Messages
658
I think you must have misunderstood me. I want to null the unit array that will be used to get the random unit.

If possible, I'd also like to know how to do it without clearing the group in case it'll still be used later on. And I'd like to do it without a unit indexer if possible.
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
Old Skool jass
JASS:
// details:
// integer bj_randDistCount - counts the number of units in the group
// unit array bj_ghoul - temporary container for units held by the group

function AddUnitsToUnitArray takes nothing returns nothing
    set bj_randDistCount=bj_randDistCount+1 
    set bj_ghoul[bj_randDistCount]=GetEnumUnit()  
endfunction

function GetRandomUnit takes group g returns unit
    set bj_randDistCount=0
    call ForGroup(g,function AddUnitsToUnitArray)
    return bj_ghoul[GetRandomInt(1,bj_randDistCount)]
endfunction
 
Level 22
Joined
Sep 24, 2005
Messages
4,821
They do leak when the object they point to gets removed and the globals are not nulled.

Here's a script that clears the array.
JASS:
function AddUnitsToUnitArray takes nothing returns nothing
    set bj_randDistCount=bj_randDistCount+1
    set bj_ghoul[bj_randDistCount]=GetEnumUnit()  
endfunction

// just pass a null value to u everytime ex:
// set udg_Target=GetRandomUnit(udg_MyGroup,null)
function GetRandomUnit takes group g, unit u returns unit
    local integer j=0
    set bj_randDistCount=0
    call ForGroup(g,function AddUnitsToUnitArray)
    set j=bj_randDistCount
    set u=bj_ghoul[GetRandomInt(1,j)]
    // Cleanup
    loop
        exitwhen j==0
        set bj_ghoul[j]=null
        set j=j-1
    endloop
    // End
    return u
endfunction
 
Level 12
Joined
Feb 22, 2010
Messages
1,115
You don't need to set global variable to null in this case because another value will be attached to it, when GetRandomUnit function is called.This situation usually called as "you don't need to null global variables" which pretty much true in most cases but not always.

But you can also argue that if we use function with a group that consist of 100 units, and after this use we always use function with group less than 100 units there will be a problem lets say for 100th array.
 
Status
Not open for further replies.
Top