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

Does this leak?

Status
Not open for further replies.
Level 12
Joined
Jan 2, 2016
Messages
973
After runing this trigger several times - the map starts lagging a lot.
I can't seem to find any leaks (maybe cuz I'm sleepy), so can you check them out?
JASS:
function DL_Effect takes nothing returns nothing
    local integer id = GetHandleId(GetExpiredTimer())
    local unit c = LoadUnitHandle(udg_Table, id, 'unit')
    local real x = GetUnitX(c)
    local real y = GetUnitY(c)
    local unit d = CreateUnit(GetOwningPlayer(c), 'h000' , x , y, 0.00)
    local unit FoG = null
    local group array p
    local boolean bull = LoadBoolean(udg_Table, id , 'bull')
    local integer count = 0
    call UnitApplyTimedLife(d , 'BTLF' , 1.5)
    set p[0] = CreateGroup()
    call UnitAddAbilityBJ( 'A004' , d)
    if bull == false then
        set p[1] = CreateGroup()
        set p[2] = CreateGroup()
        set p[3] = CreateGroup()
        call SaveBoolean(udg_Table, id, 'bull' , true)
    else
        set p[1] = LoadGroupHandle(udg_Table, id, 'grp1')
        set p[2] = LoadGroupHandle(udg_Table, id, 'grp2')
        set p[3] = LoadGroupHandle(udg_Table, id, 'grp3')
    endif
    call GroupEnumUnitsInRange( p[0] , x , y , 600 , null)
    loop
        set FoG = FirstOfGroup( p[0] )
        exitwhen FoG == null or count >= 3
        if IsUnitInGroup(FoG, p[3]) == false then
            if IsUnitEnemy( FoG , GetOwningPlayer(c)) == true  then
                call IssueTargetOrderBJ( d , "acidbomb", FoG )
                set count = count + 1
                if IsUnitInGroup(FoG, p[1]) then
                    call GroupAddUnit(p[2] , FoG)
                    call GroupRemoveUnit(p[1], FoG)
                else
                    if IsUnitInGroup(FoG, p[2]) then
                        call GroupAddUnit(p[3], FoG)
                        call GroupRemoveUnit(p[2], FoG)
                    else
                        call GroupAddUnit(p[1], FoG)
                    endif
                endif
            endif
        endif
        call GroupRemoveUnit(p[0], FoG)
    endloop
    call DestroyGroup(p[0])
    call SaveGroupHandle(udg_Table, id, 'grp1' , p[1])
    call SaveGroupHandle(udg_Table, id, 'grp2' , p[2])
    call SaveGroupHandle(udg_Table, id, 'grp3' , p[3])
    set c = null
    set d = null
    set FoG = null
    set p[0] = null
    set p[1] = null
    set p[2] = null
    set p[3] = null
endfunction

function Death_Lotus takes nothing returns nothing
    local unit c = GetTriggerUnit()
    local effect e = AddSpecialEffectTargetUnitBJ("origin", c , "war3mapImported\\BloodTornado.mdx")
    local timer t = CreateTimer()
    call SaveEffectHandle(udg_Table, GetHandleId(c), 'efct' , e)
    call SaveUnitHandle(udg_Table, GetHandleId(t), 'unit' , c)
    call SaveTimerHandle(udg_Table, GetHandleId(c), 'time' , t)
    call SaveBoolean(udg_Table, GetHandleId(t), 'bull' , false)
    call TimerStart( t , 1, true, function DL_Effect)
    set c = null
    set e = null
    set t = null
endfunction

function Trig_Death_Lotus_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A000' ) ) then
        return false
    endif
    call Death_Lotus()
    return false
endfunction


//===========================================================================
function InitTrig_Death_Lotus takes nothing returns nothing
    set gg_trg_Death_Lotus = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Death_Lotus, EVENT_PLAYER_UNIT_SPELL_CHANNEL )
    call TriggerAddCondition( gg_trg_Death_Lotus, Condition( function Trig_Death_Lotus_Conditions ) )
