1 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Как EA усложнили нам жизнь, или как мы чинили баг 12-летней давности

Как EA усложнили нам жизнь, или как мы чинили баг 12-летней давности

Иногда в программы закрадываются баги. Причем закрадываются так, что обнаружить их получается лишь через много-много лет после выпуска, когда чинить их уже нерентабельно. Иногда такие баги оказываются слишком критическими, чтобы их игнорировать. Поэтому под катом я расскажу, как мы устраняли один такой критический баг в одной старенькой гонялке. А заодно наглядно продемонстрирую, чем плох float, какие могут быть последствия и как с этим бороться.

Лирика

Речь пойдет об игре Need for Speed: Most Wanted. Эта игра очень популярна и крайне любима многими геймерами-энтузиастами, и многими считается чуть ли не лучшей в серии. Даже если вы не азартный игрок, то наверняка слышали об этой игре в частности или о серии в целом. Но обо всем по порядку.

Я – спидранер. Прохожу игры на скорость. Довелось мне быть одним из первопроходцев в деле скоростного прохождения гоночных игр, поэтому я заодно являюсь одним из «глобальных модераторов» спидран-коммьюнити серии NFS. Участь со мной разделил чех под ником Ewil.

Почему участь? Потому что в один прекрасный момент к нам в дискорд-сервер пришел человек и заявил, что все наши рекорды трасс неправильны, и что мы – нубы. Скрепя сердце, подавляя багет от, как казалось, необоснованного обвинения и борясь с языковым барьером (английским этот человек владеет на очень плохом уровне), мы начали разбираться, что же не так с нашими рекордами. Из обрывков речи мы поняли, что в игре есть некий «timebug», который делает IGT неправильным. Ewil пересмотрел некоторые записи и руками пересчитал время. Оказалось, нам не врали. На записях IGT резко отличалось от RTA . Это были не пара миллисекунд, которые тоже могу решить исход рекорда, а местами разница доходила даже до нескольких секунд(!).

Мы начали искать причину и последствия этого явления. Еще задолго до этого я в личных интересах пытался «вытащить» из игры IGT. Моя попытка не увенчалась успехом, и я как-то забил на эту идею. Информации в интернете мы найти не смогли, за исключением какой-то английской странички с очень коротким описанием, без какой-либо доказательной базы. Поиск по ютубу также не принес результатов, но были найдены записи, которые гласили «No TimeBug».

Чуть позже я познакомился со SpeedyHeart, и она мне подсказала, что в игре время считается как float. Тут все начало проясняться, и мы медленно переходим от унылого вступления к лютому экшону!

Как это работает

Вооружившись Cheat Engine, OllyDbg, DxWND и NFS: MostWanted версии 1.3, я полез рыться в памяти. Выкопал я примерно вот что (картинка кликабельна):

Нас интересуют последние три адреса. Они хранят в себе IGT для разных ситуаций. Почему они float – одному Блэк Боксу известно… Но так не делают! Float, у него же точность, как у дробовика, а может и того хуже.

Собственно, немного о самих таймерах. Таймеры хранят время в секундах, т. е. целая часть – количество полных секунд. Два из этих таймеров, а именно Global IGT и Race IGT, периодически обнуляются. Для Global IGT это происходит в момент выхода в главное меню, а Race IGT обнуляется при рестарте гонки. Подсчет IGT производится через Global IGT, и в какой-то момент времени ему уже не хватает точности. Из-за этого время считается неправильно.

На этой стадии меня заинтересовали несколько вопросов:

  1. Раз уж есть разница во времени, то отличается ли геймплей с багом и без? Логично предположить, что если IGT ускоряется, то и в целом игра должна становиться «быстрее»
  2. Какие рамки у этого бага? Как он будет себя вести при разных значениях таймера, и как на это будет реагировать игра.

Ответ на вопрос номер 1 был найден крайне быстро. Я просто взял и изменил показания Global IGT на 300000.0 и получил то, что получил. Время ускорилось почти в два раза(!), однако на физике и поведении игры это никак не отразилось. Прикола ради я тыркал и другие таймеры, но они, почему-то, ни на что не влияют. Собственно, если бы с ускорением времени ускорялся и геймплэй, то в нашем мире спидранерства это считается вполне законным. Все таки мы любим баги. Но такой расклад никого не устроил.

