• 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] Leak Check Please

Status
Not open for further replies.
Level 8
Joined
Nov 9, 2008
Messages
502
Hello Hive!

Now, I thought I was pretty decent at this leak checking except I have a trigger running very often and it seems to be leaking.

I have already:
  • Nulled units
  • Destroyed and nulled filters
  • Destroyed and nulled groups
  • There are no locs used

JASS:
function plyrFltr takes nothing returns boolean
    local unit u = GetFilterUnit()
    local boolean a = GetOwningPlayer(u) == Player(11)
    set u = null
    return a
endfunction

function zCollideUp takes unit unitSubject, real zProjected returns boolean
    local unit unitTarget
    local boolean InRange = false
    local real zTarget
    local real zActual = GetUnitFlyHeight(unitSubject)
    local group tmpGrp
    local filterfunc tmpFltr = Filter(function plyrFltr)
    set tmpGrp = CreateGroup()
    //Width of player unit global needed
    call GroupEnumUnitsInRange(tmpGrp, GetUnitX(unitSubject), GetUnitY(unitSubject), 90, tmpFltr)
    loop
        set unitTarget = FirstOfGroup(tmpGrp)
        //Height of player unit global needed
        set zTarget = GetUnitFlyHeight(unitTarget) - 100
        if (zTarget >= zActual and zTarget <= zProjected) then
            set InRange = true
            call GroupRemoveUnit(tmpGrp, unitTarget)
        endif
        call GroupRemoveUnit(tmpGrp, unitTarget)
        exitwhen unitTarget == null
    endloop
    call DestroyGroup(tmpGrp)
    call DestroyFilter(tmpFltr)
    set unitTarget = null
    set tmpGrp = null
    set tmpFltr = null
    return InRange
endfunction

function zCollideDown takes unit unitSubject, real zProjected returns boolean
    local unit unitTarget
    local boolean InRange = false
    local real zTarget
    local real zActual = GetUnitFlyHeight(unitSubject)
    local group tmpGrp
    local filterfunc tmpFltr = Filter(function plyrFltr)
    set tmpGrp = CreateGroup()
    //width of player unit global needed
    call GroupEnumUnitsInRange(tmpGrp, GetUnitX(unitSubject), GetUnitY(unitSubject), 90, tmpFltr)
    loop
        set unitTarget = FirstOfGroup(tmpGrp)
        set zTarget = GetUnitFlyHeight(unitTarget)
        //Height of object colliding with unitSubject global needed
        if (zTarget <= zActual-70 and zTarget >= zProjected-70) then
            set InRange = true
            call GroupRemoveUnit(tmpGrp, unitTarget)
        endif
        call GroupRemoveUnit(tmpGrp, unitTarget)
        exitwhen unitTarget == null
    endloop
    call DestroyGroup(tmpGrp)
    call DestroyFilter(tmpFltr)
    set unitTarget = null
    set tmpGrp = null
    set tmpFltr = null
    return InRange
endfunction

function xCollide takes unit unitSubject, real xProjected, real zProjected returns boolean
    local unit unitTarget
    local boolean InRange = false
    local real xTarget 
    local group tmpGrp
    local filterfunc tmpFltr = Filter(function plyrFltr)
    set tmpGrp = CreateGroup()
    //width of player unit global needed
    call GroupEnumUnitsInRange(tmpGrp, GetUnitX(unitSubject), GetUnitY(unitSubject), 90, tmpFltr)
    loop
        set unitTarget = FirstOfGroup(tmpGrp)
        set xTarget = GetUnitX(unitTarget)
        //Width of object colliding with unitSubject global needed
        //Width of player unit global needed
        if (xProjected+(90/2) <= xTarget+(72/2) or xProjected+(90/2) >= xTarget-(72/2)) or (xProjected-(90/2) <= xTarget+(72/2) or xProjected-(90/2) >= xTarget-(72/2)) and (zCollideUp(unitSubject, zProjected) or zCollideDown(unitSubject, zProjected)) then
            set InRange = true
            call GroupRemoveUnit(tmpGrp, unitTarget)
        endif
        call GroupRemoveUnit(tmpGrp, unitTarget)
        exitwhen unitTarget == null
    endloop
    call DestroyGroup(tmpGrp)
    call DestroyFilter(tmpFltr)
    set unitTarget = null
    set tmpGrp = null
    set tmpFltr = null
    return InRange
endfunction

