Написал простенькую систему разброса урона, чисто jass без диалектов и мемхака.
Собственно, вопрос в том, оптимально ли это или есть какие-то неочевидные минусы, способные как-то навредить?
//attack -> add damage event -> function


function damaging takes nothing returns nothing
    local integer i = 0
    local integer h = GetHandleId(GetExpiredTimer())
    local unit damager = LoadUnitHandle(udg_data, h, 0)
    local unit damaged = LoadUnitHandle(udg_data, h, 1)
    local real radius = GetRandomReal(udg_minradius, udg_maxradius) 
    local location tmp = PolarProjectionBJ(GetUnitLoc(damaged), radius, GetRandomReal(0, 360))      
    local unit u = CreateUnit(GetOwningPlayer(damager), 'h000', GetLocationX(tmp), GetLocationY(tmp), 0 )  
    call SetUnitInvulnerable( damaged, false )
    call DestroyEffect(AddSpecialEffectLoc( udg_effect_name, tmp ))
    call UnitDamagePointLoc( u, 0, udg_damage_radius, tmp, udg_damage, ATTACK_TYPE_PIERCE, DAMAGE_TYPE_NORMAL ) 
    call RemoveUnit(u)
    set u = null
endfunction

function get_damage takes nothing returns nothing
    local timer t = CreateTimer()
    local integer h = GetHandleId(GetTriggeringTrigger())
    local unit damager = LoadUnitHandle(udg_data, h, 0)
    local unit damaged = LoadUnitHandle(udg_data, h, 1)
    local integer h = GetHandleId(t)                                     
    call SaveUnitHandle(udg_data, h, 0, damager)
    call SaveUnitHandle(udg_data, h, 1, damaged)
    call SetUnitInvulnerable( GetTriggerUnit(), true )
    call TimerStart(t, 0.0, false, function damaging)
    call DestroyTrigger(GetTriggeringTrigger())
endfunction

function Trig_attacking_Conditions takes nothing returns boolean
    return GetUnitTypeId(GetAttacker()) == 'hrif'
endfunction

function Trig_attacking_Actions takes nothing returns nothing
    local trigger t = CreateTrigger()
    local integer h = GetHandleId(t)
    call TriggerRegisterUnitEvent( t, GetTriggerUnit(), EVENT_UNIT_DAMAGED )            
    call TriggerAddAction(t, function get_damage)
    call SaveUnitHandle(udg_data, h, 0, GetAttacker())
    call SaveUnitHandle(udg_data, h, 1, GetTriggerUnit())
endfunction

function InitTrig_attacking takes nothing returns nothing
    set gg_trg_attacking = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_attacking, EVENT_PLAYER_UNIT_ATTACKED )
    call TriggerAddCondition( gg_trg_attacking, Condition( function Trig_attacking_Conditions ) )
    call TriggerAddAction( gg_trg_attacking, function Trig_attacking_Actions )
endfunction

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

Нет, не оптимально, юзаешь точки вместо координат и даже не обнуляешь их, переменные юнитов тоже не обнулил, таймеры не обнуляешь, да и локальные триггеры тоже в null можно

local location tmp = PolarProjectionBJ(GetUnitLoc(damaged), radius, GetRandomReal(0, 360)) 
-->
local real x = GetUnitX(damaged)+radius*Cos(GetRandomReal(0,360)*bj_DEGTORAD))
local real y = GetUnitY(damaged)+radius*Sin(GetRandomReal(0,360)*bj_DEGTORAD))
local unit u = CreateUnit(GetOwningPlayer(damager), 'h000',x, y, 0 ) 
Координаты обнулять не нужно

call UnitDamagePointLoc( u, 0, udg_damage_radius, tmp, udg_damage, ATTACK_TYPE_PIERCE, DAMAGE_TYPE_NORMAL )
Функция дамажит всех без исключения если не ошибаюсь, лучше самим юнитом через цикл/группу дамажить юнитов

