Делал триггер и увидел огромное количество утечек, совершенно не понятных для меня, можете объяснить, как их убрать?
Утечки
function Trig_TerribleWounds_Actions takes nothing returns nothing
    local real TerribleWoundsCount
    local real UnitLifeOld
    local real UnitLifeNow 
    local group TWGroup = CreateGroup()
    local unit TWUnit
    
    call GroupEnumUnitsInRect(TWGroup, GetWorldBounds( ), null)
    
        loop
            set TWUnit = FirstOfGroup(TWGroup)
            exitwhen TWUnit == null
            
            set TerribleWoundsCount = LoadReal(H, GetHandleId(TWUnit), StringHash("TerribleWoundsCount"))
            set UnitLifeOld = LoadReal(H, GetHandleId(TWUnit), StringHash("UnitLifeOld"))
            set UnitLifeNow = GetUnitState(TWUnit, UNIT_STATE_LIFE)
            
            if TerribleWoundsCount > 1 then
                set TerribleWoundsCount = 1
            endif
            
            if (UnitLifeOld < UnitLifeNow) and UnitLifeOld != 0 and TerribleWoundsCount != 0 then
                call SetUnitState(TWUnit, UNIT_STATE_LIFE, (UnitLifeNow - (UnitLifeNow - UnitLifeOld) * TerribleWoundsCount))
            endif
            
            set UnitLifeOld = GetUnitState(TWUnit, UNIT_STATE_LIFE)
            call SaveReal(H, GetHandleId(TWUnit), StringHash("UnitLifeOld"), UnitLifeOld)
            
            call GroupRemoveUnit(TWGroup, TWUnit)
        endloop
        
        set TWGroup = null
        set TWUnit = null
endfunction

//===========================================================================
function InitTrig_TerribleWounds takes nothing returns nothing
    local trigger TerribleWoundsTrigger

    set TerribleWoundsTrigger = CreateTrigger( )
    call TriggerRegisterTimerEvent(TerribleWoundsTrigger, 0.01, true)
    call TriggerAddAction(TerribleWoundsTrigger, function Trig_TerribleWounds_Actions)
    
    set TerribleWoundsTrigger = null