function ApplyPhysics takes nothing returns nothing
    local unit unitSubject
    local real xCurrent
    local real zCurrent
    local real xProjected
    local real zProjected
    
    set udg_index = 0
    loop
        set unitSubject = udg_PlayerUnit[udg_index]
        set xCurrent = GetUnitX(unitSubject)  
        set zCurrent = GetUnitFlyHeight(unitSubject) 
        set xProjected = xCurrent + udg_xVelocity[udg_index]
        set zProjected = zCurrent + udg_zVelocity[udg_index] + udg_zAccel
        
        //--------------y--------------
        if zCollideUp(unitSubject, zProjected) then
            if udg_zVelocity[udg_index] >= 5 then // bounce threshhold when travelling up
                set udg_zVelocity[udg_index] = 0 - udg_zVelocity[udg_index]
            else
                set udg_zVelocity[udg_index] = 0
            endif
        elseif zCollideDown(unitSubject, zProjected) then
            set udg_zVelocity[udg_index] = 0
        else    
            call SetUnitFlyHeight(unitSubject, zProjected, 0)
            set udg_zVelocity[udg_index] = udg_zVelocity[udg_index] + udg_zAccel
        endif

        //-------------x-------------
        if xCollide(unitSubject, xProjected, zProjected) then
            // bounce threshhold when travelling horizontally
            if udg_xVelocity[udg_index] >= 5 then 
                set udg_xVelocity[udg_index] = 0 - udg_xVelocity[udg_index]
            else
                set udg_xVelocity[udg_index] = 0
            endif
        else 
        call SetUnitX(unitSubject, xProjected)
        set udg_xVelocity[udg_index] =  udg_xVelocity[udg_index] 
        endif
        set unitSubject = null   
        set udg_index = udg_index + 1    
        exitwhen udg_index == 13
    endloop
endfunction

//===========================================================================
function InitTrig_PhysicsV2 takes nothing returns nothing
    set gg_trg_PhysicsV2 = CreateTrigger(  )
    call TriggerRegisterTimerEventPeriodic(gg_trg_PhysicsV2, 0.01)
    call TriggerAddAction( gg_trg_PhysicsV2, function ApplyPhysics )
endfunction

Like I said, it runs pretty often atm (will probably be reduced) so it is important it doesn't leak.

What have I missed?


P.S. It isn't correct so don't bother copying it xD
 
Last edited:
Some comments.

  • You can inline your filter function;
    JASS:
    function plyrFltr takes nothing returns boolean
        return GetOwningPlayer(u) == Player(11)
    endfunction
  • You don't need to store your filterfunction, they are stored in tables an re-used so they do not leak.
  • TriggerRegisterTimerEventPeriodic - Useless BJ.
  • Change the timer period from 0.01 to 0.03

I strongly suggest using vJass, this could be made much more efficient then.
 
Level 8
Joined
Nov 9, 2008
Messages
502
Won't the filter leak a unit reference? Also, by u I'm guessing you meant GetFilterUnit().

Thanks for that BJ, didn't notice regular timer event has a periodic boolean.

I am using JNGP so I could vJass if I knew how. Could you elaborate how you would make it more efficient?
 
Level 8
Joined
Nov 9, 2008
Messages
502
I see. So instead of executing the loop all at once it will be split up slightly by the timer.

Do you mean you would put all actions in ApplyPhysics inside the filter too?
 

Dr Super Good

Spell Reviewer
Level 64
Joined
Jan 18, 2005
Messages
27,286
Filter functions and Condtion() returned filters do not leak as they are immutable and so static (always have the same object returned).

However, they do technically leak if you use them once and then never again (as they still exist although never needed), in which case they should be removed (however the leak is minor as it is only 1 object).
 
Level 8
Joined
Nov 9, 2008
Messages
502
I have to store the filter into a local otherwise I acn't use it in the function so I don't see how that applies.
 
Level 8
Joined
Nov 9, 2008
Messages
502
Ah yeah ofcourse, silly me.

Thanks all for your comments. It feels a lot smoother and I haven't yet implemented timers or reduced the period.

Dunno about putting all actions into the filter, it just seems like the same code re-arranged. I guess it will eliminate having to use FirstOfGroup().

For some reason, I'm still getting a degredation of FPS though...
 
Level 8
Joined
Nov 9, 2008
Messages
502
...to be expected with Blizzard really :grin: Well it seems to be a lot smoother now.

This is the revised version for anyone interested:

JASS:
function plyrFltr takes nothing returns boolean
    return GetOwningPlayer(GetFilterUnit()) == Player(11)
endfunction

function zCollideUp takes unit unitSubject, real zProjected returns boolean
    local unit unitTarget
    local boolean InRange = false
    //Width of arena global needed
    call GroupEnumUnitsInRange(udg_tmpGrp, GetUnitX(unitSubject), GetUnitY(unitSubject), 90, Filter(function plyrFltr))
    loop

        set unitTarget = FirstOfGroup(udg_tmpGrp)
        //Height of player unit global needed
        if (GetUnitFlyHeight(unitTarget)-100 >= GetUnitFlyHeight(unitSubject) and GetUnitFlyHeight(unitTarget)-100 <= zProjected) then
            set InRange = true
        endif
        call GroupRemoveUnit(udg_tmpGrp, unitTarget)
        exitwhen unitTarget == null
    endloop
    return InRange
endfunction

function zCollideDown takes unit unitSubject, real zProjected returns boolean
    local unit unitTarget
    local boolean InRange = false
    //width of player unit global needed
    call GroupEnumUnitsInRange(udg_tmpGrp, GetUnitX(unitSubject), GetUnitY(unitSubject), 90, Filter(function plyrFltr))
    loop
        set unitTarget = FirstOfGroup(udg_tmpGrp)
        //Height of object colliding with unitSubject global needed
        if (GetUnitFlyHeight(unitTarget) <= GetUnitFlyHeight(unitSubject)-70 and GetUnitFlyHeight(unitTarget) >= zProjected-70) then
            set InRange = true
        endif
        call GroupRemoveUnit(udg_tmpGrp, unitTarget)
        exitwhen unitTarget == null
    endloop
    return InRange
