globals
    unit missle
    real magX
    real magY
    real tarX
    real tarY
endglobals

function Trig_Froze_Conditions takes nothing returns boolean
    if GetSpellAbilityId() == 'A000' then
        return true
    endif
    return false
endfunction

function Check takes nothing returns boolean
    return GetBooleanAnd( IsUnitAliveBJ(GetFilterUnit()), GetOwningPlayer(GetFilterUnit()) != GetOwningPlayer(missle) )
endfunction

function CheckActions takes nothing returns nothing
    local unit picked = GetEnumUnit()
    SetUnitLifeBJ( picked, ( GetUnitStateSwap(UNIT_STATE_LIFE, picked) - 250.00 ) )
    SetUnitLifePercentBJ( picked, ( GetUnitLifePercent(picked) - 5.00 ) )
    AddSpecialEffect( "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", GetUnitX(picked), GetUnitY(picked) )
    DestroyEffect(GetLastCreatedEffectBJ())
    set picked = null
endfunction

function Move takes nothing returns nothing
    local real vecX = ( tarX - magX ) / ((SquareRoot((tarX-magX) * (tarX-magX) + (tarY-magY) * (tarY-magY)) ) / 2 )
    local real vecY = ( tarY - magY ) / ((SquareRoot((tarX-magX) * (tarX-magX) + (tarY-magY) * (tarY-magY)) ) / 2 )
    local real misX = GetUnitX(missle)
    local real misY = GetUnitY(missle)
    local group g = CreateGroup()
    call GroupEnumUnitsInRange( g, misX, misY, 150, Condition(function Check) )
    local group check = g
    SetUnitX(missle, misX + vecX)
    SetUnitY(missle, misY + vecY)
    if SquareRoot((tarX-misX) * (tarX-misX) + (tarY-misY) * (tarY-misY)) < 100 then
        DestroyTimer(GetExpiredTimer())
        RemoveUnit(missle)
        ForGroup( check, function CheckActions )
    endif
    DestroyGroup(g)
    DestroyGroup(check)
    set g = null
    set check = null
endfunction

function Trig_Froze_Actions takes nothing returns nothing
    local unit mage = GetSpellAbilityUnit()
    local unit target = GetSpellTargetUnit()
    local timer t = CreateTimer()
    //  RemoveUnit(missle)
    //  set missle = null
    set magX = GetUnitX(mage)
    set magY = GetUnitY(mage)
    set tarX = GetUnitX(target)
    set tarY = GetUnitY(target)
    set missle = CreateUnit( GetOwningPlayer( mage ), 'hpea', magX, magY, 270 )
    TimerStart( t, 0.01, true, function Move )
    set mage = null
    set target = null
    set t = null
endfunction

//===========================================================================
function InitTrig_Froze takes nothing returns nothing
    set gg_trg_Froze = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Froze, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition( gg_trg_Froze, Condition( function Trig_Froze_Conditions ) )
    call TriggerAddAction( gg_trg_Froze, function Trig_Froze_Actions )
endfunction
(Когда я удаляю missle в начале, то юнит не спавнится, по этому я закоментил 2 линии.)
При использовании способности появляется 2-3 хендла и при срабатывании CheckActions 2-4 хендла. Где происходит утечка?

у тебя не удаляется последний созданный эффект потому что ты не особо понимаешь основ пока что
AddSpecialEffect( "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", GetUnitX(picked), GetUnitY(picked) )
DestroyEffect(GetLastCreatedEffectBJ())
--->
bj_lastCreatedEffect = AddSpecialEffect( "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", GetUnitX(picked), GetUnitY(picked) )
DestroyEffect(bj_lastCreatedEffect)
либо же (лучше в твоём случае) --->
DestroyEffect(AddSpecialEffect( "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", GetUnitX(picked), GetUnitY(picked) ) )

внутренности GetLastCreatedEffectBJ() следующие
function GetLastCreatedEffectBJ takes nothing returns effect
    return bj_lastCreatedEffect
endfunction
т.к. ты не присвоил этой переменной никакое значение (свой созданный эффект), то и удалять игре нечего
вот так выглядит гуишная функция создания эффекта
function AddSpecialEffectLocBJ takes location where, string modelName returns effect
    set bj_lastCreatedEffect = AddSpecialEffectLoc(modelName, where)
    return bj_lastCreatedEffect
endfunction


старайся раскрывать красные (бж) функции доставая нативки (это не всегда необходимо), и улучшай логику своего кода, а-ля
function Trig_Froze_Conditions takes nothing returns boolean
    if GetSpellAbilityId() == 'A000' then
        return true
    endif
    return false
