99 маленьких багов

Любая разработка — это длинная тропа, конец которой никогда не видно, где на каждом шагу лежат грабли. Особенность этих граблей в том, что у каждой отдельно взятой штуки уникальная рукоятка, стильный набалдашник и неповторимая форма самих шипов. Какие-то из них нормальной длины, какие-то короче, какие-то длиннее, и каждые бьют в свою точку, лишь изредка повторяясь.

Переходя ближе к проекту Allstars, нужно принять во внимание 3 фактора:
  1. Это готовый чужой движок. Его поведение, конечно, в обычных сценариях очень даже предсказуемо. Это не Source, где движок даже числа округляет с ошибкой, превращая 59 в 50, а 120 в 117. Но особенность любой карты WC3 в том, что она играет на нестандартных способностях и фичах, которые и привлекают людей. А на крайностях движок ведет себя своенравно.
  2. Это готовая оригинальная карта. 100 тысяч строк кода, более 500 юнитов и 3 тысячи способности. Почему конкретно так была реализована та или иная фича? Это обход какого-то бага или криворукость? Почему использована та способность, а не иная? Вопросов тысячи, а в скайпе фрог, как назло, не отвечает.
  3. Это попытка соответствовать высоким стандартам DotA2. Не то что бы фрог был гением гейм-дизайна, но нельзя отрицать, что после откровенно экспериментальных 82 и 83 дота вернулась на старые рельсы. Да, игра в догонялки с врагом в плане наград за убийства осталась, но она влияет намного слабее, чем прежде. Дота2 сегодня — это то, во что хотят играть дотеры, и графики онлайна, да и личный опыт, подтверждают это. Отсюда — далекие планы, высокие цели и вечные удары макушкой о лимиты чего-либо в варкрафте. В погоне за соответствием начинаются игры на крайностях движка, поэтому см. пункт 1.

Итак, о чем здесь будет:
  1. Откуда и как берутся баги у меня и фрога;
  2. Какие баги/фичи решены в ближайшее время точно не будут (или будут) и почему;
  3. Какие еще баги предстоит увидеть.

Отказ от ответственности: автор не несет ответственности за изувеченную психику или безумный смех читателя. Любые примеры алгоритмов даны не с математической точностью, а так, чтобы донести суть конкретного примера. Те, кто знает JASS код, и без деталей понимают, как повторить, и не нужно пугать тех, кто не знает.

Изобретение бага

Придумать баг крайне просто — для этого нужно просто идти вперед и что-то менять. Народная мудрость гласит: если работает, не трогай. Мудрость программистов пошла дальше — если работает, не трогай и не пытайся выяснить, как именно оно работает, а то захочется рефакторинг.

Фрог придерживается этого принципа до конца. До сих пор в некоторых местах используется слегка модифицированный код из 90х, а точнее — из тех версий, когда деревья были зелеными, а дота была в руках ребят, которые кодить умели только мышкой.  Pudge,  Potm, система пика героев, старые моды — всё это работает максимально неэффективно, тяжело и местами грубо. Тем не менее, оно работает, поэтому править ничего не нужно.

В коде можно найти ряд функций, которые друг друга дублируют. Это следствие наследования, передачи доты из одних рук в другие. Вместо того, чтобы гадать, как предыдущие разработчики назвали ту или иную функцию, пишется своя, которая делает то же самое. В некоторых случаях в нужной функции имеется «фатальный недостаток», который, разумеется, устраняется путём ctrl+c ctrl+v, а не вынесением основного года в другую функцию.

Из 100 тысяч строк около 60 занимает код способностей героев, еще 30 уходит под все остальные интерактивные системы — предметы, моды, нейтралы и т.п. И еще десятка — это определение баз данных и вспомогательных функций, на основе которых работает часть навыков. Большинство этих строк можно упростить, оптимизировать или вовсе удалить за неактуальностью. В коде до сих пор оставались функции от старых (и новых, но не вошедших в релиз) способностей, проверки на несуществующих юнитов и многое другое. Мелочь, но тратить время одного-единственного CPU на такое — верх расточительства.

