Добавлен
Я сделал способность, но она утекает. В коде не нашел утечек, но они где то есть. Помогите найти пожалуйста
карта:
видео:
globals
    real rx
    real ry
    unit array sum
endglobals

function Trig_R_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A006'
endfunction

function Filter_Enemy takes nothing returns boolean
    local unit u = GetFilterUnit()
    local integer id = GetUnitTypeId(u)
    // юнит: (не юнит игрока) и (не мертв) и (не структура)
    local boolean check = ( GetOwningPlayer(u) != GetOwningPlayer(sum[15]) ) and (GetUnitState(u, UNIT_STATE_LIFE) > 0) and ( IsUnitIdType(id, UNIT_TYPE_STRUCTURE) == false )
    set u = null
    return check
endfunction

function Filter_Vedmyak takes nothing returns boolean
    local unit u = GetFilterUnit()
    local integer id = GetUnitTypeId(u)
    // юнит: (не мертв) и (не структура) и (не юнит игрока)
    local boolean check = ( id == 'h006' ) and (GetUnitState(u, UNIT_STATE_LIFE) > 0)
    set u = null
    return check
endfunction

function Stun_R takes unit enemy, unit u returns nothing
    local real ux = GetUnitX(u)
    local real uy = GetUnitY(u)
    local real x = GetUnitX(enemy)
    local real y = GetUnitY(enemy)
    local real a = Atan2(y-uy, x-ux)
    local effect specef
    // стан
    local unit dummy = CreateUnit(GetOwningPlayer(u), 'u000', x, y, 0.) // Создадим дамми в координатах цели
    call UnitApplyTimedLife(dummy, 'BTLF', 1) // Укажем время жизни дамми
    call UnitAddAbility(dummy, 'A007')
    call IssueTargetOrder(dummy, "thunderbolt", enemy)
    set dummy = null
    // двигаем
    call SetUnitX(enemy, x + 40*Cos(a))
    call SetUnitY(enemy, y + 40*Sin(a))
    // визуал
    call SetUnitAnimation(u, "spell")
    set specef = AddSpecialEffect("Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl", ux, uy)
    call DestroyEffect(specef)
    set specef = null
endfunction

function Vedmyak takes nothing returns nothing
    local unit u = GetEnumUnit()
    local unit enemy
    local group g = CreateGroup()
    local real ux = GetUnitX(u) // позиция юнита
    local real uy = GetUnitY(u)
    local real x // позиция врага
    local real y
    local real a
    call GroupEnumUnitsInRange(g, ux, uy, 100, Condition(function Filter_Enemy))
    loop
    set enemy = FirstOfGroup(g)
    exitwhen enemy == null
    call Stun_R(enemy, u)
    call GroupRemoveUnit(g, enemy)
    endloop
    call DestroyGroup(g)
    set g = null
    set u = null
    set enemy = null
endfunction

function NoEscape takes nothing returns nothing
    local timer t = GetExpiredTimer()
    local group g = CreateGroup()
    local unit u
    
    call GroupEnumUnitsInRange(g, rx, ry, 450, Condition(function Filter_Vedmyak))
    set u = FirstOfGroup(g)
    if u == null then
        call PauseTimer(t)
        call DestroyTimer(t)
    else
        call ForGroup(g, function Vedmyak)
    endif
    call DestroyGroup(g)
    set g = null
    set u = null
    set t = null
endfunction

function CreateArena takes player owner returns nothing
    local integer i = 0
    local real a
    local real ux
    local real uy
    loop
        exitwhen i >= 15 // Создаёт 8 стен, образуя круг
        set a = i * 24 * bj_DEGTORAD
        set ux = rx + 400 * Cos(a)
        set uy = ry + 400 * Sin(a)
        set a = Atan2(ry-uy, rx-ux) * bj_RADTODEG
        set sum[i+14] = CreateUnit(owner, 'h006', ux, uy, a)
        call SetUnitAnimation(sum[i+14], "stand defend")
        call UnitApplyTimedLife(sum[i+14], 'BFig', 3) // Исчезает через 10 сек sum i +14
        set i = i + 1
    endloop
endfunction