Ой посмотрел на это всё, вообще желательно всё переписать, зачем сохранять что-то в хэш-таблицу если ты уже создал триггер для этого
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
2
28
3 года назад
2
Звучит как создание одного громоздкого триггера...
Что лучше, чем бред с постоянным созданием и удалением триггеров. Сколько писал на варе, ни разу такой дичи не потребовалось.
1
32
3 года назад
1
map_maiker, проблема в другом - что такая реализация очень хромает и хоть как то еще годится для мили юнитов, для ренжей никак, можно стопя атаку провоцировать создание пачки триггеров, все яды, или другие виды урона от лица героя тоже заставят триггер сработать. Ибо нужно ставить еще событие время вышло (секунды полторы), события - юнит отдал приказ - цель точка, цель обьект, без указания цели, чтобы удалять триггер не дожидаясь урона по цели, но это годится для милишников, ренжам - только собтие время вышло (примерное время за сколько долетит снаряд до цели +- секунда). И все. Есть вариация еще с отрецательным маг уроном, это когда всем на карте вручена пассивка рунных браслетов, если урон выше 0 - он физический или чистый, иначе магический (ну условно, не будем вдаватся в подробности типов урона и атаки).
Ну и естественно компенсировать лечение от отрицательного маг урона, забирать пассивку браслетов и еще раз наносить урон от лица того кто до этого нанес урон, при этом отключив триггеры реагирующие на урон, после вернуть все наместо. Вот такая реализация кроме ресурсоемкости уже почти идеальна и как то заобузить или забаговать её не получится.

С наработкой детекта урона из мемхака у тебя появляется возможность проверять типы урона и прочие параметры в потоке любого триггера, сработавшего на событие - юнит получает урон.

кстати там какраз выше производительность.
0
9
3 года назад
0
Что лучше, чем бред с постоянным созданием и удалением триггеров.
Как я понимаю, правильное удаление триггера не оставляет утечек. Каждый такой триггер живёт непродолжительное время, если добавить соответствующее событие.
Я не особо смотрел на производительность, но четыре сотни стрелков с задержкой между атаками 0.4 тормозили не больше чем любые другие четыре сотни сражающихся юнитов.
Так почему это бред?
события - юнит отдал приказ - цель точка, цель обьект, без указания цели,
А почему это не подойдёт к ренжам? В контексте отслеживания обычной атаки, не способностями.
quq_CCCP:
ренжам - только собтие время вышло (примерное время за сколько долетит снаряд до цели +- секунда)
А зачем +- секунда?
С наработкой детекта урона из мемхака у тебя появляется возможность проверять типы урона и прочие параметры в потоке любого триггера, сработавшего на событие - юнит получает урон.
кстати там какраз выше производительность.
Хм, ясно.
0
32
3 года назад
0
map_maiker, потому что нужно думать, ибо пока летит снаряд, юнит уже завершил атаку и может быть отдан новый приказ, что само собой все сломает.
Зачем секунда, другая - а чтобы исключить возможность промаха. чтобы у снаряда было время долететь и ударить, и если за отведенное время это го не получилось - то значит промах и отключаем и удаляем триггер. Как удалять триггеры правильно можно глянуть в доте айсфрога или в наработках на сайте (код баратрума и урсы кто то выкладывал).
Еще раз - подобные способы очень ограничены и их старается никто не юзать, кроме совсем простых вещей, плодить триггеры для сотен юнитов очень хреновая идея, потому что есть способы куда проще и оптимальнее.
2
28
3 года назад
2
Так почему это бред?
Конкретно это реализация - потому что замах произойдёт, а атака нет, триггер будет создан, после чего атакованный получит урон от другого юнита, и созданный триггер сработает. И как я уже сказал, для данной задачи плодить триггеры не нужно, достаточно одного.
0
27
3 года назад
Отредактирован rsfghd
0
Если я не ошибаюсь, при удалении триггера событие же всё равно остаётся в памяти?

Звучит как создание одного громоздкого триггера...
Мой пример по такому принципу и работает, один триггер с регистрацией для всех юнитов на карте и те, кто входят в её область

Да, я знаю. Дамми-касты и всё такое
Ну вообще даммикаст только касательно дебаффов, всё остальное триггерно)
Да и на примере молний, разноцветную даммикастом фиг сделаешь)

Я же не про утечки. Например, как в гуи прицепить функцию к таймеру?
Что мешает другой триггер создать?)
Тебе в любом случае тут таймер не нужен был и я об этом и говорю, что твою затею спокойно на гуи можно было сделать
2
28
3 года назад
2
Если я не ошибаюсь, при удалении триггера событие же всё равно остаётся в памяти?
Не остаётся.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.