Я пошел немного глубже и нашел ответ на вопрос 2. Как только Global IGT достигает отметки в 524288 время в игре полностью останавливается. Это немного смущает игру, и она начинает плохо себя вести делать интересные вещи. Например, не дает начать гонку после рестарта, намертво блокируя игру (выйти из нее можно только через диспетчер задач или Alt+F4). Отрыв/отставание от соперников перестает работать. А если проиграть гонку, то игра отправляет вас в свободное плавание по миру.

Float — ад перфекциониста.

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

Перед непосредственно кодом, распишу немного про цели. Известно, что игра «блокирует» цикл обновления физики на 120 раз в секунду (опять же, спасибо SpeedyHeart за информацию). Однако vsync обрубает обновление физики еще сильнее, до 60 раз в секунду. Соответственно, мы просто возьмем float-переменную и будем циклически туда добавлять 1/60 секунды. Потом мы посчитаем, за сколько шагов мы добились результата, и за сколько шагов мы должны были добиться этого результата. Также будем делать все циклически для разных случайных величин и считать среднюю погрешность в рассчетах. Любые отклонения в 2 и менее шагов (33мс) мы будем считать незначительными, потому что игра показывает время до сотых секунды.

Читать еще:  Эволюция Dodge Challenger из гоночной серии Need for Speed

Меняя значения START_TIME и TEST_TIME мы можем получить необходимую нам статистику. В целом, пока START_TIME не превышает 15 минут, то обычный 2-х минутный заезд окажется «свободным» от бага. Разница остается не критичной в рамках игры, 1-2 кадра:

16 Минут же оказались «критической точкой», когда время беспощадно плывет:

Интересен так же тот момент, что в зависимости от START_TIME будет меняться «сторона» ошибки. Например, после полутора часового непрерывного геймплея время начнет течь медленнее, чем должно:

Поигравшись со значениями еще немного я оценил, что в получившейся программе «время» течет примерно так же, как в игре. Это было подтверждено практически – любые рекорды, записанные «из главного меню» в течение первых 15 минут геймплея были чистыми. При START_TIME близкому к 300000 секунд количество шагов было почти в два раза меньше, чем ожидалось. При START_TIME, большем магической константы 524288 программа переставала работать. Все это подтверждало, что процесс подсчета времени был скопирован верно.

Устраняем нежелательное поведение

Теперь, когда известна проблема и ее поведение, можно ее устранить. Нужно лишь перезаписывать Global IGT всякий раз, когда игрок начинает заезд заново. Это можно узнать довольно просто – в этот момент обнуляется Race IGT. Но тут есть проблема.

Есть два издания игры: NFS: Most Wanted и NFS: Most Wanted Black Edition. Второе издание включает в себя две дополнительные машины и две трассы, да 69-ое испытание. Но, технически, это две совершенно разные игры! Их запускаемые файлы отличаются. Помимо этого, есть патч 1.3… Который отличается для каждого издания. В итоге у нас есть 4 разных версии игры, которые надо поддерживать. Этот факт делает «правильный» путь чрезмерно сложным и неоправданным. По-хорошему, нужно слегка подправить запускаемый файл и обнулять счетчик там, но… Править 4 разных экзешника, которые еще и запакованы, да защищены от отладки… Лучше просто напишем простую программку, которая будет в реалтайме отслеживать состояние таймеров и обнулять их при необходимости. Писать будем на C#.

Вот такую архитектурку я набросал. GameProcess – это вспомогательный класс, который упрощает доступ к чтению-записи памяти процесса. GameHolder – сердце программы. Он будет инициализировать GameProcess, а при «подцепе» процесса будет определять версию игры и создавать необходимый экземпляр наследника Game. Поскольку логика «фикса» не отличается от версии к версии, то ее лучше вынести в один класс.

Как же нам определить версию? Просто – по размеру основного модуля. Я специально реализовал проперти ImageSize. А чтобы не захламлять код магическими константами, запилим enum:

Остальные версии добавим по мере их попадания ко мне в руки.

isUnknown отвечает за тот факт, удалось ли нам определить версию или нет. Из всего класса нам интересен только метод Refresh, вот он:

Логика фикса вышла совсем простенькой:

Дело осталось за малым: реализовать версию, выставив в конструкторе необходиме значения соответствующим protected-переменным. В мэйне же просто кидаем цикл обновления в отдельный трэд и забываем про него. Ах да, из-за особенностей карточек Nvidia и особенностей реализации установщика игр NFS мы будет принимать на вход имя процесса, чтобы была возможность кастомизации.

На этом фикс заканчивается. Компилируем, запускаем и забываем о таймбаге, yay! ^_^ Картинка кликабельна.