Естественно, никто в этот массив данных никогда не лезет и пишет там, где придется. Никаких систем для стака тех или иных эффектов не предусмотрено. Например, триггерное движение. Если героя посадил на цепь  Pudge, и его же начал тянуть к себе  Earth Spirit, к кому он должен в итоге приехать? Аналогичные вопросы можно задать к любой комбинации передвижений. Но даже сама система передвижения в оригинале выглядит весьма страшно, и новички едва ли могут модифицировать её. Можно просто отметить, что любое передвижение использует собственный триггер для этого, проще говоря — нет единого универсального движка для поездок, каждая работает на своём. Отсюда — огромный объем скопированного кода и максимум боли при попытке совместить хотя бы пару из функций друг с другом. Так и ездят, перебивая друг друга как повезет (pun).

Итак, как можно навредить уже работающим системам?

Фрог
В одной из версий копье  PL внезапно начало начислять убийство не игроку за фантома, а самой цели, т.е. суицид. Казалось бы, с чего? В ченжлоге той версии не было ни одного изменения касательно этого героя, и на тебе. Как позже выяснилось, по какой-то причине сменили источник урона (хозяин даммику, который бросает копье, назначался от цели, а не от кастера). Фрог держал лицо кирпичом около месяца, прежде чем выпустил апдейт. Как сломал? Зачем?



Лич
В моих релизах тоже было предостаточно глупых и, казалось бы, нереальных ошибок. Самая запоминающаяся, потому что висела дольше прочего — это баг с астралом в 83d. По сути, я отходил от проекта и был занят реальной жизнью, а ошибка висела на главной странице сайта. Всё началось с того, что я пытался сделать Ethereal с  Ghost Scepter стакающимся. В картах фрога он работает максимально просто:
  • Создать таймер на 4 секунды;
  • Когда таймер тикнет, снять способность, дающую форму.

Хорошо видно, что если включить новый Scepter на 3й секунде предыдущего, то форма снимется, потому что тикнет первый таймер. Вместо этого я пытался перевести триггер на новые рельсы, делая таймер отзывчивым, заставляя его регулярно проверять, сколько от формы осталось, обновляя счетчик при новом касте. Проблема в том, что при тестах я сделал длительность бесконечной, отключив код удаления. А потом меня отвлекли очередной пачкой фиксов и апдейтов. В результате строчки забылись, а т.к. оригинальная проблема не была решена, в ченжлог ничего не попало, и проверить совершенно неизмененный артефакт никто не удосужился.



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

Отсюда очевидная технология создания Butterfly, который можно включать, теряя уклонение: выдача уклонения через эту систему, снятие нужного числа при включении артефакта, возвращение через время. Но мы пошли другим путём, оставив на артефакте уклонение, и создав его дублера, который уклонений лишен. С одной стороны, на нём написано, что этот конкретный Butterfly уклонения не дает, но я не скажу, что эта морока стоит такого извращения. Чуть позже выяснилось, что еще и замена артефакта на другой сделана не по канону, и, в случае смерти, не заменяет артефакт и отключается. Поэтому владелец будет всю оставшуюся игру бегать с выключенным артефактом, который еще и выбросить нельзя.

Бонусом — отсутствие толковой проверки на то, может ли юнит вообще сейчас взять предмет, от чего и произошел баг с  Arc Warden. Мертвой копии пытались выдать артефакт, который она тут же бросала на землю (или вообще не брала, как посмотреть).


Лич
Издавна известно, что в ледышках  Tuskarr можно застрять. Это препятствия размером 64х64, тогда как большинство героев от 16 и меньше в диаметре. Если такая упадет на голову, можно зависнуть с нею в обнимку на 5-7 секунд, в зависимости от версии. Как исправить дело? Правильно, выталкивать всех, кто оказался под ледышкой, внутрь. Для этого я просто брал всех юнитов вокруг и проверял их координаты. Но, после тестов, снова забыл добавить фильтры для юнитов. Поэтому и появились вышки, которые шли в атаку, и просто безумный ИИ, заставлявший деревья идти в атаку.



Фрог
Безумный Lycan — следствие крайне малого внимания, уделенного технической стороне WC3. Большинство серьезных картоделов знают, что морфить юнитов небезопасно по многим причинам, особенно метаморфозой. Но фрог — не серьезный картодел примерно с 2010 года, поэтому взятки гладки. Несмотря на относительно сложные условия, бесконтрольный  Lycan — слишком частое явление, о чем наглядно говорит количество репортов. Боже, да мне до сих пор с RGC пишут люди, которые играют на моей же 83d, чтобы я пофиксил ликана.



Лич
Счетчик нейтралов  Chen фиксился около трех раз. Каждый раз проблема была своя.

Первый фикс: алгоритмическая ошибка при подсчете древних и обычных нейтралов. Но, вместо кода доты, был по ошибке исправлен код LoD. Мой первый фикс, который баг.

