Не могу понять как добавить в функции 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
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
24
PT153, что-то мне подсказывает, что это синтаксический сахар от кого-то из препроцессоров и в коде туда добавляется Filter() или Condition() на самом деле.
15
PT153, как написал prog, это действительно синтаксический сахар vJass. Вот во что превратилась функция внутри war3map.j файла
Если отключить компиляцию синтаксиса vJass, будет ошибка.
Загруженные файлы
28
Вот во что превратилась функция внутри war3map.j файла
Часто залезал вовнутрь war3map.j и никогда не замечал...
Что же, очень хорошо, теперь будут знать.

Про этот сахар написано в мануале JassHelper? Я вот что-то не помню.
15
Что же, очень хорошо, теперь будут знать.
Вряд ли это можно назвать хорошо. Эта та часть синтаксиса, что приводит к серьезной неразберихе. Подумать только, совершенно неявное приведение.
PT153:
Про этот сахар написано в мануале JassHelper? Я вот что-то не помню.
Да, написано. В самом низу, в ченжлоге
0.A.0.0
  • . or this. are not required anymore to use members. Note that this may cause issues if for some (incredibly weird) reason you try to use global variables from a method of a struct that has variables of the same name. To disable this feature, you can add [noimplicitthis] to jasshelper.conf.
  • Improved the syntax error when you place a function inside a struct.
  • Code values might get implicitly casted to boolexpr in some occasions, specifically, when using them as arguments for natives/bjfunc that take boolexpr. More cases will get added when type safety gets on its way for more stuff...
Я не включил этот момент в перевод, о чем в итоге сам напрочь забыл.Все таки стоило.
28
Да, написано. В самом низу, в ченжлоге
Было бы неплохо вытащить это из чейнжлога в отдел Jass Syntax extensions.
И это никак нельзя отключить, печально. :(
Вряд ли это можно назвать хорошо. Эта та часть синтаксиса, что приводит к серьезной неразберихе. Подумать только, совершенно неявное приведение.
Хорошо, что теперь я и многие другие знают о таком сахаре.

Вообще, JassHelper любит кое-что менять не уведомляя.
Вот например, я забыл поставить равно.
globals
    boolean B true
endglobals
JassHelper превратит это в
globals
    boolean B
endglobals
То есть B будет без значения, и когда я буду его использовать, ожидая там изначальное значение, поток прервётся.
Хорошо, что последний pjass может такие случаи вывести на поверхность.
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, если в группе СУПЕР много юнитов или действий над ними супер много, упереться возможно.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.