endfunction
При этом делал схожий триггер, но он утечки не вызывает.
Нет утечек
//! nocjass
library Horror requires MemoryHackDamageEventHook
    globals
        group HorrorGroup   = CreateGroup( )
    endglobals
    
    function HorrorCheckGroup takes nothing returns nothing
        local real HorrorTime = LoadReal(H, GetHandleId(GetEnumUnit()), StringHash("HorrorTime"))
        local effect HorrorEffect = LoadEffectHandle(H, GetHandleId(GetEnumUnit()), StringHash("HorrorEffect"))
        local unit Isazam = LoadUnitHandle(H, GetHandleId(GetEnumUnit()), StringHash("Isazam"))
        local real TargetX = GetUnitX(GetEnumUnit())
        local real TargetY = GetUnitY(GetEnumUnit())
        local real IsazamX = GetUnitX(Isazam)
        local real IsazamY = GetUnitY(Isazam)
        local integer HorrorQuest = LoadInteger(H, GetHandleId(Isazam), StringHash("HorrorQuest"))
        
        if HorrorTime >= 20 then
            set HorrorQuest = 1
            call SaveInteger(H, GetHandleId(Isazam), StringHash("HorrorQuest"), HorrorQuest)
        endif
        
        if SquareRoot((IsazamX - TargetX) * (IsazamX - TargetX) + (IsazamY - TargetY) * (IsazamY - TargetY)) >= 700 then //Указываем желаемую дальность увеличенного снижения ужаса
            set HorrorTime = HorrorTime - 1.5
        else
            set HorrorTime = HorrorTime - 1
        endif
                
        if HorrorTime <= 0 then
            call DestroyEffect(HorrorEffect)
            call GroupRemoveUnit(HorrorGroup, GetEnumUnit())
            set HorrorTime = 0
        else
            call PingMinimapEx(TargetX, TargetY, 1, 255, 0, 0, false)
        endif
        
        call SaveReal(H, GetHandleId(GetEnumUnit()), StringHash("HorrorTime"), HorrorTime)
        
        set HorrorEffect = null
        set Isazam = null
    endfunction
    
    function HorrorCheckAction takes nothing returns nothing
        call ForGroup(HorrorGroup, function HorrorCheckGroup)
    endfunction

    function Damaged_Handler takes unit source, unit target, real dmg returns nothing
        local integer evnt  = GetDamageEventESPData()
        local integer data  = ReadRealMemory(evnt + 0x00)
        local real init_dmg = CleanReal(IndexToReal(ReadRealMemory(evnt + 0x04)))
        local integer flags = ReadRealMemory(data + 0x0C)
        local integer atk_t = ReadRealMemory(data + 0x20)
        local real HorrorTime = LoadReal(H, GetHandleId(target), StringHash("HorrorTime"))
        local effect HorrorEffect
        local unit Isazam
        local integer HorrorQuest = LoadInteger(H, GetHandleId(source), StringHash("HorrorQuest"))
        
        if GetUnitTypeId(source) == 'U005' then // Ставим свой ID Исазама
            call SaveReal(H, GetHandleId(target), StringHash("HorrorTime"), HorrorTime + 2 + HorrorQuest)
            if HorrorTime <= 0 then
                set HorrorEffect = AddSpecialEffectTarget("Abilities\\Spells\\Undead\\UnholyFrenzy\\UnholyFrenzyTarget.mdl", target, "chest")
                call SaveEffectHandle(H, GetHandleId(target), StringHash("HorrorEffect"), HorrorEffect)
                call SaveUnitHandle(H, GetHandleId(target), StringHash("Isazam"), source)
                call GroupAddUnit(HorrorGroup, target)
            elseif (IsFlagBitSet(flags, 0x100) or IsFlagBitSet(flags, 0x101)) and atk_t != 0 and HorrorTime > 0 then
                set HorrorEffect = AddSpecialEffectTarget("Abilities\\Spells\\Undead\\VampiricAura\\VampiricAuraTarget.mdl", source, "origin")
                call DestroyEffectTimer(HorrorEffect, 0.3)
                call SetUnitState(source, UNIT_STATE_LIFE, (GetUnitState(source, UNIT_STATE_LIFE) + init_dmg * 0.2))
            endif
        endif
        
        set HorrorEffect = null
        set Isazam = null
    endfunction

    function Damage_Event takes nothing returns nothing
        call DisableTrigger( GetTriggeringTrigger( ) )
        call Damaged_Handler( GetEventDamageSource( ), GetTriggerUnit( ), GetEventDamage( ) )
        call EnableTrigger( GetTriggeringTrigger( ) )
    endfunction
endlibrary

function InitTrig_Horror takes nothing returns nothing
    local group gMain = CreateGroup()
    local unit uTemp 
    local trigger trTemp
    local trigger HorrorCheck
    
    if true then
        set trTemp = CreateTrigger( )
        call GroupEnumUnitsInRect( gMain, GetWorldBounds( ), null )
        loop
            set uTemp = FirstOfGroup( gMain )
            exitwhen uTemp == null
            call TriggerRegisterUnitEvent( trTemp, uTemp, EVENT_UNIT_DAMAGED )
            call GroupRemoveUnit( gMain, uTemp )
        endloop
        call TriggerAddAction( trTemp, function Damage_Event )
    endif
    
    set HorrorCheck = CreateTrigger( )
    call TriggerRegisterTimerEvent(HorrorCheck, 1, true)
    call TriggerAddAction(HorrorCheck, function HorrorCheckAction)
    
    set gMain = null
    set uTemp = null
    set trTemp = null
    set HorrorCheck = null
endfunction
//! endnocjass

Да, в самом коде тоже можно оптимизировать. Про вынос стрингхешей уже сказали.
Еще например функция GetWorldBounds(), насколько помнится, создает новый рект каждый вызов. То есть его как минимум надо удалять после этого. А лучше только один раз ее вызвать и тоже просто загнать в глобалку на всю игру. Или можно пользоваться БЖшной глобалкой bj_mapInitialPlayableArea (но она учитывает только играбельную зону карты, без черных краев).
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
33
Я делал бенчмарк (на попугаях Анрайза) прохода по глобальной группе и локально создаваемой группе, разницы практически нет.
Наконец-то некоторые начинают понимать что разницы практически нет и этим можно пренебречь
32
Bergi_Bear, ну я тоже много чего проверял с анрайзом, и давно писал - есть в мемхаке примитивный тестер на ресурсоемкость кода, и все можно самому проверить.

