Нож в спину от варкрафта, или искусство кэширования

Ради того, чтобы иметь возможность отличить урон, нанесенный заклинаниями, от урона с атак, мне пришлось переделать все стандартные заклинания в обертки. Это они же, только кастует их уже дамми, а не настоящий герой. Источник урона другой, поэтому можно точно сказать, было это заклинанием или сам герой ударил.

Всё прошло хорошо — вери изи триггеры, никакой высшей математики, на каждую стандартную волну (лина магнус баньша ) — фейковая для каста, настоящая у дамми. Оно работало без проблем, даммик в точности повторял приказ и осечек быть не могло. Я знал про теоретическую возможность даммика не суметь бросить волну, если игрок отдал приказ бросить волну в самого себя, но на практике этот кейс тоже был учтен и не представлял большого интереса — часто ли щелкают на своего героя?

Пару репортов с нерабочими волнами я списал именно на тот случай, когда даммик по каким-то причинам не сумел бросить заклинание. Подумал, что бросок пошел на скалы. Смотреть не посчитал нужным — были и более заметные баги, и более частые. И только когда карта вышла на ргц, я понял, что это серьезная проблема, и что мало репортов не значит «редкий». Кроме того, ульта SF тоже использовала фейковые волны, и они тоже иногда не работали.

Селфи драколича, по мнению игроков за СФа или лину

В статье описано, как был диагностирован баг и что он из себя представляет.


Зачин
Количество репортов с нерабочими волнами росло как на дрожжах. ВТФ? Практически в каждой 3ей игре была  лина или  магнус (забавно, что баньшу никто не пикал), у которых не работали волны. Просто катастрофа. Притом в одиночной игре не воспроизводится вообще никак — куда ни кликай, система найдет способ бросить волну. В предоставленных реплеях же волны не работали даже по ровной поверхности.

В поисках Баго
Келлер нашел зависимость, отметив, что во всех играх со сломанными волнами присутствовал  гоблин текис. "Этот мелкий пидор решил заруинить и мою катку", сразу подумалось мне. Уж сколько он игр подпортил, но чтобы так жестко? Причем интересно:
  •  текис должен появиться на карте ДО того, как кто-либо применит волну;
  • если кто-то применил волну,  текис уже никак не влияет на дальнейшую игру — всё работает как надо.

Течисы успешно подорвали пукан

Интересно, что даммик, который должен был имитировать каст волны, прямо говорил, что не может использовать способность. Варкрафт не дает ответа, почему — он лишь информирует, получилось ли сделать каст или нет. У даммика это упорно не получалось. Я даже снял с даммика Locust, чтобы собственноручно проверить — и внезапно, я мог легко бросить волну в любую точку. Т.е. у меня в руках тот же даммик, который только что отказывался дать каст в точку — и теперь легко даёт его под моим руководством.

Более того — даммик МОГ бросить абилку. Добавив, в отчаянии, условие "если у тебя не получилось бросить абилку с 20 попыток, брось её в самого себя". Я полагал, что, если проблема в обработке проходимости, бросить на себя можно всегда — даже с непроходимой точки. Внезапно — даммик бросил волну. И бросал исправно, независимо от состояния текиса. Это было крайне необычно. Но поехали дальше, решать проблему.

Методом тыка определил сегмент кода  течиса, отключение которого лечило проблему с волнами. Это была часть, связанная с суицидом. Как известно, с появлением Wraith State от аганима  Leoric пришлось найти возможность отключить суицид-способности на время действия «призрачной формы». Это реализуется очень просто — у всех игроков есть скрытый юнит, необходимый для применения абилки. Грубо говоря, тот же принцип, что существует во многих TD — "требования: хх уровень". При необходимости юнита убивают или оживляют, чтобы разрешить или запретить использование абилки. Но вернемся к проблеме.

Удивительное — рядом
Выяснилось, что волны начинают ломаться только при входе на карту юнита  e00K, которого методом тыка я выбрал на роль переключателя доступности суицида. Это старый дух эзалора, который могут помнить олдскулы.

Как какой-то юнит может помешать никак с ним не связанным юнитам? Пошли проверять зависимости — в коде ни единого упоминания. Появиться на карте как-то еще дух не может, т.е. проблема может возникнуть только при пике  текиса. Использование других айдишников решает проблему, но мне нужно было докопаться до сути.

Да простят мне роемы использование данной картинки

Что привносит с собой на карту юнит? Свои способности. Пошел в UnitAbilities и удалил всю строку абилок у e00K. Там были старые скилы виспа. Внезапно — это решило проблему. И снова непонятно — как одна абилка может мешать другим юнитам работать с другой абилкой? Методом исключения выяснил, что проблемная абилка — это A10V, Blinding light. Её структура по SLK:

C;X2;K"ANcl"
C;X10;K1
C;X11;K1
C;X19;K20
C;X20;K50
C;X22;K500
C;X25;K1
C;X28;K"carrionswarm"


Вообще ничего необычного. Типичная абилка на Channel, мгновенная (X24=0), видимая (X25=1), приказ — carrionswarm. Приказ и оказался единственным, за что тут можно было зацепиться. Ведь точно такой же приказ используется у стандартных волн.

Добавление этой абилки любому юниту на карте в любое время делало даммиков беспомощными — они не могли бросить волну, о чем отчаянно сингализировали в IssuePointOrder, возвращая false. При этом, если любая стандартная волна была использована до вхождения A10V на карту, всё работало корректно, и сама A10V работала как надо.

