Написал простенькую систему разброса урона, чисто 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
27
3 года назад
0
Сейчас попробую реализовать твою задумку, если никто не преуспеет)
0
9
3 года назад
0
Не нужно значения передавать, у тебя триггер реагирует на дамаг по этому юниту, ты уже можешь получить нужные тебе переменные с самого триггера
Хм, логично. Как-то не подумал.
rsfghd:
Как ты вообще сохранил карту без ошибок, если у тебя пересоздание переменной идёт?
Забавно. Ну как-то так получилось. Мб вар не считает это ошибкой?
makkad:
local code c=function Trig_attacking_Actions
call TriggerAddCondition( gg_trg_attacking, Filter(c) )
Хм, а что Filter делает?

закинул счётчик хэндлов, можешь посмотреть что происходит
Вылет в главное меню...
0
27
3 года назад
0
map_maiker, сохрани карту перед запуском

И возможно стоит проверить эти галочки, раз уж вар не выдал ошибку с пересозданием переменной
Загруженные файлы
0
9
3 года назад
0
map_maiker, сохрани карту перед запуском
У меня обычный редактор, если это имеет значение. Как-то не дошли пока руки поставить jngp.
0
22
3 года назад
0
map_maiker, Filter() - в твоём случае позволит подставить вместо функции, которая должна возвратить boolean, подставить функцию, которая возвращает nothing
0
27
3 года назад
0
map_maiker, лол, как ты вообще работаешь с кодом в обычном редакторе?
Многое теряешь без джнгп, и скорее всего, мою версию не заценишь
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 не нужно, это ничего не удаляет.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.