На самом деле, никуда этот баг не денется. Если один заезд физически не уложится в рамки 15 минут, то тут уже ничего не поделаешь. Но таких заездов в игре аж один, и тот от полиции.
Полные исходники на гитхабе.

Summary

Вот так один маленький баг нехило подпортил нам жизнь. А ведь его можно было избежать, если бы Black Box использовали в свое время double, но нет. Кстати, это яркий пример того, как «написанное однажды» выливается в кучу неулавливаемых/перекатывающихся багов. Timebug присутствовал в каждой игре от Black Box ever since. В Carbon, ProStreet и даже Undercover. В последнем они поменяли логику подсчета IGT, но эти три таймера там все так же присутствуют, и ошибки округления приводят к странным последствиям. SpeedyHeart обещала сделать видео-обзор всей найденой в процессе информации, так что ждем-с.

Чему меня научила эта ситуация? Не знаю. Я и так понимал, что использовать float для серьезных вычислений – идея сомнительная. Но теперь я лучше представляю, как именно все это будет работать на практике. Однако забавно получилось, что такая серьезная компания могла допустить такую серьезную ошибку, да еще и несколько лет подряд не замечать ее.

Мне кажется, что для данной задачи (подсчет IGT) нужно использовать такой путь: ставить timestamp в начале заезда, а потом вычитать из текущего времени. Причем арифметических операций стоит избегать, даже над целыми числами. 1/60 секунды это 16,(6) миллисекунд, поэтому в случае целого числа мы будем наивно откидывать 0,(6) при каждом сложении, что приведет к неточностям в подсчете.

В некоем обозримом будущем я постараюсь написать фикс и на другие версии. На этом у меня все, спасибо за внимание.

Читать еще:  Мнение - Need for Speed: Hot Pursuit

UPD: Поправил ссылку на гитхаб всвязи с переездом на новое имя.
UPD2: Выкатил вторую часть, интересующиеся могут прочитать.

Need for Speed: Most Wanted (preview)

Разработчик:EA Canada
Издатель:Electronic Arts
Жанр:3D-симулятор
Официальный сайт:Need for Speed: Most Wanted

Автор: Александр Снегов
Дата: 19.11.2005

Интригующая криминальная история станет основной «зацепкой» новой гонки из серии NFS: нелегальные гонки, «подстава», тюрьма и чудесный шанс повторно взлететь в поднебесье автогоночной элиты.

Геймплей

Серия NFS в особом представлении не нуждается. Поэтому перейдем сразу к впечатлениям от демо-версии. Игра Most Wanted является последователем ветки Hot Pursuit, т.е. главный козырь игры — соперничество с блюстителями порядка — копами. Визуально игра повторяет Underground 2, но геймплей отличается именно «коповским» контентом.

Режимы

Из главного меню можно выбрать вид игры, а именно карьера (Blacklist), быстрая гонка (Quick race) и различные соревнования (Challenge series). Раздел Blacklist в демо-версии реализован в виде видео-заманухи поэтому, ничего особенно конкретного о нем сказать нельзя, однако, из внешних источников известно, что он и будет являться своеобразной карьерой, цель которой продвижение к вершине «коповского» черного списка (Blacklist) до статуса Most Wanted, т.е. «самый разыскиваемый полицией». Список состоит из 16 позиций, каждую из которых занимает один из соперников, которого и предстоит «выбить». Чтобы продвигаться выше, нужно победить в серии разнообразных гонок (до 10 на каждый пункт Blacklist) в той или иной степени задействующих различные режимы игры, такие как кольцевые гонки, езда из точки А в точку Б (спринт). Приготовьтесь опробовать новшества: гонки Speedtrap и Tollbooth, не говоря уже о классической беготне от полиции и ее вариации в виде Roadblock. В общем, Blacklist это смесь — всего понемногу.

Помимо «смеси», также как и в предыдущих Hot Pursuit и Hot Pursuit 2, в игре предусмотрены «чистые» разделы «без полиции» и «с полицией». «Без полиции» — это Quick Race с настройкой сложности траффика на дорогах и количества оппонентов. Здесь гонки лишены участия дорожной полиции (по крайней мере, в демо-версии), а вот заезды Challenge series — наоборот, происходят с активным участием копов.