Второй фикс: юниты получили бонус к хп до конкретного уровня, а не просто статичный бонус. Фильтры подсчета искали крипов именно с этими статическими абилками, поэтому не находили и говорили, что количество равно нулю.

Третий фикс: когда с переманенных юнитов сняли Phased-форму, т.е. сквозь них больше нельзя просто взять и пройти. Никто и не вспомнит, зачем вообще нужно было вводить этот бред, но, скорее всего, чтобы не блочили союзников. В Dota2 фрог решил, что эта механика не нужна, и убрал её, а в оригинале не удосужился. Когда я снял абилку формы, счетчик сломался снова. Опять же, это оказалась одна из абилок, которую ищет фильтр. Матерь божья, этот фильтр из 90-х был настоящей занозой.



Фрог
Ульт  Disruptor в одной из версий научился блокировать использование предметов. Проблема в том, что хардкорно такой возможности нет. Если рюкзак нельзя использовать, то нельзя применить и пассивные способности артефактов в нём. Гляньте на рошана — у парня в рюкзаке аегис, а он не возрождается. Именно потому, что он не может использовать содержимое рюкзака. Сперва я использовал именно эту технологию (еще в LoD), а позже улучшил в другую систему мута предметов.

Что сделал фрог? Накладывает коротенький Doom на все цели в пределах круга ульты. В принципе, цель достигнута — предметы активировать точно нельзя, а аегис, в случае чего, сработает. Но есть парочка огромных нюансов:
  1. Doom блокирует несколько популярных пассивных способностей, включая уклонение, крит, баш, блок урона и пару других. Поэтому Disruptor в версии фрога — настоящая машина по убийству героев, полагающихся на эти способности.
  2. Doom не складывается, поэтому другой  Doom не сможет ультануть на цели в круге, пока псевдо-дум не закончится. Мелочь, а неприятно.



Лич
Один  Meepo — хорошо, а 194872348923797589274 мипо — еще лучше! Когда Мипарик получил абилку для демонстрации доп. резиста, я скрыл иконку плюсика от статов. Проблема в том, что это замена одного навыка (который видно) на другой (который не видно). А мипо сделан так, что создание клона просто «переводит» конкретный список скиллов от главного мипо новому клону. В этом списке был только оригинальный плюсик, а не скрытый. Оттуда и появилась возможность на новых клонах брать какие-либо другие навыки, изучая всё, включая ульту, независимо друг от друга.



Второй раз проблема всплыла намного позже. Переделанные для поддержки  алхимика аганимы не раздавались клонам, поэтому ID их ульты отличался от ID оригинального мипо. В результате — после приобретения аганима новые клоны не прокачивали ульт автоматически, что вело к возможности размножить каждого мипо несколько раз.



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


Дорожная карта, или roadmap

У людей в костюмах используется понятия диздок — дизайн документа, в котором описывается всё и вся, что из себя должен представлять проект, до последней мелочи. У людей помельче, которые не страдают от тяжести лейбла «КОРПОРАЦИЯ», используются roadmap — дорожные карты действий. На них примерно отмечено, к чему ведет дорога, и какие цели вдоль этой дороги можно выполнить.

Здесь же я задержусь на вещах, которые часто спрашивают, но до сих пор они не сделаны.

Псевдо полная невидимость
Когда впервые была введена абсолютная псевдоневидимость в виде смоков, было немного страшно. Но когда это вышло на уровень игры и стало частью  Slark, стало реально боязно.

По сути, Blizzard оставляли возможность «видеть» либо невидимых, либо закопанных, либо и тех, и других. Но на практике между этими инвизами не оказалось никакой разницы в плане подсветки — одинаково хорошо видно всех. Поэтому реальной невидимости добиться невозможно. В случае сларка — она короткая, поэтому даже простая отмена атаки по нему сработает. В случае смоков — сложнее. Забежать под вражеский фонтан и тусоваться там нельзя — трусайт не дремлет. В лучшем случае можно останавливать атаки пушек и фонтана, и, пожалуй, именно это я сделаю в новой версии. Всё остальное, включая потенциальный визуальный контакт врага, который глянет на фонтан, остается в силе.



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