endfunction
JASS:
function Cancelation takes nothing returns nothing
    local integer id = GetHandleId(GetTriggerUnit())
    local effect e = LoadEffectHandle(udg_Table, id, 'efct')
    local timer t = LoadTimerHandle(udg_Table, id, 'time')
    local integer t_id = GetHandleId(t)
    local group p1 = LoadGroupHandle(udg_Table, t_id, 'grp1')
    local group p2 = LoadGroupHandle(udg_Table, t_id, 'grp2')
    local group p3 = LoadGroupHandle(udg_Table, t_id, 'grp3')
    call DestroyGroup(p1)
    call DestroyGroup(p2)
    call DestroyGroup(p3)
    set p1 = null
    set p2 = null
    set p3 = null
    call FlushChildHashtable(udg_Table, t_id)
    call DestroyTimer(t)
    set t = null
    call FlushChildHashtable(udg_Table, id)
    call DestroyEffect( e )
    set e = null
endfunction

function Trig_Death_Lotus_End_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A000' ) ) then
        return false
    endif
    call Cancelation()
    return false
endfunction

//===========================================================================
function InitTrig_Death_Lotus_End takes nothing returns nothing
    set gg_trg_Death_Lotus_End = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Death_Lotus_End, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
    call TriggerAddCondition( gg_trg_Death_Lotus_End, Condition( function Trig_Death_Lotus_End_Conditions ) )
endfunction

Describtion:
When a unit starts channeling a spell - a custom special effect is created.
Every second, 3 units are hit by 'a missile'
No unit can be hit more than 3 times per cast.
 
Level 12
Joined
Jan 2, 2016
Messages
973
I destroy it in the second trigger (when the unit stops casting)
And sometimes, when I don't know a function, I make a trigger, add the GUI action for it, then I change it to JASS and copy-paste the function xP.
I have only 3 BJ functions in these triggers anyways...
 
I do the same thing :p
I'm a noob at JASS so take this with a grain of salt, but I think it's better to look up the BJ function in the function list and copy what goes on inside the function though.
Even TriggerRegisterAnyUnitEventBJ can be replaced that way.

Example:
JASS:
function AddSpecialEffectTargetUnitBJ takes string attachPointName, widget targetWidget, string modelName returns effect
    set bj_lastCreatedEffect = AddSpecialEffectTarget(modelName, targetWidget, attachPointName)
    return bj_lastCreatedEffect
endfunction
So in your code make it:
JASS:
local effect e = AddSpecialEffectTarget("war3mapImported\\BloodTornado.mdx", c, "origin")

At the same time, DestroyEffect doesn't stop the effect from being displayed, it only removes it from memory (if I'm not mistaken), so there's no use in storing and loading it to a hashtable. Although I suppose that depends on whether or not the animation loops or not.
==>
JASS:
DestroyEffect( AddSpecialEffectTarget("war3mapImported\\BloodTornado.mdx", c, "origin") )


Also this can be simplified:
JASS:
function Trig_Death_Lotus_End_Conditions takes nothing returns boolean
    if ( not ( GetSpellAbilityId() == 'A000' ) ) then
        return false
    endif
    call Cancelation()
    return false
endfunction

JASS:
function Trig_Death_Lotus_End_Conditions takes nothing returns boolean
    if ( GetSpellAbilityId() == 'A000' ) then
       call Cancelation()
    endif
    return false
endfunction

Although probably this would be better:
JASS:
function Trig_Death_Lotus_End_Conditions takes nothing returns boolean
    return ( GetSpellAbilityId() == 'A000'  )
endfunction

//===========================================================================
function InitTrig_Death_Lotus_End takes nothing returns nothing
    set gg_trg_Death_Lotus_End = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Death_Lotus_End, EVENT_PLAYER_UNIT_SPELL_ENDCAST )
    call TriggerAddCondition( gg_trg_Death_Lotus_End, Condition( function Trig_Death_Lotus_End_Conditions ) )
    call TriggerAddAction( gg_trg_Death_Lotus_End, function Cancelation )
endfunction
That way you can also put both functions in the same trigger, use only one function to register both events, and use the same Condition function for both.
These kinds of changes go a long way in making your code more readable, and also minimizes function calls etc, which can make the code perform better, even if it's only little bit in most short systems.
 
Level 12
Joined
Jan 2, 2016
Messages
973
I need to destroy the effect when the spell stops begin cast, cuz the effect is looping.
However, I don't see any major leaks, yet this is the trigger that is causing the most lag from all the triggers I've ever made.

Is it possible that the custom special effect is causing it?
 
Status
Not open for further replies.
Top