Написал простенькую систему разброса урона, чисто 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 )
Функция дамажит всех без исключения если не ошибаюсь, лучше самим юнитом через цикл/группу дамажить юнитов

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

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
0
9
3 года назад
0
makkad:
map_maiker, Filter() - в твоём случае позволит подставить вместо функции, которая должна возвратить boolean, подставить функцию, которая возвращает nothing
Хм, любопытно.

rsfghd:
map_maiker, лол, как ты вообще работаешь с кодом в обычном редакторе?
Многое теряешь без джнгп, и скорее всего, мою версию не заценишь
jasscraft есть. Так-то, я раньше особо не писал на jass, недавно вот решил что гуи сковывает. Изначально я хотел на гуи написать эту систему, но вышла хрень. Неработающая как надо, что важно.
На счёт твоей версии - мб и заценю...
0
27
3 года назад
Отредактирован rsfghd
0
Ну в таком случае вот
раскрыть
Я не говорю, что это идеально, но чутка получше чем у тебя
library mylib initializer init
private group TempG = CreateGroup()
private trigger trg1 = CreateTrigger()

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

private function enemy takes nothing returns boolean
    set bj_lastReplacedUnit = GetFilterUnit()
    return not IsUnitDead(bj_lastReplacedUnit) and IsUnitEnemy(bj_lastReplacedUnit,GetOwningPlayer(bj_lastCreatedUnit))
endfunction

private function damage takes nothing returns nothing
    call UnitDamageTarget(bj_lastCreatedUnit,GetEnumUnit(),udg_damage,false,false,ATTACK_TYPE_PIERCE,DAMAGE_TYPE_NORMAL,null)
endfunction

private function damage1 takes nothing returns nothing
    local unit attacker = GetEventDamageSource()
    local unit damaged = GetTriggerUnit()
    local real rad = GetRandomReal(udg_minradius,udg_maxradius)
    local real a = GetRandomReal(0,360)*bj_DEGTORAD
    local real x = GetUnitX(damaged)+rad*Cos(a)
    local real y = GetUnitY(damaged)+rad*Sin(a)
    local boolexpr b = Condition(function enemy)
    
    call KillUnit(CreateUnit(Player(15),'u000',x,y,0))
    set bj_lastCreatedUnit = attacker
    call GroupEnumUnitsInRange(TempG,x,y,udg_damage_radius,b)
    call DisableTrigger(trg1)
    call ForGroup(TempG,function damage)
    call EnableTrigger(trg1)
    call GroupClear(TempG)
    set bj_lastCreatedUnit = null
    
    set attacker = null
    set damaged = null
    set b = null
endfunction

//===========================================================================
private function myfunc takes nothing returns nothing
    call TriggerRegisterUnitEvent(trg1,GetEnumUnit(),EVENT_UNIT_DAMAGED)
endfunction
private function Trig_d1_Actions takes nothing returns nothing
    call TriggerRegisterUnitEvent(trg1,GetTriggerUnit(),EVENT_UNIT_DAMAGED)
endfunction
//===========================================================================
private function mycond1 takes nothing returns boolean
    return GetUnitTypeId(GetTriggerUnit()) != 'u000'
endfunction
private function mycond takes nothing returns boolean
    return GetEventDamage() > 0. and GetUnitTypeId(GetEventDamageSource()) == 'hrif'
endfunction
private function init takes nothing returns nothing
    set gg_trg_d1 = CreateTrigger(  )
    call GroupEnumUnitsInRect(TempG,bj_mapInitialPlayableArea,null)
    call ForGroup(TempG,function myfunc)
    call GroupClear(TempG)
    call TriggerRegisterEnterRectSimple( gg_trg_d1, bj_mapInitialPlayableArea )
    call TriggerAddCondition(gg_trg_d1,Condition(function mycond1))
    call TriggerAddAction( gg_trg_d1, function Trig_d1_Actions )
    call TriggerAddCondition(trg1,Condition(function mycond))
    call TriggerAddAction(trg1,function damage1)