JackFastGame, просто создавать и удалять группу никчему, есть глобалки внезапно, вот и не будут утечки плодится, очистка происходит не сразу а спустя некоторое время.
25
  1. Для таймера в 0.01 оптимизация все же важна
  2. Группу надо 1 глобальную. И вообще не добавлять в нее юнитов, а все делать в фильтре.
globals
    group TWGroup = CreateGroup()
endglobals

function TerribleWounds_Filter takes nothing returns boolean
    local unit TWUnit = GetFilterUnit()
    local real TerribleWoundsCount = LoadReal(H, GetHandleId(TWUnit), StringHash("TerribleWoundsCount"))
    local real UnitLifeOld = LoadReal(H, GetHandleId(TWUnit), StringHash("UnitLifeOld"))
    local real UnitLifeNow = GetUnitState(TWUnit, UNIT_STATE_LIFE)

    if TerribleWoundsCount > 1 then
        set TerribleWoundsCount = 1
    endif

    if (UnitLifeOld < UnitLifeNow) and UnitLifeOld != 0 and TerribleWoundsCount != 0 then
        call SetUnitState(TWUnit, UNIT_STATE_LIFE, (UnitLifeNow - (UnitLifeNow - UnitLifeOld) * TerribleWoundsCount))
    endif

    set UnitLifeOld = GetUnitState(TWUnit, UNIT_STATE_LIFE)
    call SaveReal(H, GetHandleId(TWUnit), StringHash("UnitLifeOld"), UnitLifeOld)

    set TWUnit = null

    return false
endfunction

function Trig_TerribleWounds_Actions takes nothing returns nothing
    call GroupEnumUnitsInRect(TWGroup, GetWorldBounds(), Filter(function TerribleWounds_Filter))
endfunction

//===========================================================================
function InitTrig_TerribleWounds takes nothing returns nothing
    local trigger TerribleWoundsTrigger

    set TerribleWoundsTrigger = CreateTrigger( )
    call TriggerRegisterTimerEvent(TerribleWoundsTrigger, 0.01, true)
    call TriggerAddAction(TerribleWoundsTrigger, function Trig_TerribleWounds_Actions)

    set TerribleWoundsTrigger = null
endfunction
32
стрингхеши тоже можно вывести в глобалки, это хоть немного но быстрее.
25
Да, в самом коде тоже можно оптимизировать. Про вынос стрингхешей уже сказали.
Еще например функция GetWorldBounds(), насколько помнится, создает новый рект каждый вызов. То есть его как минимум надо удалять после этого. А лучше только один раз ее вызвать и тоже просто загнать в глобалку на всю игру. Или можно пользоваться БЖшной глобалкой bj_mapInitialPlayableArea (но она учитывает только играбельную зону карты, без черных краев).
Принятый ответ
14
quq_CCCP:
стрингхеши тоже можно вывести в глобалки, это хоть немного но быстрее.
можно по подробнее?

Hanabishi:
Да, в самом коде тоже можно оптимизировать. Про вынос стрингхешей уже сказали.
Еще например функция GetWorldBounds(), насколько помнится, создает новый рект каждый вызов. То есть его как минимум надо удалять после этого. А лучше только один раз ее вызвать и тоже просто загнать в глобалку на всю игру. Или можно пользоваться БЖшной глобалкой bj_mapInitialPlayableArea (но она учитывает только играбельную зону карты, без черных краев).
Не научите ими пользоваться а то мой знакомый говорит что функция IsTerrainPathable ресурсоемкая и лучше устанавливать границы карты
28
Гуванч, я не говорил что нужно устанавливать границы карты, я говорил что её стоит заменить на проверку проходимости предметом)

А если про границы карты, то я тебе уже скидывал спелл с бумерангом как что и почему, там и юзаются границы
32
Гуванч, ептить...
globals
integer ExMySpellKey = StringHash("Ура в жопе дыра")
endglobals
....
set t = LoadTriggerHandle( HashTable, ExMySpellKey, GetHandleId(unit))
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.