endfunction

function xCollide takes unit unitSubject, real xProjected returns boolean
    local unit unitTarget
    local boolean InRange = false
    //width of player unit global needed
    call GroupEnumUnitsInRange(udg_tmpGrp, GetUnitX(unitSubject), GetUnitY(unitSubject), 100, Filter(function plyrFltr))
    loop
        set unitTarget = FirstOfGroup(udg_tmpGrp)
        //Width of object colliding with unitSubject global needed
        //Width of player unit global needed
        if (GetUnitFlyHeight(unitTarget) >= GetUnitFlyHeight(unitSubject) and GetUnitFlyHeight(unitTarget) <= GetUnitFlyHeight(unitSubject)+100) or (GetUnitFlyHeight(unitTarget)+70 >= GetUnitFlyHeight(unitSubject) and GetUnitFlyHeight(unitTarget)+70 <= GetUnitFlyHeight(unitSubject)+100) then
            if (xProjected+18 >= GetUnitX(unitTarget)-72 and xProjected+18 <= GetUnitX(unitTarget)+72) or (xProjected-18<=GetUnitX(unitTarget)+72 and xProjected-18>=GetUnitX(unitTarget)-72) then
                set InRange = true
            endif
        endif
        call GroupRemoveUnit(udg_tmpGrp, unitTarget)
        exitwhen unitTarget == null
    endloop
    return InRange
endfunction

function ApplyPhysics takes nothing returns nothing
    local real xCurrent
    local real zCurrent
    local real xProjected
    local real zProjected
    
    if udg_index > 10 then
        set udg_index = 0
    endif
    if GetPlayerSlotState(Player(udg_index)) != PLAYER_SLOT_STATE_PLAYING then
        return
    endif
        set xCurrent = GetUnitX(udg_PlayerUnit[udg_index])  
        set zCurrent = GetUnitFlyHeight(udg_PlayerUnit[udg_index]) 
        set xProjected = xCurrent + udg_xVelocity[udg_index]
        set zProjected = zCurrent + udg_zVelocity[udg_index] + udg_zAccel
        
        //--------------z--------------
        if zCollideUp(udg_PlayerUnit[udg_index], zProjected) then
            if udg_zVelocity[udg_index] >= 5 then // bounce threshhold when travelling up
                set udg_zVelocity[udg_index] = 0 - udg_zVelocity[udg_index]
            else
                set udg_zVelocity[udg_index] = 0
            endif
        elseif zCollideDown(udg_PlayerUnit[udg_index], zProjected) then
            set udg_zVelocity[udg_index] = 0
        else    
            call SetUnitFlyHeight(udg_PlayerUnit[udg_index], zProjected, 0)
            set udg_zVelocity[udg_index] = udg_zVelocity[udg_index] + udg_zAccel
        endif

        //-------------x-------------
        if xCollide(udg_PlayerUnit[udg_index], xProjected) then
            // bounce threshhold when travelling horizontally
            if udg_xVelocity[udg_index] >= 5 then 
                set udg_xVelocity[udg_index] = 0 - udg_xVelocity[udg_index]
            else
                set udg_xVelocity[udg_index] = 0
            endif
        else 
            call SetUnitX(udg_PlayerUnit[udg_index], xProjected)
            set udg_xVelocity[udg_index] =  udg_xVelocity[udg_index] 
        endif
        set udg_index = udg_index + 1
endfunction

function StartPhysicsTimerLoop takes nothing returns nothing
    local timer t = CreateTimer()
    set udg_index = 0
    call TimerStart(t, 0.001, true, function ApplyPhysics)
endfunction

//===========================================================================
function InitTrig_PhysicsV2 takes nothing returns nothing
    set gg_trg_PhysicsV2 = CreateTrigger(  )
    call TriggerAddAction( gg_trg_PhysicsV2, function StartPhysicsTimerLoop )
endfunction

There is one other thing I could use some help with....

I added this IF:

JASS:
    if GetPlayerSlotState(Player(udg_index)) != PLAYER_SLOT_STATE_PLAYING then
        return
    endif
...so that it would skip the rest of the function if the player slot was empty but it seems to return regardless of the slot status.
Any ideas? Is this because of the editing environment and it will work in-game?
 
Last edited:
Level 8
Joined
Nov 9, 2008
Messages
502
I know. You're talking about libraries, methods and scopes right?
Problem is I've never used them and I wouldn't know where to start.
If I can get a working system in Jass, it would be easy to convert to vJass if I so wished right?
 
Level 8
Joined
Nov 9, 2008
Messages
502
Can you recommend a specific resource for what I need?

EDIT: Else if someone would be kind enough to revamp my code into vJass that would provide a sufficient example I could understand and use to learn how the vJass functions work.
 
Last edited:
Status
Not open for further replies.
Top