function Trig_R_Actions takes nothing returns nothing
    local timer t = CreateTimer()
    local unit caster = GetTriggerUnit()
    local player owner = GetOwningPlayer(caster)
    set rx = GetSpellTargetX()
    set ry = GetSpellTargetY()

    call CreateArena(owner)
    call TimerStart(t, 0.1, true, function NoEscape)

    set t = null
    set caster = null
    set owner = null
endfunction

function InitTrig_R takes nothing returns nothing
    local trigger trg = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(trg, EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(trg, Condition(function Trig_R_Conditions))
    call TriggerAddAction(trg, function Trig_R_Actions)
endfunction

Начни с того, чтоб юзать нормальный счётчик хэндлов.

И зачем ты плодишь переменные еффектов?
set specef = AddSpecialEffect("Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl", ux, uy)
call DestroyEffect(specef)
set specef = null
Можно же проще:
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl", ux, uy))
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
8
set dummy = null
Это не удаление даммика, это обнуление переменной, нужно RemoveUnit(dummy)
Ответы (1)
13
Tredor46, у него есть в коде call UnitApplyTimedLife(dummy, 'BTLF', 1), которая должна освободить память после разложения.
8
Эвенты у тебя короче не очищаются
Загруженные файлы
30
Начни с того, чтоб юзать нормальный счётчик хэндлов.

И зачем ты плодишь переменные еффектов?
set specef = AddSpecialEffect("Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl", ux, uy)
call DestroyEffect(specef)
set specef = null
Можно же проще:
call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl", ux, uy))
Принятый ответ
15
Так же, разве обязательно плеера обнулять?
Это же целочисленная?

Этот счётчик хэндлов при быстром создании и удалении эффектов багается.
Так что попробуй убрать эффекты и утечки посчитать.
6
Tredor46, ивенты это типо события? события тоже утекают что ли
nazarpunk, но я же использовал сразу два счетчика, чтобы наверняка, или они оба неправильно работают и на самом деле нет утечек памяти? про эффекты не знал, отныне буду так делать.
LastUchiha, я на всякий случай обнуляю все хендлы, чтообы наверняка не было утечек.
Так что попробуй убрать эффекты и утечки посчитать.
а на видео и так не создаются эффекты, но я попробовал без спец эффектов - все равно утечка.

Ответы (3)
30
но я же использовал сразу два счетчика, чтобы наверняка
Ога, особенно тот, который спамит локации. Вот, выбирай любой на вкус.
6
так этот же и исполльзуется на видео, под первым счетчиком
а в этом не показывается общее количество хенлдов, так что трудно понять утекает или нет
30
под первым счетчиком
Только вот первый счётчик по кд спамит хэндлы. А в мониторе зачем тебе общее количество? Ты по типам смотри.
13
Тут нужно оптимизировать код, много вижу лишних функций с группами. Если я правильно понял, твой скил мгновенный, создает в точке каста вокруг ведьмаков, которые станят вокруг себя в радиусе 100.
Более оптимизированная версия, попробуй проверить ее на уточки.
globals
    group TempGroup = CreateGroup()
endglobals

function Trig_R_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A006'
endfunction

function Stun_R takes unit enemy, unit u returns nothing
    local real ux = GetUnitX(u)
    local real uy = GetUnitY(u)
    local real x = GetUnitX(enemy)
    local real y = GetUnitY(enemy)
    local real a = Atan2(y-uy, x-ux)
    // стан
    local unit dummy = CreateUnit(GetOwningPlayer(u), 'u000', x, y, 0.) // Создадим дамми в координатах цели
    
    call UnitApplyTimedLife(dummy, 'BTLF', 1) // Укажем время жизни дамми
    call UnitAddAbility(dummy, 'A007')
    call IssueTargetOrder(dummy, "thunderbolt", enemy)
    // двигаем
    call SetUnitX(enemy, x + 40*Cos(a))
    call SetUnitY(enemy, y + 40*Sin(a))
    // визуал
    call SetUnitAnimation(u, "spell")
    call DestroyEffect(AddSpecialEffect("Abilities\\Spells\\Other\\Incinerate\\IncinerateBuff.mdl", ux, uy))
    
    set dummy = null
endfunction

function Trig_R_Actions takes nothing returns nothing
    local unit caster = GetTriggerUnit()
    local integer i = 0
    local real a
    local real ux
    local real uy
    local unit witchers
    local unit enemy
    local real rx = GetSpellTargetX()
    local real ry = GetSpellTargetY()
    
    loop
    exitwhen i >= 15 // Создаёт 8 стен, образуя круг
        set a = i * 24 * bj_DEGTORAD
        set ux = rx + 400 * Cos(a)
        set uy = ry + 400 * Sin(a)
        set a = Atan2(ry-uy, rx-ux) * bj_RADTODEG
        set witchers = CreateUnit(GetOwningPlayer(caster), 'h006', ux, uy, a)
        call SetUnitAnimation(witchers, "stand defend")
        call UnitApplyTimedLife(witchers, 'BFig', 3) // Исчезает через 10 сек sum i +14
        
        call GroupEnumUnitsInRange(TempGroup, ux, uy, 100, null)
        loop
            set enemy = FirstOfGroup(TempGroup)
        exitwhen enemy == null
            if IsPlayerEnemy( GetOwningPlayer(caster), GetOwningPlayer(enemy)) and UnitAlive(enemy) and not IsUnitIdType(GetUnitTypeId(enemy), UNIT_TYPE_STRUCTURE) then
                call Stun_R(enemy, witchers)
            endif
            call GroupRemoveUnit(TempGroup, enemy)
            set enemy = null
        endloop
        set witchers = null
        set i = i + 1
    endloop
    call GroupClear(TempGroup)
    
    set caster = null
endfunction

function InitTrig_R takes nothing returns nothing
    local trigger trg = CreateTrigger()
    local integer index = 0

    loop
        call TriggerRegisterPlayerUnitEvent(trg, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
    
    call TriggerAddCondition(trg, Condition(function Trig_R_Conditions))
    call TriggerAddAction(trg, function Trig_R_Actions)
    
    set trg = null
endfunction
Ответы (8)
30
SoulRazor, зачем ты делаешь set enemy = null если переменная и так станет null в этом месте set enemy = FirstOfGroup(TempGroup)?
И зачем очищать call GroupClear(TempGroup) если она и так очищается перебором?
6
SoulRazor, спасибо за оптимизированный код, но дело в не в коде оказывается.
    local trigger trg = CreateTrigger()
    local integer index = 0

    loop
        call TriggerRegisterPlayerUnitEvent(trg, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
    endloop
Это получается делает способность муишной? Я не совсем понял эту часть
30
Это получается делает способность муишной?
Именно это не делает. Здесь он просто руками событие на всех зарегестрировал.
Хотя мне больше нравится условие выхода как можно выше переносить.
local integer index = -1
loop
        set index = index + 1
        exitwhen index == bj_MAX_PLAYER_SLOTS
        call TriggerRegisterPlayerUnitEvent(trg, Player(index), EVENT_PLAYER_UNIT_SPELL_EFFECT, null)
endloop
30
а зачем тогда так писать?
Привычка и вкусовщина. А если ты за то, что цикл руками написан, то представь что у тебя не один триггер. Ради каждого по всем игорькам пробегать?
15
nazarpunk, после таких открытий xgm.guru/p/wc3/firstofgroup-caution это имеет смысл, я делаю так же. Лучше конечно не использовать ручной перебор, а вместо него ForGroup, или же перед ручным перебором пересодавать группу. Только так можно избежать утечек, возможных при смерти кого то из юнитов из группы. И даже если в конкретном случае автор уверен, что в перебираемой группе не будет мертвых юнитов, лучше приучать себя писать на все случаи жизни, ибо это варик... Ответил на вопрос об очистке группы (все время забываю как цитировать товарищей по сайту, извините)
30
Лучше конечно не использовать ручной перебор, а вместо него ForGroup, или же перед ручным перебором пересодавать группу.
Зачем лишние действия? Если ты собираешься работать с живыми юнитами, то проверяй на то что они живые. Если собираешься работать с мёртвыми, то проверяй что они мёртвые, но всё еще существующие.
6
Оказывается, первый хедл каунтер ( который призван помогать устранять утечки памяти ) сам утекает!😁А со способностью все хорошо и вроде как он не утекает.
извиняюсь, оказывается этот вопрос можно было бы избежать если бы не моя ошибка
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.