Теперь чуть подробнее о свежих режимах гонок. Кольцевые и спринт — не ново. В Speedtrap вы стартуете с группой «товарищей». Гонка происходит по четко обозначенной трассе, снабженной фото-радарами. Задача здесь в том, чтобы пройти каждый фото-радар на максимально возможной скорости. Почему фото-радар? Потому, что по концепции игры ему можно доверять и его показания являются доказательством вашей «крутизны», ну не об этом. Итак, показания пройденных фото-радаров суммируются и определяют вашу позицию в рейтинге заезда (таблица справа вверху экрана). По окончании гонки подводится итог и самый быстрый «нарушитель» выигрывает по результатам фото-сессии. Еще один вариант использования показаний полиции в качестве доказательства — это режим Tollbooth. По сути это обычный заезд с чекпоинтами в виде пропускных пунктов. Здесь фиксируется не максимальная скорость прохождения точки, а замеряется время от одного пункта до другого. Чем меньше — тем лучше. Теперь от пассивного участия полиции в гонке перейдем к активному.

В игре полноценно реализована классическая беготня от полиции. В вашем распоряжении радар (вверху экрана) и своеобразный анализатор трудности положения (внизу экрана). Чем больше полоска на верхнем радаре, тем ближе вы к представителю правопорядка, будь то коповская машина или фото-радар. Анализатор внизу экрана — это шкала, заполнение которой влево красным цветом приближает ваш «конец» (ненавистное «busted»), а вправо — означает вероятность полного освобождения от полицейского преследования. Полоска постоянно двигается и меняется в зависимости от ситуации. Кроме того, карта слева внизу экрана снабжена неким огненным значком с цифровым индексом. Он показывает насколько вас «хотят» поймать. Чем больше эта цифра, тем более серьезные меры к вам будут применяться и агрессивнее поведут себя полицейские — видимо поэтому в заездах раздела Challenges и нет возможности выбора уровня сложности. Как правило, все начинается с банальной группы копов на хвосте, но с увеличением индекса появятся серии машин, перегородивших дорогу, причем машины будут разной весовой категории, опять же в зависимости от уровня тревоги. В полной же версии нас ждут различные останавливающие приспособления вроде шипованных полос, блоков и уже традиционных вертолетов. Разновидностью «коповких» гонок является режим Roadblock, где необходимо пробить несколько «загородок» из полицейских машин, перегородивших дорогу. В режиме Pursuit Length требуется продержать у себя на хвосте копов какое-то время (минимум минуту в демо), а потому уже прятаться. Да, особенностью полицейского режима является именно возможность прятаться. Когда полицейские теряют вас из виду, нижний анализатор преобразуется в единую шкалу, которая постепенно заполняется синей линией и символизирует «окончательность» потери вас полицией. Кроме того, на карте появляются синие вращающиеся кружки — в этих местах можно надежно укрыться. Тонкость в том, что если вы попытаетесь «окончательно» спрятаться в режиме Roadblock, то заезд будет проигран, если вы не прошли указанное число «кордонов», поэтому, в нем, как только избавитесь от копов, поспешите показаться им на глаза снова.

Карта города действительно большая. Не так чтобы совсем огромная, но достаточно большая для того, чтобы почувствовать свободный полет. В некоторых режимах игры карта открыта вся, а в некоторых прочерчена только «белая линия» с несколькими небольшими ответвлениями и дорожками для срезания. Также возможен вариант, когда ветки карты блокируются постепенно в процессе гонки, что немного усложняет маневрирование (режим Roadblock).

«Фишки»

В игре реализованы функция «замедления времени». Пресловутый «bullet-time» не дает покоя разработчикам, поэтому в NFSMW можно нажать правый Ctrl и замедлить происходящее. Ресурс «замедлялки» ограничен, но запас пополняется. Аналогично обстоит дело и с «нитро». Повреждения в этой игре — это удел копов. Вы можете испытывать лишь косметические повреждения стекол и кузова, не влияющих на ваши ходовые качества. При этом полицейские автомобили вполне могут пестрить отбитыми капотами и крыльями, вплоть до повреждений «не совместимых с жизнью». Еще одной интересной возможностью игры является наличие мест-ловушек. Они отмечены на карте красными треугольниками и позволяют сделать пакость преследователям. Например, таким символом может быть обозначена опора небольшой деревянной конструкции, сбив которую, вы обвалите все строение (позади себя) и ненадолго испортите жизнь копам, а если повезет — то и выведите кого-нибудь из них из строя. О реализме окружающего мира говорить не приходится: легко разрушается или отлетает все, начиная от небольших предметов на дороге, заканчивая фонарными столбами, остановками общественного транспорта и деревянными заборами. Встречные автомобили при лобовом столкновении отлетают как футбольные мячи. Опасность представляют только крупные каменные конструкции, большие деревья и т.п., причем опасность не в повреждениях (которых нет), а в задержке. Уперевшись в такую конструкцию конечно можно нажать на R и снова появиться на дороге, но вот злоупотреблять этой кнопкой в обществе копов не рекомендуется — шансы оказаться «busted» очень велики.