С технической точки зрения это был ад. В статье про вижн я писал, что обзор перерабатывается плавно, даже при смене его типа с наземного в летающий. При наличии у спектры 1800/800 можно увидеть огромный кусок территории, а-ля  баланар с аганимом, и это одним лишь даггером. Поэтому у неё и бруды нет реального обзора — за них «смотрят» специальные даммики, аналогичные тем, что выдаются для исправления бага с обзором при быстром возрождении. На каждую иллюзию тоже выделяется по одному такому даммику. Ну и, плюс к тому, для превращения этих героев в летающую форму используется 4 абилки (одна в, другая из) и по одному клону каждого героя с летающим типом передвижения.

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

В случае с кентавром — требуется копия для каждого юнита, который может оказаться под воздействием ульты. И по две абилки на каждого героя. И еще по две — на каждую альтернативную форму. Т.е. на одного тролля понадобится 5 юнитов и 10 абилок, потому что каждый мили тролль — другой юнит. Отсюда — в лучшем случае кентавр может получить личную воздушную подушку. Появление полета для всех героев в варкрафте нереалистично.

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

Аганим для морфа
Как я уже говорил, здесь 60к строк абилок. Часть из них писалась в здравом уме — и там владелец, уровень и прочие характеристики сохраняются в момент каста. Другая часть писалась абы как, и уровень, хозяина или любую другую характеристику они могут проверять в середине или конце своей работы. Гарантировать, что все они корректно работают, нельзя, а перебирать вручную — долго и муторно.

С учетом нынешней позиции морфа (где-то на уровне дна мирового океана) и его керри-ориентированности в первую очередь, отбросить всё и заняться именно им — скорее роскошь, чем потребность. Как и аганим тускара, этот аганим существует чисто ради фана, но при этом требует непомерно много внимания. По этой причине увидим мы его еще не скоро.



Варды в один слот
Технология как была придумана еще в 83 патче, так до сих пор и не вышла в релиз. Ну никак не получается найти решение запиливания в огромную неповоротливую систему предметов такого финта ушами. И если в идеальных условиях — просто при передаче между героями — никаких проблем нет, то вот с курьерами творится сущий ад. Опция лежит в категории «продолжаем тестить», и света пока не особо видно.



Искусственный Интеллект
Нейтралы и рошан управляются одним и тем же ИИ. Он не блещет оригинальностью решений. Например, если нанести урон от лица неуязвимого или невидимого юнита, крипы побегут как ошалелые. При этом они не будут обращать внимания на тех, кто их бьет, всю дорогу, что дает 5-10 секунд свободной безнаказанной атаки. Также нейтралы любят агриться на любых юнитов рядом с ними, включая курьеров.

Если с поведением еще можно придумать правки, то как быть с курьерами — неясно до сих пор. Лечения так и нет.



Дабл-клики для каста на себя
Невозможны по своей сути, т.к. панель скиллов закрыта при прицеливании и ничего не может зарегистрировать, никаких нажатий.

Glimmer Cape без отмены приказа
Любое заклинение, которое имеет цель, заставляет юнита прервать текущее действие. Поэтому  Glimmer может быть непрерываемым только в одном случае — если он будет активироваться одним кликом. А раз никаких Ctrl+ Alt+ модификаторов в WC3 не завезли, придется довольствоваться тем, что есть. Да, он будет сбивать ченнел тому, кто его нажимает. Поэтому — думайте до, а не после.

Маг иммун снимает позитивные бафы
Стандартное поведение WC3. Чтобы его побороть, нужно все подобные бафы перевести из стандартных в триггерные. Это куча работы, но не сложной. В будущем и до этого дойдут руки.

M K B и Geminate Attack
Я уже писал, почему у MKB и дальнего боя такие большие проблемы, просто напомню — изменить хочется, но все решения глобальные и никак не попадают в категорию «стабильные». Аналогичные проблемы и у  вивера.

«Недопустимая цель»
Некоторые заклинания нельзя применять на скалы или неподходящую цель. При этом реальный эффект не зависит от типа цели — это лишь вспомогательный механизм прицеливания. Поэтому подобные способности хочется изменить, добавив в разрешенные цели всё, что угодно. Например, так был изменен  Meepo — пуф можно наживать куда угодно, хоть здания, хоть неуязвимые юниты. Но список таких способностей большой, так что работы много.



Баги из будущего

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

Впрочем, какие бы страшные баги не пролазили в продакшн — все равно большинство других, местами еще более ужасных, было отловлено самостоятельно и вообще на публику не попали. В свете того, как Valve просто вывалили на всех Reborn и заставили в него играть, вполне себе человечный подход.

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

avatar
давай продолжение :D
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.