endfunction
endlibrary

Кстати, ты можешь делать намного интереснее вещи с триггерной атакой, вплоть до кривой цепной молнии скакающей по юнитам накладывающая дебаффы с отталкиванием и всей ерундой что только можешь придумать

Так-то, я раньше особо не писал на jass, недавно вот решил что гуи сковывает.
Чистый гуи да, но у тебя есть кастом скрипт, где можно обнулить точки и это всё, что в принципе нужно, чтобы эта система работала без утечек
Загруженные файлы
2
28
3 года назад
Отредактирован PT153
2
makkad:
Могу сказать, что TriggerAddAction вызывает утечку памяти, если отдельно его не сохранять и позже удалять. Лучше через TriggerAddCondition вызывать действия триггера.
А в чём разница? Это всё одно и тоже.

А по теме - динамическое создание триггеров тут не нужно.

Filter() - в твоём случае позволит подставить вместо функции, которая должна возвратить boolean, подставить функцию, которая возвращает nothing
Фильтр берёт коде, и возвращает фильтр, что подтип булеэкспры. А TriggerAddCondition принимает только булекспры.
0
22
3 года назад
Отредактирован makkad
0
PT153, Разница в утечке памяти. Вот тестовая карта. А удалять - это больше строчек на код тратить, конкретно в этом случае. Если sleep не нужен.
Загруженные файлы
0
28
3 года назад
Отредактирован PT153
0
makkad, убедил. TriggerClearActions и ResetTrigger не нужно, это ничего не удаляет.
0
22
3 года назад
0
PT153:
makkad, убедил. TriggerClearActions и ResetTrigger не нужно, это ничего не удаляет.
Да. И это тоже проверялось.
1
16
3 года назад
1
AddAction создает уникальный объект при каждом обращении, а AddCondition кэширует объекты. поэтому в динамических триггерах, где всё создается и разрушается множество раз за игру, нужно использовать именно Condition
Filter() и Condition() одно и то же
3
32
3 года назад
Отредактирован quq_CCCP
3
Детект урона что ты описал, уже есть на сайте и готовый, широко юзается в доте фрога - и это вызывает баги, не столь критичные но тем не менее, ибо замахиваясь ты провоцирует событие триггера, который создаёт еше 1 триггер, который ждёт любого урона по цели, что неправильно, во первых время существования триггера нужно, вдруг промах, так же событие смерти, если жертва умерла - то закругляемся.
Про кондишены правильно написал лич, ибо триггер акшин это объект, который сам по себе не удаляется.
0
9
3 года назад
0
Кстати, ты можешь делать намного интереснее вещи с триггерной атакой, вплоть до кривой цепной молнии скакающей по юнитам накладывающая дебаффы с отталкиванием и всей ерундой что только можешь придумать
Да, я знаю. Дамми-касты и всё такое. rsfghd:
Чистый гуи да, но у тебя есть кастом скрипт, где можно обнулить точки и это всё, что в принципе нужно, чтобы эта система работала без утечек
Я же не про утечки. Например, как в гуи прицепить функцию к таймеру?
PT153:
А по теме - динамическое создание триггеров тут не нужно.
А можно подробнее?
quq_CCCP:
во первых время существования триггера нужно, вдруг промах,
Да, в случае промаха урон просто откладывается. Но я не придумал как можно прицепить удаление триггера по времени. Самый правильный вариант - добавить событие в триггер, но... В общем, как это сделать чтобы работало - я не придумал.
0
28
3 года назад
0
map_maiker, юнит входит на карту, на него и добавляем событие на получение урона. Всё. А все эти костыли с событием на атаку бред. Тем более, что это замах, а не сама атака. И на каждый замах по новому триггеру - бред.
0
32
3 года назад
0
map_maiker, с мемхаком куда веселее, просто смотришь тип урона и атаки.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.