Не могу понять как добавить в функции GroupEnumUnitsInRange фильтр, который добавлял бы в группу только врагов кастера.
Пробовал делать функцию фильтр, которая фильтровала бы юнитов. (возвращает boolean) Для типов юнитов это работает, но как прописать в фильтр враждебность к игроку - понять затрудняюсь. (интерег игрока различается в зависимости от кастующего)
В общем, какими способами можно заставить добавлять в группу юнитов только врага другого юнита?

Обычно в группу собираю всех юнитов, перебирая их вручную через цикл
Вот только фильтры куда быстрее циклов (JASS плохо справляется с циклами), а внутри фильтров можно делать абсолютно все необходимые действия.
Не могу понять как добавить в функции GroupEnumUnitsInRange фильтр, который добавлял бы в группу только врагов кастера.
Ниже пример, когда группа вообще не заполняется, а нужна только для вызова фильтра, чтобы выполнить нужные действия.
globals
    player P
endglobals

function filter takes nothing returns boolean
    if IsUnitEnemy(GetFilterUnit(), P) then
        // твои действия
    endif
    return false
endfunction

function f takes integer i, real x, real, y, real range returns nothing
    set P = Player(i)
    call GroupEnumUnitsInRange(bj_lastCreatedGroup, x, y, range, function filter)
endfunction
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
16
filter и condition - одно и то же, у них свой поток, это да
перебор группы в цикле медленнее, но удобнее и гарантированно локальные. Если события могут привести к срабатыванию этой же группировки во время обработки цикла, локальные переменные останутся нетронутыми, а глобалки могут перезатереться. Например, если мы собирает группу в действии триггера, реагирующего на урон, и наносит каждому юниту в группе урон, получится еще один вызов, который перебьет общие глобалки, и дальше первый проход по группе пойдет не по плану. Нужно четко осознавать, когда какой подход выгоднее.
24
DracoL1ch, настоящий отдельный поток или варовский "последовательный" отдельный поток? Пример с нанесением урона удавалось повторить на практике или это теоретическое рассуждение? Я просто помню, что активно пользовался кодом в фильтрах и кондишнах и как-то этого типа "багов" не возникало.
28
Пример с нанесением урона удавалось повторить на практике или это теоретическое рассуждение?
Я так понял, он имел ввиду такой случай.
В триггере на получение урона юниты выбираются группой и в фильтре им наносится урон, то есть триггер срабатывает ещё раз, глобалки перезаписываются. На практике вар просто вылетит из-за зацикливания события.
32
фильтры на то и фильтры чтобы в них делать проверки на не инициировать события, в том числе нанесение урона. Лич же писал про ForGroup куда передаются глобалками данные, нужно либо иметь глобалки которые нигде более не используются кроме как для ForGoup потоков в таких местах, где не может быть перезаписи из за инициации другого события, к примеру наносить урон в спеллах которые по типу волны силы или стомпа, при этом абики срабатывающие на урон эти глобалки не юзают. Это все к тому - думайте своей головой что и как юзать, учитывайте взаимодействие и зацикливания событий.
16
prog:
Пусть у меня пассивка, которая в ответ на входящий урон наносит урон в ответ по аое, типа пассивки вайпера, но с одним зарядом (чтобы не крашнуться от вечного цикла) и в аое
Встретились два вайпера, №1 получил урон от второго и инициирует ответный урон в аое, в котрое входит №2, я использую глобалки:
function Nanesti_Uron_v_aoe takes nothing returns nothing
call DamageTarget(tt_unit1,GetEnumUnit(),100)//типа 100 урона по юниту в группе
//... здесь сработает триггер на урон и мы придём сюда уже с новой глобалкой
call BJDebugMsg("damage dealt by "+GetUnitName(tt_unit1)+" to "+GetUnitName(GetEnumUnit()))//дважды увидим имя вайпера №2 в первой части, во второй части будет №1, затем №2
//если здесь были любые операции с tt_unit1, они пойдут неверно
endfunction

... set tt_unit1=GetTriggerUnit()//типа вайпер №1
call ForGroup(g,function Nanesti_Uron_v_aoe)//в группу попал №2
Очевидно, если действие одно и обращения к глобалке (после потенциально-вызывающего-такое-же-событие действия) нет, то пофиг на пересечение
Варкрафт строго линеен, "поток" лишь определяет то, есть ли шанс упереться в лимит операций или нет. Новый поток - снова 300к операций, гуляй душа. В цикле по FirstOfGroup, если в группе СУПЕР много юнитов или действий над ними супер много, упереться возможно.
24
DracoL1ch, спасибо за подробный разбор. Значит ничего не поменялось за годы пока я не трогал вар и все потоки как были последовательными, так и остались.
А проблема перезаписи глобалок в такой ситуации должна решаться очень просто - записываем значение глобалки в локалку при срабатывании события и потом в конце обработчика события возвращаем глобалке старое значение. Насколько я знаю, невозможна ситуация, когда вклинившееся событие вернет управление в предыдущий поток не закончив свой обработчик (не считая вейтов).
16
интересный подход, должно сработать, но, как говорится, нахера козе баян? Своя сфера применимости и всё
28
Варкрафт строго линеен
Тогда выходит, что 2 события не могут одновременно произойти ни при каких условиях?
32
PT153, открыл Америку, все строго линейно. Возможно есть исключения в других потоках игры.
Именно по этой причине нужно юзать темповые глобалки с умом а не как это делают гуишники.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.