Здраствуйте. Небольшая предыстория. Шел я значит по триггерам, проверял все как мог. И тут дошел до действия с заменой юнита:
Конвертнул его в текст, нашел бж, сразу пошел её проверять
В указанной статье она описана как с утечкой, значит надо что-то делать.
И тут я решил испытать новый подход:
в function list нашел собственно функцию ReplaceUnitBJ, на глаз попытался определить что тут утекает(и что нужно обнулить). Далее скопировал, дописал как надо( set oldUnit = null и set indexItem = null), конвертнул мой триггер в код, функцию написал как без БЖ и собственно проверил. Оно вроде бы заработало, далее я перенес её в шапку карты, оно приняло там такой вид:
function ReplaceUnit takes unit whichUnit, integer newUnitId, integer unitStateMethod returns unit
    local unit    oldUnit = whichUnit
    local unit    newUnit
    local boolean wasHidden
    local integer index
    local item    indexItem
    local real    oldRatio

    // If we have bogus data, don't attempt the replace.
    if (oldUnit == null) then
        set bj_lastReplacedUnit = oldUnit
        return oldUnit
    endif

    // Hide the original unit.
    set wasHidden = IsUnitHidden(oldUnit)
    call ShowUnit(oldUnit, false)

    // Create the replacement unit.
    if (newUnitId == 'ugol') then
        set newUnit = CreateBlightedGoldmine(GetOwningPlayer(oldUnit), GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
    else
        set newUnit = CreateUnit(GetOwningPlayer(oldUnit), newUnitId, GetUnitX(oldUnit), GetUnitY(oldUnit), GetUnitFacing(oldUnit))
    endif

    // Set the unit's life and mana according to the requested method.
    if (unitStateMethod == bj_UNIT_STATE_METHOD_RELATIVE) then
        // Set the replacement's current/max life ratio to that of the old unit.
        // If both units have mana, do the same for mana.
        if (GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE) > 0) then
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_LIFE) / GetUnitState(oldUnit, UNIT_STATE_MAX_LIFE)
            call SetUnitState(newUnit, UNIT_STATE_LIFE, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
        endif

        if (GetUnitState(oldUnit, UNIT_STATE_MAX_MANA) > 0) and (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
            set oldRatio = GetUnitState(oldUnit, UNIT_STATE_MANA) / GetUnitState(oldUnit, UNIT_STATE_MAX_MANA)
            call SetUnitState(newUnit, UNIT_STATE_MANA, oldRatio * GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
        endif
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_ABSOLUTE) then
        // Set the replacement's current life to that of the old unit.
        // If the new unit has mana, do the same for mana.
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(oldUnit, UNIT_STATE_LIFE))
        if (GetUnitState(newUnit, UNIT_STATE_MAX_MANA) > 0) then
            call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(oldUnit, UNIT_STATE_MANA))
        endif
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_DEFAULTS) then
        // The newly created unit should already have default life and mana.
    elseif (unitStateMethod == bj_UNIT_STATE_METHOD_MAXIMUM) then
        // Use max life and mana.
        call SetUnitState(newUnit, UNIT_STATE_LIFE, GetUnitState(newUnit, UNIT_STATE_MAX_LIFE))
        call SetUnitState(newUnit, UNIT_STATE_MANA, GetUnitState(newUnit, UNIT_STATE_MAX_MANA))
    else
        // Unrecognized unit state method - ignore the request.
    endif

    // Mirror properties of the old unit onto the new unit.
    //call PauseUnit(newUnit, IsUnitPaused(oldUnit))
    call SetResourceAmount(newUnit, GetResourceAmount(oldUnit))

    // If both the old and new units are heroes, handle their hero info.
    if (IsUnitType(oldUnit, UNIT_TYPE_HERO) and IsUnitType(newUnit, UNIT_TYPE_HERO)) then
        call SetHeroXP(newUnit, GetHeroXP(oldUnit), false)

        set index = 0
        loop
            set indexItem = UnitItemInSlot(oldUnit, index)
            if (indexItem != null) then
                call UnitRemoveItem(oldUnit, indexItem)
                call UnitAddItem(newUnit, indexItem)
            endif

            set index = index + 1
            exitwhen index >= bj_MAX_INVENTORY
        endloop
    endif

    // Remove or kill the original unit.  It is sometimes unsafe to remove
    // hidden units, so kill the original unit if it was previously hidden.
    if wasHidden then
        call KillUnit(oldUnit)
        call RemoveUnit(oldUnit)
    else
        call RemoveUnit(oldUnit)
    endif

    set bj_lastReplacedUnit = newUnit
    set oldUnit = null
    set indexItem = null
    return newUnit
    
    