Читать еще:  Need for Speed: Underground 2 - прохождение, гайд, руководство, мануал, FAQ

В течение игры вы набираете очки, за которые будете приобретать апгрейды, обвес и новые машины. К сожалению, в демо-версии о тюнинге ни слова, но почувствовать разницу между базовой и тюнингованной версией автомобиля можно в QuickRace, где Ford Mustang и Porsche Cayman S предстанут в обоих вариантах. Полная же версия даст возможность объездить автомобили марок Aston Martin, Audi, BMW, Mercedes-Benz, Dodge, Fiat, Ford, Corvette, Cadillac, Pontiac, Vauxhall, Cobalt, Lamborghini, Lotus, Mazda, Mitsubishi, Porsche, Renault, Subaru, Lexus, Toyota, VW.

Графика и звук

Графика была и остается достоинством всей серии NFS и этой игры в частности. Помимо стандартно шикарного освещения, эффектов и моделей здесь можно увидеть опадающую листву, перелетных птиц, эффект дождя, а при длительной гонке меняется время суток, от утра к вечеру и наоборот — ночи нет. Эффект скорости передается безупречно даже на тех не самых быстроходных моделях, которые доступны в демо. На стартовых роликах видно затемнение стекол, виден водитель и даже просматривается кожаная обивка салона авто. Ролик задержания (когда вы «busted») — это вообще отдельная тема для диссертации: как всегда с юмором и красиво. Полицейский ведет себя непринужденно, может дать подзатыльник, а лицо задержанного скрыто в стиле оперативных видеосъемок.

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

Ложка дегтя…

Коротко о неприятном. Нет вида из кабины — это конечно на любителя, но все же. Ни о каком реализме вождения говорить не приходится — аркада 100%. В игре нет повторов — досадно при такой шикарной графике и головокружительных пируэтах, которые иногда удается совершать. Отсутствие повторов компенсируется эпизодическими киношными видами с внешней камеры, которые изрядно сбивают. Тоже относится и к ролику пробивания полицейского кордона, который всегда выглядит красиво, но после возвращения в кабину, как правило, сталкиваешься с совершенно неожиданной ситуацией на дороге. В плане геймплея замечена такая вещь: в режиме Roadblock, когда требуется пробить 6 полицейских кордонов, куда проще выехать в город и подыскать кольцевую дорогу, чтобы не усложнять себе жизнь, гоняя по всей карте и рискуя попасться в новом месте — а ведь придется все заново начинать. Найдя «кольцевую» (некий условный круг на карте), можно наматывать круги на полной скорости, слегка подправляя руль, и время от времени пробивать кордоны: утомительно зато эффективно, а разработчикам «минус». Сколько еще таких «нюансов» выплывет? Наверное немало.

Вывод

Игра несомненно «достойна» благодаря копам — ради них чего только не сделаешь. Динамичный гемплей, супер-скорости и многообещающий парк машин, только оттюнинговать которые уже чего стоит. Несомненным плюсом игры является широта аудитории: и детям и взрослым будет с чем поразвлечься. Чего только стоит вступительная агитационная фраза смазливой супер-модели, которая намекает, что вы ребята тут отрывайтесь на все 100%, а по дорогам ездите правильно и ответственно. И хитро так подмигнула…

Подведение итогов.

На данной ноте эта статья заканчивается. Но перед тем, как закончить ее нам необходимо подвести итоги по игре и по чит-кодам. Итак, игра Need for Speed: Most Wanted очень интересная и увлекательная. Но все же игра имеет некоторые минусы. Они по большей части мелкие, но есть главный минус – это затянутость игры в середине. Отбросив все минусы, я с чистой душой могу порекомендовать Need for Speed: Most Wanted. А если вы ее проходили, то советую вам вспомнить как это было и снова поиграть.

p, blockquote 15,0,0,0,0 —> p, blockquote 16,0,0,0,1 —>

Ну и под конец подведем итог по чит-кодам. Чит-коды в Need for Speed: Most Wanted дают вам отличный старт в начале игры. Но все же стоит ли они того? Решайте сами, но скажу одно, не увлекайтесь ими, иначе игра может вам быстро наскучить. На этом все, удачной игры.

Ссылка на основную публикацию
Статьи c упоминанием слов:
Adblock
detector