Отсюда можно сделать лишь один вывод. Варкрафт любит кэшировать юнитов, а значит, скорее всего, как-то кэширует и мета-данные способностей. И в случае ANcl близзарды допустили какую-то ошибку, по вине которой приказ "carrionswarm" вносился в кэш по данным этой абилки, а не на основе реального Carrion Swarm. Т.к. способность A10V применялась мгновенно, без прицела, вызов IssuePointOrder приводил к проблеме вида "я не могу использовать мгновенную абилку на точку". Взяв эту теорию за основу, я… ничего не сделал. А что тут сделать? Без открытых исходников пытаться что-то проанализировать в варкрафте невозможно.



Всем выйти из сумрака!
Окей, абилки кэшируются. Значит, нужно обезопасить не только течиса, но и всех, кто использовал такой приказ. Мало ли, войдет такой кадр на карту и испортит? Поиск показал несколько совпадений:
  • еще 2 абилки от старых виспов эзалора;
  • одна старая неиспользуемая абилка для Shadowraze;
  • ульт Storm Panda.

Сперва я удивился —  Storm ведь частый гость в играх, как и  SF, и обычно  Storm быстрее берет ульт, чем  SF. Как он не запорол ульту сфу? Пошел проверять и вспомнил — я ведь менял  шторма. Поэтому у фрога воспроизвести проблему в реальной игре невозможно.

Сноска: фрог использует стандартый Carrion Swarm в качестве основы для ульты  Storm. Технически — это одни минусы. Его шторм не может делать микро-прыжки — только на 100+, нельзя нажать на себя (под себя), т.к. клик все равно заденет модель героя и приказ не пройдет — «нельзя указывать самого себя». Его шторм не может залезать на скалы по той же причине — абилка не используется на скалах. Чтобы сделать из шторма нормального героя, я сменил базовое заклинание, сохранив приказ.

Теперь можно вспомнить, что даммик успешно кастовал способность на самого себя. Почему?

Когда я проверял работоспособность  Lotus Orb, который должен был отражать все заклинания, у которых есть SpellTargetUnit, было обнаружено, что у мгновенных абилок, по мнению движка, на самом деле есть цель — сам юнит. Т.е. веер ножей имеет цель = кастер, все Channel, у которых мгновенная активация, тоже имеют цель = кастер. Поэтому, даже несмотря на потенциальный конфликт IssueTargetOrder и IssueImmediateOrder, оба приказа успешно могут выполниться даммиком на одной и той же абилке.

im not even mad

Выводы
Итак, что из всего этого было вынесено:
  • не стоит выбирать дамми-юнитов наобум, а если и делать — то стирать все способности, которые не будут использоваться. Хотя это такое себе предохранение;
  • варкрафт использует кэширование для работы с функциями вроде Issue*Order;
  • в функции, определяющей, стоит ли закешировать результаты работы с данной способностью, допущена какая-то ошибка.

Продолжаем копать
Проблема устранена, все carrionswarm-channel получили другие приказы. Но только ли в них проблема? Я продолжил расследование.

Первым делом добавил абилке A10V не мгновенный тип применения, а как у волны — "земля или юнит". Приказ старый — "carrionswarm". Результат:
  • IssuePointOrder возвращает true (приказ успешно выполнен);
  • волна не вылетает.

what?

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

Поехали дальше. Возвращаем тип применеиня "мгновенно", ставим приказ… ну пусть bloodlust. У нас есть  Rabid и  Bloodlust огра при помощи мультикаста, где bloodlust кидается даммиками. Если мы правы, ANcl сломает их и никто больше не вырастет. Тестим:
  • даммики успешно кидают Bloodlust на цели.

Таким образом, IssueTargetOrder НЕ ломается из-за кэширования, либо функция кэширования игнорирует ANcl.

Проверяем эту теорию: ставим приказ rainoffire, который используется через IssuePointOrder на  Pit Lord. Результат:
  • даммик НЕ начал применять огненный дождь;
  • приказ вернул false.

Теория почти подтверждена. Фо фан хотелось проверить приказ "move", но он явно подгружается в карту с первым же юнитом, если не раньше, поэтому спуфинг ничего не дал — всё работало корректно.

Ради интереса
Еще одна проверка. Приказ = dreadlordinferno. Он используется даммиком, который сбрасывает второго голема с ульты  варлока. Результат был ожидаем:
  • возвращено false;
  • второго голема нет.

Меняем цели A10V на "unit only" (X24=1), результат тот же. Ставим цели "ground only" (X24=2) — ура, голем падает, возвращается true. Т.е. еще и не все цели одинаково полезны? При X24=3 (ground or unit) голем, опять же, падает. Т.е. только ANcl с X24=0 проходят кэширование?

Пробуем X24=3 на rainoffire — дождь успешно стартует. На X24=2 картина та же.

Итак, ANcl с типом применения "no target" (0) или "unit only" (1) может запороть работу даммиков, которые используют способности с таким же приказом.

так и задумано

Домашнее задание
Полагаю, что для IssueTargetOrder картина тоже может измениться. если экспериментировать с типом прицела на ANcl, но желания продолжать эти эксперименты уже нет.

Заключение
Пока что я просто стер приказы из проблемных абилок (что перевело их на приказ channel по умолчанию), на случай, если каким-то чудом они даже появятся на карте.

Вот так я наткнулся на неизвестный (по крайней мере мне — точно) конфликт внутренних систем варкрафта. Теперь я знаю, что за баг терроризировал LoD всё это время, не позволяя использовать  Midnight Pulse и  March of the Machines, которых тоже кастуют даммики, причем приказы есть на ANcl-способностях.

Надеюсь, было интересно.

10 комментариев

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.