Я больше чем на 70% уверен, что у меня код написан плохо. Так как взаимодействия с отрядами не очень сложилось у меня, прошу помочь оптимизировать код, и убрать лишнее. Наворотил всякого.
Код и карту приложил.
Код:
return GetSpellAbilityId() == 'A001'
endfunction
function FilterR takes nothing returns boolean
local unit z = LoadUnitHandle(udg_Hash,StringHash("x"),1)
local player p = GetOwningPlayer(z)
return  IsPlayerEnemy(p, GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
endfunction
function Trig_R_Boom takes unit d returns nothing
local real x = GetUnitX(d)
local real y = GetUnitY(d)
local group g = CreateGroup()
local unit f
call GroupEnumUnitsInRange(g, x, y,500,Condition(function FilterR))
    loop
    set f = FirstOfGroup(g)
    exitwhen f == null
    call UnitDamageTarget(d,f,400, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null)
    call GroupRemoveUnit(g,f)
endloop
set g = null
set f = null
call DestroyGroup(g)
endfunction
function Trig_LOCAL_TimerR takes nothing returns nothing
local timer timerer = GetExpiredTimer()
local integer i = GetHandleId(timerer)
local unit Caster = LoadUnitHandle(udg_Hash,i,4)
local unit Dummy = LoadUnitHandle(udg_Hash,i,3)
local real xd = GetUnitX(Dummy)
local real yd = GetUnitY(Dummy)
if (GetWidgetLife(Dummy) < 0.405) then
call Trig_R_Boom (Dummy)
call FlushChildHashtable(udg_Hash,i)
call FlushChildHashtable(udg_Hash,StringHash("x"))
call DestroyTimer(timerer)
set Dummy = CreateUnit(GetOwningPlayer(Caster),'u001',xd,yd,0)
call UnitApplyTimedLife(Dummy,'BTLF', 2)
set Caster = null
set Dummy = null
else
set xd=GetUnitX(Dummy)+10*Cos(GetUnitFacing(Dummy)*bj_DEGTORAD)
set yd=GetUnitY(Dummy)+10*Sin(GetUnitFacing(Dummy)*bj_DEGTORAD)
call SetUnitPosition(Dummy,xd,yd)
endif
set Caster = null
set Dummy = null
endfunction

function Trig_R_Actions takes nothing returns nothing
local unit Caster = GetTriggerUnit()
local location Target = GetSpellTargetLoc()
local real xt = GetLocationX(Target)
local real yt = GetLocationY(Target)
local real xc = GetUnitX(Caster)
local real yc = GetUnitY(Caster)
local real Angle = bj_RADTODEG * Atan2(yt-yc,xt-xc)
local unit Dummy = CreateUnit(GetOwningPlayer(Caster),'u000',xc,yc,Angle)
local timer timerer = CreateTimer()
local integer i = GetHandleId(timerer)
call SetUnitAnimation( Dummy, "Birth" )
call UnitApplyTimedLife(Dummy,'BTLF', 1)
call SaveUnitHandle(udg_Hash,i,3,Dummy)
call SaveUnitHandle(udg_Hash,i,4,Caster)
call SaveUnitHandle(udg_Hash,StringHash("x"),1,Caster)
call TimerStart(timerer, 0.01, true, function Trig_LOCAL_TimerR)
call RemoveLocation(Target)
set Caster = null
set Dummy = null
endfunction
Карта:

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

call SaveInteger(udg_Hash,StringHash("x"),1,GetPlayerId(GetOwningPlayer(Caster)))

function Trig_R_Boom takes unit d, unit c returns nothing

call GroupEnumUnitsInRange(g, x, y,500,Condition(function FilterR))
loop
	set f = FirstOfGroup(g)
    exitwhen f == null
    call UnitDamageTarget(c,f,400, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null)
    call GroupRemoveUnit(g,f)
endloop

В конце функции Trig_R_Actions( )не обнулена переменная типа timer.
- Короче, вот:
function Trig_LOCAL_TimerR takes nothing returns nothing
    local  timer   timerer =  GetExpiredTimer( )
    local  integer i       =  GetHandleId( timerer )
    local  unit    Caster  =  LoadUnitHandle( udg_Hash, i, 4 )
    local  unit    Dummy   =  LoadUnitHandle( udg_Hash, i, 3 )
    local  real    xd      =  GetUnitX( Dummy )
    local  real    yd      =  GetUnitY( Dummy )
    local  group   g       =  null
    local  unit    f       =  null

    if ( GetWidgetLife( Dummy ) < 0.405 ) then

        set  g  =  CreateGroup( )

        call GroupEnumUnitsInRange( g, xd, yd, 500.0, null )
        loop
            set  f  =  FirstOfGroup( g )
            exitwhen ( f == null )
            call GroupRemoveUnit( g, f )

            if IsUnitEnemy( f, GetOwningPlayer( Caster ) ) and ( GetWidgetLife( f ) > 0.405 ) and ( not IsUnitType( f, UNIT_TYPE_STRUCTURE ) ) and ( not IsUnitType( f, UNIT_TYPE_FLYING ) ) then
                call UnitDamageTarget( Caster, f, 400.0, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null )
            endif

        endloop

        call DestroyGroup( g )
        set  g  =  null

        call FlushChildHashtable( udg_Hash, i )
        call DestroyTimer( timerer )
        set  Dummy  =  CreateUnit( GetOwningPlayer( Caster ), 'u001', xd, yd, 0.0 )
        call UnitApplyTimedLife( Dummy, 'BTLF', 2.0 )

    else
        set  xd = GetUnitX( Dummy ) + 10.0 * Cos( GetUnitFacing( Dummy ) * bj_DEGTORAD )
        set  yd = GetUnitY( Dummy ) + 10.0 * Sin( GetUnitFacing( Dummy ) * bj_DEGTORAD )
        call SetUnitPosition( Dummy, xd, yd )
    endif

    set  timerer  =  null
    set  Caster   =  null
    set  Dummy    =  null
endfunction


function Trig_R_Actions takes nothing returns nothing
    local  unit     Caster   =  GetTriggerUnit( )
    local  real     xt       =  GetSpellTargetX( )
    local  real     yt       =  GetSpellTargetY( )
    local  real     xc       =  GetUnitX( Caster )
    local  real     yc       =  GetUnitY( Caster )
    local  unit     Dummy    =  CreateUnit( GetOwningPlayer( Caster ), 'u000', xc, yc, bj_RADTODEG * Atan2( yt - yc, xt - xc ) )
    local  timer    timerer  =  CreateTimer( )
    local  integer  i        =  GetHandleId( timerer )

    call SetUnitAnimation( Dummy, "Birth" )
    call UnitApplyTimedLife( Dummy, 'BTLF', 1.0 )
    call SaveUnitHandle( udg_Hash, i, 3, Dummy )
    call SaveUnitHandle( udg_Hash, i, 4, Caster )
    call TimerStart( timerer, 0.01, true, function Trig_LOCAL_TimerR )

    set  Caster   =  null
    set  Dummy    =  null
    set  timerer  =  null
endfunction
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
19
6 лет назад
0
Похожие вопросы:

ответ
Есть, триггер для триггерных скиллов 1, 3 ивента, кастанул, завершил каст, выучил - все, далее условие что абилка в базе данных и собственно действие екзикут функции взятой из базы данных.
ответ
все нормально, релизную карту шлифани vexorian optimiser'ом, и будет тебе счастье
ответ
Alexander69, xgm.guru/p/wc3/optimisations
внимательно прочти то что там написано
особенно про переменные
если коротко то объект не может быть удалён из памяти пока используется (хранится в переменных/хэше/кэше)
ответ
ничем, кроме названий переменных. попробуй отключить морфинг имен
ответ
ClotPh:
Кстати да, тоже интересно. Всегда просто удаляю второй. Я понимаю, что там скорее всего что-то несет информационную ценность, но оно бы тогда хотя бы настраивалось как-то в оптимизаторе, создавать его или не создавать и/или удалить после выполнения оптимизации, а то немного раздражает мусор руками чистить. Если такие настройки есть - подскажите плз.
Это скрип карты, для анализа на ошибки.

4
21
6 лет назад
4
что сразу бросается в глаза:
юзаешь GetSpellTargetLoc вместо GetSpellTargetX, GetSpellTargetY
не обнуляешь локации и таймеры, не обнуляешь юнита в фильтре
вызываешь дейстрой групп после обнуления переменной, то есть разрушаешь null а группа остается висеть
2
7
6 лет назад
Отредактирован WoLLFeR
2
biridius, так, сейчас поправлю. А вот насчет Хэша и переменной игрока, которую я использую тут. Это место больше всего задаёт вопрос.
function FilterR takes nothing returns boolean
local unit z = LoadUnitHandle(udg_Hash,StringHash("x"),1)
local player p = GetOwningPlayer(z)
set z = null
return  IsPlayerEnemy(p, GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
biridius, что-то я тупанул, в общем, можно было просто игрока в хэш сохранить. Насчет группы, её отчистить просто, а потом уничтожить, или как?
function FilterR takes nothing returns boolean
local player p = LoadPlayerHandle(udg_Hash,StringHash("x"),1)
return  IsPlayerEnemy(p, GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
endfunction
biridius, и всё-таки, переменная игрока будет утечкой? может получить индекс игрока, только как?
biridius, Взял индекс, проще, надеюсь правильно
call SaveInteger(udg_Hash,StringHash("x"),1,GetPlayerId(GetOwningPlayer(Caster)))
biridius, Ну как-то так, утечки всё равно есть, но не грубые. Если найдёте еще, напишите пожалуйста.
Результат:
local integer p = LoadInteger(udg_Hash,StringHash("x"),1)
return  IsPlayerEnemy(Player(p), GetOwningPlayer(GetFilterUnit())) and GetWidgetLife(GetFilterUnit()) > 0.405 and not IsUnitType(GetFilterUnit(), UNIT_TYPE_STRUCTURE) and not IsUnitType(GetFilterUnit(), UNIT_TYPE_FLYING)
endfunction
function Trig_R_Boom takes unit d, unit c returns nothing
local real x = GetUnitX(d)
local real y = GetUnitY(d)
local group g = CreateGroup()
local unit f
call GroupEnumUnitsInRange(g, x, y,500,Condition(function FilterR))
    loop
    set f = FirstOfGroup(g)
    exitwhen f == null
    call UnitDamageTarget(c,f,400, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null)
    call GroupRemoveUnit(g,f)
endloop
call GroupClear(g)
call DestroyGroup(g)
set g = null
set f = null
endfunction
function Trig_LOCAL_TimerR takes nothing returns nothing
local timer timerer = GetExpiredTimer()
local integer i = GetHandleId(timerer)
local unit Caster = LoadUnitHandle(udg_Hash,i,4)
local unit Dummy = LoadUnitHandle(udg_Hash,i,3)
local real xd = GetUnitX(Dummy)
local real yd = GetUnitY(Dummy)
if (GetWidgetLife(Dummy) < 0.405) then
call Trig_R_Boom (Dummy,Caster)
call FlushChildHashtable(udg_Hash,i)
call FlushChildHashtable(udg_Hash,StringHash("x"))
call DestroyTimer(timerer)
set Dummy = CreateUnit(GetOwningPlayer(Caster),'u001',xd,yd,0)
call UnitApplyTimedLife(Dummy,'BTLF', 2)
else
set xd=GetUnitX(Dummy)+10*Cos(GetUnitFacing(Dummy)*bj_DEGTORAD)
set yd=GetUnitY(Dummy)+10*Sin(GetUnitFacing(Dummy)*bj_DEGTORAD)
call SetUnitPosition(Dummy,xd,yd)
endif
set Caster = null
set Dummy = null
set timerer = null
endfunction

function Trig_R_Actions takes nothing returns nothing
local unit Caster = GetTriggerUnit()
local real xt = GetSpellTargetX()
local real yt = GetSpellTargetY()
local real xc = GetUnitX(Caster)
local real yc = GetUnitY(Caster)
local real Angle = bj_RADTODEG * Atan2(yt-yc,xt-xc)
local unit Dummy = CreateUnit(GetOwningPlayer(Caster),'u000',xc,yc,Angle)
local timer timerer = CreateTimer()
local integer i = GetHandleId(timerer)
call SetUnitAnimation( Dummy, "Birth" )
call UnitApplyTimedLife(Dummy,'BTLF', 1)
call SaveUnitHandle(udg_Hash,i,3,Dummy)
call SaveUnitHandle(udg_Hash,i,4,Caster)
call SaveInteger(udg_Hash,StringHash("x"),1,GetPlayerId(GetOwningPlayer(Caster)))
call TimerStart(timerer, 0.01, true, function Trig_LOCAL_TimerR)
set Caster = null
set Dummy = null
endfunction
1
21
6 лет назад
1
timerer еще не обнулил в самой нижней функции
0
7
6 лет назад
0
biridius:
timerer еще не обнулил в самой нижней функции
Всё. Спасибо большое.
0
26
6 лет назад
0
А я вот вижу проверку на 0.405 хп, вместо проверки мёртвости юнита
5
21
6 лет назад
Отредактирован scopterectus
5
call SaveInteger(udg_Hash,StringHash("x"),1,GetPlayerId(GetOwningPlayer(Caster)))

function Trig_R_Boom takes unit d, unit c returns nothing

call GroupEnumUnitsInRange(g, x, y,500,Condition(function FilterR))
loop
	set f = FirstOfGroup(g)
    exitwhen f == null
    call UnitDamageTarget(c,f,400, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null)
    call GroupRemoveUnit(g,f)
endloop

В конце функции Trig_R_Actions( )не обнулена переменная типа timer.
- Короче, вот:
function Trig_LOCAL_TimerR takes nothing returns nothing
    local  timer   timerer =  GetExpiredTimer( )
    local  integer i       =  GetHandleId( timerer )
    local  unit    Caster  =  LoadUnitHandle( udg_Hash, i, 4 )
    local  unit    Dummy   =  LoadUnitHandle( udg_Hash, i, 3 )
    local  real    xd      =  GetUnitX( Dummy )
    local  real    yd      =  GetUnitY( Dummy )
    local  group   g       =  null
    local  unit    f       =  null

    if ( GetWidgetLife( Dummy ) < 0.405 ) then

        set  g  =  CreateGroup( )

        call GroupEnumUnitsInRange( g, xd, yd, 500.0, null )
        loop
            set  f  =  FirstOfGroup( g )
            exitwhen ( f == null )
            call GroupRemoveUnit( g, f )

            if IsUnitEnemy( f, GetOwningPlayer( Caster ) ) and ( GetWidgetLife( f ) > 0.405 ) and ( not IsUnitType( f, UNIT_TYPE_STRUCTURE ) ) and ( not IsUnitType( f, UNIT_TYPE_FLYING ) ) then
                call UnitDamageTarget( Caster, f, 400.0, true, false, ATTACK_TYPE_NORMAL, DAMAGE_TYPE_MAGIC, null )
            endif

        endloop

        call DestroyGroup( g )
        set  g  =  null

        call FlushChildHashtable( udg_Hash, i )
        call DestroyTimer( timerer )
        set  Dummy  =  CreateUnit( GetOwningPlayer( Caster ), 'u001', xd, yd, 0.0 )
        call UnitApplyTimedLife( Dummy, 'BTLF', 2.0 )

    else
        set  xd = GetUnitX( Dummy ) + 10.0 * Cos( GetUnitFacing( Dummy ) * bj_DEGTORAD )
        set  yd = GetUnitY( Dummy ) + 10.0 * Sin( GetUnitFacing( Dummy ) * bj_DEGTORAD )
        call SetUnitPosition( Dummy, xd, yd )
    endif

    set  timerer  =  null
    set  Caster   =  null
    set  Dummy    =  null
endfunction


function Trig_R_Actions takes nothing returns nothing
    local  unit     Caster   =  GetTriggerUnit( )
    local  real     xt       =  GetSpellTargetX( )
    local  real     yt       =  GetSpellTargetY( )
    local  real     xc       =  GetUnitX( Caster )
    local  real     yc       =  GetUnitY( Caster )
    local  unit     Dummy    =  CreateUnit( GetOwningPlayer( Caster ), 'u000', xc, yc, bj_RADTODEG * Atan2( yt - yc, xt - xc ) )
    local  timer    timerer  =  CreateTimer( )
    local  integer  i        =  GetHandleId( timerer )

    call SetUnitAnimation( Dummy, "Birth" )
    call UnitApplyTimedLife( Dummy, 'BTLF', 1.0 )
    call SaveUnitHandle( udg_Hash, i, 3, Dummy )
    call SaveUnitHandle( udg_Hash, i, 4, Caster )
    call TimerStart( timerer, 0.01, true, function Trig_LOCAL_TimerR )

    set  Caster   =  null
    set  Dummy    =  null
    set  timerer  =  null
endfunction
Принятый ответ
0
32
6 лет назад
0
В фильтрах незачем обьявлять локалки, для этого есть темповые глобалки.
0
20
6 лет назад
0
quq_CCCP:
В фильтрах незачем обьявлять локалки, для этого есть темповые глобалки.
почему?
0
32
6 лет назад
0
Diaboliko, во первых их нужно еще и обнулять, когда речь идет о хендлах, во вторых внезапно это тоже операция и затрачивается время, потом вспоминаем что фильтры работают постоянно перебирая юнитов и понимаем зачем нужны глобалки...
0
7
6 лет назад
0
ScopteRectuS, Огромное спасибо, никак не мог понять работу с отрядами, то есть с фильтром, оказывается можно было обойтись одним условием. Это всё облегчает. Благодарю за советы.
Extremator:
А я вот вижу проверку на 0.405 хп, вместо проверки мёртвости юнита
Так это же, юнит умирает когда у него хп не ноль, а где-то 0.4. Кончено у меня целостный урон я мог бы и так написать:
GetUnitState(whichUnit, UNIT_STATE_LIFE) <= 0
Но и в этом случаи всё равно работало бы, кроме одного: а если предположим у юнита (мёртвого) 0.3 здоровья, он мёртв, но его выделит в отряд и нанесёт ему ещё урон, но зачем? Он как бы итак мёртв.
quq_CCCP:
В фильтрах незачем объявлять локалки, для этого есть темповые глобалки.
Не думаю, что от глобалок лучше станет, как написал ScopteRectuS, можно обойтись условием, не создавая лишних функций.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.