endfunction
В конвертнутом тригге тоже заменил бж на мною созданную "Починенную" функцию.
И вроде бы, по моему мнению, я должен был утечек избежать. Но таблица хендлов начинает скакать то назад, то вперед, а через некоторое время резко доходит до числа 52к+-. Есть два вопроса. Один по поводу того, что я тут наделал: в правильном направлении я шел и убрал ли я утечки этого действия (на большой карте тяжело отследить результат от этого конкретного действия). Второй вопрос: почему постоянно, когда опять же что-то утекает, вдруг происходит взрывной рост до 52+- тысяч. То есть катализатором может быть любой кривой код, но чую причина взрывного роста какая-та иная (может тоже связана с масштабом карты, а может и систему учета утечек не справляется.
В общем, буду благодарен за наводки и предположения.

Принятый ответ

VinerX, посмотри гуи функцию "пропустить остальные действия" по факту это слово "return" в коде, то есть после ретурна ты никак не поставишь set newUnit = null, и правильно это делать после set bj_lastReplacedUnit = newUnit, а возвращать не newUnit, а bj_lastReplacedUnit, вот код если непонятно
set bj_lastReplacedUnit = newUnit
set newUnit = null
set oldUnit = null
set indexItem = null
return bj_lastReplacedUnit
`
ОЖИДАНИЕ РЕКЛАМЫ...
1
27
3 года назад
1
Второй вопрос: почему постоянно, когда опять же что-то утекает, вдруг происходит взрывной рост до 52+- тысяч.
показывай счётчик

а в коде, приложенном к посту, утекает необнуление newUnit
0
14
3 года назад
Отредактирован VinerX
0
В вот по поводу newUnit, я его попытался обнулить (ставил после return), он мне ошибку выдавал (тогда подумал что значение, которое уходит в ретурн обнулять не надо). Это как нужно реализовать?
Код счетчика, который находится в шапке карты в самом верху:
function HandleCounter_Update takes nothing returns nothing
   local integer i = 0
   local integer id = 0
   local location array P
   local real result=0
   loop
      exitwhen i >= 50
      set i = i + 1
      set P[i] = Location(0,0)
      set id = GetHandleId(P[i])
      set result = result + (id-0x100000)
   endloop
   set result = result/i-i/2
   loop
      call RemoveLocation(P[i])
      set P[i] = null
      exitwhen i <= 1
      set i = i - 1
   endloop
   call LeaderboardSetItemValue(udg_HandleBoard,0,R2I(result))
endfunction

function HandleCounter_Actions takes nothing returns nothing
   set udg_HandleBoard = CreateLeaderboard()
   call LeaderboardSetLabel(udg_HandleBoard, "Handle Counter")
   call PlayerSetLeaderboard(GetLocalPlayer(),udg_HandleBoard)
   call LeaderboardDisplay(udg_HandleBoard,true)
   call LeaderboardAddItem(udg_HandleBoard,"Handles",0,Player(0))
   call LeaderboardSetSizeByItemCount(udg_HandleBoard,1)
   call HandleCounter_Update()
   call TimerStart(GetExpiredTimer(),0.05,true,function HandleCounter_Update)
endfunction

function InitTrig_HandleCounter takes nothing returns nothing
   call TimerStart(CreateTimer(),0,false,function HandleCounter_Actions)
endfunction
+запуск(хз, нужен ли он)

Обратно к функции, если добавляю set newUnit = null, ловлю такую ошибку.
set bj_lastReplacedUnit = newUnit
    set oldUnit = null
    set indexItem = null
    return newUnit
    set newUnit = null
Загруженные файлы
1
27
3 года назад
Отредактирован rsfghd
1
VinerX, посмотри гуи функцию "пропустить остальные действия" по факту это слово "return" в коде, то есть после ретурна ты никак не поставишь set newUnit = null, и правильно это делать после set bj_lastReplacedUnit = newUnit, а возвращать не newUnit, а bj_lastReplacedUnit, вот код если непонятно
set bj_lastReplacedUnit = newUnit
set newUnit = null
set oldUnit = null
set indexItem = null
return bj_lastReplacedUnit
Принятый ответ
0
14
3 года назад
0
rsfghd,
Так, ну по поводу ретурна понял, огромное спасибо.
А вот случалось нечто подобное из второго вопроса(резкий необъясним скачек хендлов) ? Понимаю, может его сформулировал не понятно, но вдруг. Ну и хендлкаунтер, с ним как, все нормально?
1
27
3 года назад
Отредактирован rsfghd
1
VinerX, не-а, по счётчику ничего не обнаружил и никогда подобного не случалось если были какие-то малейшие изменения
но имей ввиду, хэндлы это всё что находится на карте кроме дудадов
Чтобы оставить комментарий, пожалуйста, войдите на сайт.