endfunction
--->
function Trig_Froze_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction
`
ОЖИДАНИЕ РЕКЛАМЫ...
28
у тебя не удаляется последний созданный эффект потому что ты не особо понимаешь основ пока что
AddSpecialEffect( "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", GetUnitX(picked), GetUnitY(picked) )
DestroyEffect(GetLastCreatedEffectBJ())
--->
bj_lastCreatedEffect = AddSpecialEffect( "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", GetUnitX(picked), GetUnitY(picked) )
DestroyEffect(bj_lastCreatedEffect)
либо же (лучше в твоём случае) --->
DestroyEffect(AddSpecialEffect( "Abilities\\Spells\\Undead\\FrostNova\\FrostNovaTarget.mdl", GetUnitX(picked), GetUnitY(picked) ) )

внутренности GetLastCreatedEffectBJ() следующие
function GetLastCreatedEffectBJ takes nothing returns effect
    return bj_lastCreatedEffect
endfunction
т.к. ты не присвоил этой переменной никакое значение (свой созданный эффект), то и удалять игре нечего
вот так выглядит гуишная функция создания эффекта
function AddSpecialEffectLocBJ takes location where, string modelName returns effect
    set bj_lastCreatedEffect = AddSpecialEffectLoc(modelName, where)
    return bj_lastCreatedEffect
endfunction


старайся раскрывать красные (бж) функции доставая нативки (это не всегда необходимо), и улучшай логику своего кода, а-ля
function Trig_Froze_Conditions takes nothing returns boolean
    if GetSpellAbilityId() == 'A000' then
        return true
    endif
    return false
endfunction
--->
function Trig_Froze_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == 'A000'
endfunction
Принятый ответ
32
Ну код конечно у тебя не ахти, вот пример кода из доты:

function IsUnitDead takes unit u returns boolean
  return GetUnitTypeId(u)<1 or IsUnitType(u,UNIT_TYPE_DEAD)==true
endfunction

function ID1 takes nothing returns boolean
  local trigger t=GetTriggeringTrigger()
  local integer S5I=GetHandleId(t)
  local integer PCI=(LoadInteger(HashData,(S5I),(30)))
  local unit P8I=NYI(PCI)
  local integer IE1=(LoadInteger(HashData,(S5I),(43)))
  local unit P7I=NYI(IE1)
  local real IF1=(LoadReal(HashData,(S5I),(44)))
  local unit IG1=(LoadUnitHandle(HashData,(S5I),(45)))
  local real x=GetUnitX(IG1)
  local real y=GetUnitY(IG1)
  local real QJI=GetUnitX(P8I)
  local real QKI=GetUnitY(P8I)
  local real IH1=IF1*0.03
  local real IZ1=UEI(x,y,QJI,QKI)
  local real IV1=x+IH1*Cos(IZ1*bj_DEGTORAD)
  local real IW1=y+IH1*Sin(IZ1*bj_DEGTORAD)
  local boolean IX1=(LoadBoolean(HashData,(S5I),(698)))
  local boolean IY1=(LoadBoolean(HashData,(S5I),(818)))
  call SetUnitX(IG1,IV1)
  call SetUnitY(IG1,IW1)
  call SetUnitFacing(IG1,IZ1)
  if IsUnitDead(P8I)and IX1==false or(((LoadInteger(HashData,(GetHandleId((P8I))),((4422))))==1)==true and IY1==true)then
    call KillUnit(IG1)
    call NXI(PCI)
    call FlushChildHashtable(HashData,(S5I))
    call S0I(t)
  elseif UTI(QJI,QKI,IV1,IW1)<=IH1 then
    call KillUnit(IG1)
    set GK=P7I
    set HK=P8I
    call ExecuteFunc((LoadStr(HashData,(S5I),(46))))
    call NXI(PCI)
    call FlushChildHashtable(HashData,(S5I))
    call S0I(t)
  endif
  set t=null
  set P8I=null
  set P7I=null
  set IG1=null
  return false
endfunction

function IJ1 takes unit P7I,unit P8I,integer IK1,string IL1,real IF1,boolean IM1 returns trigger
  local trigger t=CreateTrigger()
  local integer S5I=GetHandleId(t)
  local real QXI=GetUnitX(P7I)
  local real QYI=GetUnitY(P7I)
  local real IN1=GetUnitFacing(P7I)
  call TriggerRegisterTimerEvent(t,0.03,true)
  call TriggerAddCondition(t,Condition(function ID1))
  call SaveReal(HashData,(S5I),(44),((IF1)*1.0))
  call SaveInteger(HashData,(S5I),(30),(NKI(P8I)))
  call SaveStr(HashData,(S5I),(46),(IL1))
  call SaveInteger(HashData,(S5I),(43),(NKI(P7I)))
  call SaveUnitHandle(HashData,(S5I),(45),(CreateUnit(GetOwningPlayer(P7I),IK1,QXI,QYI,IN1)))
  call SaveBoolean(HashData,(S5I),(698),(false))
  call SaveBoolean(HashData,(S5I),(818),(IM1))
  set WK=t
  set t=null
  return WK
endfunction
Это готовая наработка для создание снарядов из юнитов,
используется так
  local trigger t=IJ1(DKI,GetEnumUnit(),'h0D8',"MT3",400,false)
кто кастер, кто цель, ид юнита снаряда, имя функции которая вызывается при попадании, скорость в секунду, уничтожаем снаряд если цель подохла или недосигаем.
Функция возвращает триггер, на ID которого мы можем записать остальные данные и получить их в другой функции.
Код тоже не идеален, но вполне удобен, юзаются триггеры вместо таймеров, т.к тут отслеживаются события.
4
Ну код конечно у тебя не ахти, вот пример кода из доты:

function IsUnitDead takes unit u returns boolean
  return GetUnitTypeId(u)<1 or IsUnitType(u,UNIT_TYPE_DEAD)==true
endfunction

function ID1 takes nothing returns boolean
  local trigger t=GetTriggeringTrigger()
  local integer S5I=GetHandleId(t)
  local integer PCI=(LoadInteger(HashData,(S5I),(30)))
  local unit P8I=NYI(PCI)
  local integer IE1=(LoadInteger(HashData,(S5I),(43)))
  local unit P7I=NYI(IE1)
  local real IF1=(LoadReal(HashData,(S5I),(44)))
  local unit IG1=(LoadUnitHandle(HashData,(S5I),(45)))
  local real x=GetUnitX(IG1)
  local real y=GetUnitY(IG1)
  local real QJI=GetUnitX(P8I)
  local real QKI=GetUnitY(P8I)
  local real IH1=IF1*0.03
  local real IZ1=UEI(x,y,QJI,QKI)
  local real IV1=x+IH1*Cos(IZ1*bj_DEGTORAD)
  local real IW1=y+IH1*Sin(IZ1*bj_DEGTORAD)
  local boolean IX1=(LoadBoolean(HashData,(S5I),(698)))
  local boolean IY1=(LoadBoolean(HashData,(S5I),(818)))
  call SetUnitX(IG1,IV1)
  call SetUnitY(IG1,IW1)
  call SetUnitFacing(IG1,IZ1)
  if IsUnitDead(P8I)and IX1==false or(((LoadInteger(HashData,(GetHandleId((P8I))),((4422))))==1)==true and IY1==true)then
    call KillUnit(IG1)
    call NXI(PCI)
    call FlushChildHashtable(HashData,(S5I))
    call S0I(t)
  elseif UTI(QJI,QKI,IV1,IW1)<=IH1 then
    call KillUnit(IG1)
    set GK=P7I
    set HK=P8I
    call ExecuteFunc((LoadStr(HashData,(S5I),(46))))
    call NXI(PCI)
    call FlushChildHashtable(HashData,(S5I))
    call S0I(t)
  endif
  set t=null
  set P8I=null
  set P7I=null
  set IG1=null
  return false
endfunction

function IJ1 takes unit P7I,unit P8I,integer IK1,string IL1,real IF1,boolean IM1 returns trigger
  local trigger t=CreateTrigger()
  local integer S5I=GetHandleId(t)
  local real QXI=GetUnitX(P7I)
  local real QYI=GetUnitY(P7I)
  local real IN1=GetUnitFacing(P7I)
  call TriggerRegisterTimerEvent(t,0.03,true)
  call TriggerAddCondition(t,Condition(function ID1))
  call SaveReal(HashData,(S5I),(44),((IF1)*1.0))
  call SaveInteger(HashData,(S5I),(30),(NKI(P8I)))
  call SaveStr(HashData,(S5I),(46),(IL1))
  call SaveInteger(HashData,(S5I),(43),(NKI(P7I)))
  call SaveUnitHandle(HashData,(S5I),(45),(CreateUnit(GetOwningPlayer(P7I),IK1,QXI,QYI,IN1)))
  call SaveBoolean(HashData,(S5I),(698),(false))
  call SaveBoolean(HashData,(S5I),(818),(IM1))
  set WK=t
  set t=null
  return WK
endfunction
Это готовая наработка для создание снарядов из юнитов,
используется так
  local trigger t=IJ1(DKI,GetEnumUnit(),'h0D8',"MT3",400,false)
кто кастер, кто цель, ид юнита снаряда, имя функции которая вызывается при попадании, скорость в секунду, уничтожаем снаряд если цель подохла или недосигаем.
Функция возвращает триггер, на ID которого мы можем записать остальные данные и получить их в другой функции.
Код тоже не идеален, но вполне удобен, юзаются триггеры вместо таймеров, т.к тут отслеживаются события.
local geu = GetEnumUnit()
geu = nil zabyl
21
если ты создал handle на время, типа эффект или юнит, то значит его нужно потом удалить, иначе будет утечка
если ты создал handle юнит — героя при старте мапы игроку, то он будет у тебя до конца игры
ничего сложного
Чтобы оставить комментарий, пожалуйста, войдите на сайт.