
Недавно я вспомнил о игре Star Wars Jedi Knight: Jedi Academy, на которую подростком потратил больше десяти тысяч часов. Изучая материалы о ней, я наткнулся на любопытную историю.
Оказывается в 2013 году, сразу после покупки Lucasfilm компанией Disney и закрытия LucasArts, разработчики Raven Software запаниковали, что их работа будет навсегда положена под сукно, поэтому они в спешке выложили весь исходный код Jedi Outcast и Jedi Academy онлайн.
Этот дамп был таким внезапным, что они даже не подчистили внутренние комментарии разработчиков. Весь код превратился в капсулу времени, прочитав которую, можно узнать о том, как вымотанные программисты сходят с ума, пытаясь реализовать физику светового меча на движке Quake 3.
Заглянув в основной файл боёв (bg_saber.c), можно увидеть, что вся система схваток на световых мечах представляет собой огромную спагетти-конструкцию switch из пяти тысяч строк.
Я прошерстил кодовую базу и нашёл потрясающие комментарии:
1. sv_savegame.cpp — разработчику пришлось написать имитацию цикла загрузки, чтобы игрок успевал прочитать всплывающее сообщение «Saving».
// Если мне ещё раз придётся писать такую белиберду, я просто брошусь под автобус. int startOfFunction = Sys_Milliseconds(); // ...спустя несколько десятков строк... // Первым дело отложенный скрипт закрывает всплывающее сообщение "Saving", // но нам нужно, чтобы оно отображалось хотя бы секунду, поэтому сидим здесь // в ждущем цикле. См. примечание об автобусе в начале функции.
2. AI_Jedi.cpp — пытаться заставить ботов пользоваться Силой и перемещаться по 3D-картам на CPU 2003 года явно было не самым лучшим решением.
{ //нахрен, просто будем прыгать { //нахрен, просто шарашим Силой
3. Отрезание конечностей (G2_bones.cpp) — для того, чтобы можно было отрезать конечности, в Jedi Academy использовалась собственная система скелетной анимации. Необходимость ручного переопределения углов шарниров привела к этому примечанию:
// зачем это нужно делать, одному дьяволу известно. но это нужно делать.
4. bg_pmove.cpp — кому-то пришлось слишком долго отучать модели персонажей соскальзывать по плоским поверхностям.
{ //мы на земле, не движемся и находимся на ровной поверхности, не надо добавлять сраную гравитацию с помощью clipvelocity!!!
5. NPC_reactions.cpp — реальная логика кода, когда игрок стоит, направив прицел прямо в лицо дружественного NPC.
//спрашиваем, какого хера он делает
6. Математика Quake (q_math.cpp) — этот знаменитый трюк с битовым хакингом позаимствован прямиком из движка Quake 3 Джона Кармака. Даже разработчики из Raven, читавшие его годы спустя, не смогли разобраться, как он работает.
i = 0x5f3759df - ( i >> 1 ); // это что за нахрен?
7. mhead.c — когда движок находит повреждённые заголовки данных файлов MP3 или WAV.
return 0; // чёрт знает, что это такое, но точно не наше...
8. Ошибка с фатальным вылетом (win_glimp.cpp) — что происходит, если графический рендерер полностью отказывается загружаться в Windows.
// сообщение об ошибке, к которой я сделаю откат, если навернётся что-то серьёзное
9. Ярость, направленная на Win32 (инструмент ModView) — те, кому доводилось бороться с Win32 API, оценят имя этой функции, которая заставляла UI обновлять панель заголовка документа.
void FuckingWellSetTheDocumentNameAndDontBloodyIgnoreMeYouCunt(LPCSTR psDocName) { if (gpLastOpenedModViewDoc) { // чтоб, сука, он точно делал то, что нужно... gpLastOpenedModViewDoc->SetTitle(psDocName); } }
10. wp_saber.cpp — когда другой разработчик ломает главный файл заголовка, и тебе приходится вручную объявлять свои переменные через extern.
// Нужно вручную написать для них extern. Нельзя сделать #include qcommon.h из-за какого-то дятла
11. Ограничения скелетных мешей (g_client.cpp) — попытка изогнуть позвоночник персонажа игрока на основании отклонения мыши, не поломав при этом хитбокс.
//ФУХ-Х-Х... ломаем его полностью // ...18 строк спустя... //ФУХ-Х-Х... позвоночник мотыляется, к хренам всё это
12. Исправление мультиплеер-коллизий в однопользовательской игре game (g_active.cpp) — самый быстрый способ устранить баг физики, при котором NPC убивались, залезая друг в друга моделями.
Так как движок Quake 3 создавался для мультиплеера, все части игры — это «клиенты»; Raven переделали движок под однопользовательскую компанию, поэтому если NPC сталкиваются друг с другом на слишком большой скорости, то они просто умирают. Вместо того, чтобы тратить недели на изменение алгоритмов поиска пути искусственного интеллекта, разработчики одним оператором if просто избавились от урона при коллизиях между NPC.
{//ой, в жопу всё это, клиенты больше не наносят друг другу урон, только если это не player
13. Логика состояния транспорта (g_vehicles.c) — обработка логики при столкновении летающих спидеров со стеной.
{//просто сваливаем из него
14. Урон от взрыва (g_mover.c) — вычисление урона игрокам, стоящим рядом с разрушаемым объектом карты.
{//просто разносим их к чертям
16. Отказываемся от линейной алгебры (r_surface.cpp). ModView — это внутренний инструмент, который использовался для рендеринга моделей и анимаций 3D-персонажей. Очевидно, работа с матричными 3D-преобразованиями и математикой поверхностей вынула из кого-то душу.
// В дупу эту математическую хрень, она не работает // #define real_nclip(x0,y0,x1,y1,x2,y2) ( (y1-y0)*(x2-x1) - (x1-x0)*(y2-y1) )
17. Ярость из-за «железа» начала 2000-х (textures.cpp). Жёстко прописываем исключение просто для того, чтобы графические карты AMD/ATI не вызывали вылет инструмента.
if (error && error != GL_STACK_OVERFLOW /* дебильные карты ATI почему-то иногда выдают эту ошибку */ )
18. Машина времени аудиобуфера (cl_mp3.org). Для экономии ОЗУ движок декодирует сжатое аудио линейными блоками, поэтому не может просто перемотать аудиобуфер назад. Разработчик решил, что если часы игрового движка внезапно подтормаживают и из-за этого он запрашивает аудиосэмпл из прошлого, то нужно сдаться и ничего не делать.
// чё?!?!?! Я назад в прошлое должен улететь или чего? Да ну нафиг
Очень странно осознавать, что на этом коде работает одна из самых качественных многопользовательских игр. Выражаю благодарность команде OpenJK за улучшение этого спагетти-кода и сохранение жизни игры.
Комментарии (47)

Rive
22.05.2026 05:36Я полез копать эту тему и случайно нашёл статью 2023 года, которая на основе анализа 11 тысяч репозиториев на Github утверждает, что код с ругательствами статистически качественнее, чем код без них: https://cme.h-its.org/exelixis/pubs/JanThesis.pdf

myswordishatred
22.05.2026 05:36Всё ещё лучшая игра про поединки на световых мечах.

It_poirot
22.05.2026 05:36Я помню эту офигенную игру. Играл в детстве. Но я знаю, что с тогг момента вышли пару новых SW. Мое железо не тянет, так что я не в теме, но неужели там бои хуже?!

myswordishatred
22.05.2026 05:36Вышло-то вышло, но разработчикам не хватает... решимости? фантазии? Не знаю, чего, в общем, чтобы сделать световые мечи такими, какими они были в фильмах.
Вот самый очевидный пример: Fallen Order (ну и сиквел его, Survivor). Там световой меч это просто, ну, палка, который ты бьёшь противников. Не отрезаешь им руки-ноги, как ожидалось бы, а ну вот просто тыкаешь, как в Dark Souls каком-нибудь. С этим как-то можно было мириться двадцать лет назад в KotOR, но сейчас-то в чём проблема? Слишком просто будет? Так геймдизайнеры у вас за что деньги получают? Пускай придумают, чтобы было не слишком просто.
В общем, там бои не то чтобы хуже, просто они не про фехтование на световых мечах.

Wijey
22.05.2026 05:36Конечности и в оригинале по дефолту очень редко отлетают. Но если в консоли прописать одну команду - меч начинает рубить как надо, и врагов и игрока, становится весело, но хардкорно

myswordishatred
22.05.2026 05:36Это требование издателей, кажется, было, да, посчитали что как-то многовато расчленёнки.
Но я больше про то, что враги умирают с одного-двух тычков, а не впитывают урон и не блокируют световой меч(!), как будто у них там оружие и броня сплошняком из кортозиса сделаны.

HardWrMan
22.05.2026 05:36не блокируют световой меч(!)
А как во вселенной SW объясняют возможность блокирования светового меча другим световым мечом?

myswordishatred
22.05.2026 05:36Честно говоря без понятия, техномагия. Вот просто блокируют они и всё, такой канон у вселенной.
То есть там пытаются что-то про магнитные поля писать в официальных энциклопедиях, но это всё настолько комично выглядит, что лучше бы не писали вовсе ничего.

Oncenweek
22.05.2026 05:36Начинают обычно с того, что меч не именно “световой”, а скорее что-то вроде плазмы в силовом поле. А силовые поля друг друга блокируют, этож силовые поля

yellowmew
22.05.2026 05:36ну, в книгах РВ авторы поддержали именно эту идею
в частности, сейчас вспоминается пара случаев: один "меч" с регулируемой длиной, в котором описывалось как раз расширение силового поля, и второй - меч Люка, который тот сконструировал сам (то самое изменение цвета меча в фильмах) взамен потерянного на Беспине. В книгах более подробно описывается в том числе фокусирующий кристалл, регулятор силового поля, источник питания.

cruiseranonymous
22.05.2026 05:36И, емнип, эти же кристаллы допускают "но если кристалл вот эдакий - то оно уже не меч а плеть; а если вот так треснутый то он ещё и ветвится как молния"
Если это не тот расширенный канон, который уже не канон потому что мышь выкинул.
yellowmew
22.05.2026 05:36Если это не тот расширенный канон, который уже не канон
ну, я не говорил про "канон" так-то. РВ - расширенная вселенная. С одной стороны книги писались так что общая линия с лукасартс согласовывалась, с другой стороны сам Лукас (еще до продажи Диснею) мог все переиграть или заретконить. В нынешней вселенной наплаканной Диснеем - вообще ничего не понятно, потому что весь бэкграунд выкинули =)
но если кристалл вот эдакий - то оно уже не меч а плеть а если вот так треснутый то он ещё и ветвится как молния
А вот этого не помню. Помню энергетический кнут времен Дарта Бэйна из "гибкого", да и тот не совсем "световой меч", остальное - почти стандартные "палки"

cruiseranonymous
22.05.2026 05:36Погуглил - да, кроме хлыста только кайлореновский меч с ответвлениями, но там они обоснованы как отдельные выводы.
Значит, форму молнии попутал с сило-магией. Был неправ.

Damnt
22.05.2026 05:36g_saberrealisticcombat2 или 3 - эх, как сейчас помню. Причем на 2-ке конечности постоянно отлетали, но только при нажатии кнопки удара, а на 3-ке - достаточно было модели меча коснуться другого тела

Oncenweek
22.05.2026 05:36С этим как-то можно было мириться двадцать лет назад в KotOR
KotOR так вообще РПГ буквально с механикой кубиков, как совместить стандартное РПГшное “вы нанесли 15 урона” с тем, что каждый непропущенный тычок ваншотит даже Эйнштейн не сообразит

myswordishatred
22.05.2026 05:36Потому и можно было закрыть глаза на это.
Но в целом-то придумать можно было бы: побольше противников давать, или выдать Бастилу и сделать ГГ джедаем (надеюсь, что можно безболезненно написать спойлеры к игре возрастом 20+ лет) попозже, или в качестве противников выдавать не бомжей, а всяких ситхов пожиже, да мало ли способов.

Oncenweek
22.05.2026 05:36Все одно, оно не совместимо с механикой классической РПГ, коей игра является, а все эти варианты превратят ее в экшон. Это же буквально жанровое, а не техническое ограничение. Так-то никто не считает за недостаток, что в каком-нибудь “Фоллауте” пистолет (тем более лазерный) не ваншотит с вероятностью 95%, как в реальности

myswordishatred
22.05.2026 05:36Это всё справедливо, но лудонарративный диссонанс всё равно присутствует.

Oncenweek
22.05.2026 05:36Ну он так-то присутствует буквально в любой РПГ (да, черт возьми, даже в почти любом шутане кроме самых хардкорных) - глобально простой меч должен расчленять не сильно хуже светового, особенно если противник не в металлической броне, любой огнестрел должен убивать с одного-двух выстрелов, тяжелый огнестрел вообще не должен оставлять шансов на выживание (это же справедливо и для другого дистанционного оружия - что бластеров из тех же ЗВ, что каких-нибудь турбо-плазменных винтовок). ЗВ со световыми мечами тут особняком не стоят, это буквально всеобщая жанровая условность

not-allowed-here
22.05.2026 05:36а самое имбовое это честный лут - взять туже "7,62: High Caliber" - без грузовика после зарубы лут не вывезешь....

not-allowed-here
22.05.2026 05:36ну.... теоретический нанять пяток усратых D&D мастеров и попросить их реально продумать как вписать в Игру такое - я думаю при наличии пары недель, неограниченного запас Пива, Кофе и вкусняшек и понимания что в их игру будут потом играть миллионы они бы справились....
Даже мне видится с десяток вариантов как на тех же кубиках реализовать отсечение конечностей и так чтобы оно не сильно ломало канон игры.... а так джедаи Имба по канону и эту имбовость надо использовать очень правильно - ибо ИМБА это зверь страшный именно тем что вписать его куда либо так чтобы он при этом оставался интересным невероятно сложно....

Oncenweek
22.05.2026 05:36Да само-то отсечение конечностей это несложно - этож банальной “критическое попадание”/“критический промах”, тут вопрос в том, что механика РПГ предполагает кучку “-5ХП -2ХП -3ХП”, а не “промах-блок-блок-промах-ваншот”, ее конечно можно так переделать, но это будет совсем не ДнД, а самое главное это та жанровая условность которая характерна буквально для каждой квази-ДнДшной РПГ, то что меч световой, а не железный дела не меняет

FAZAA
22.05.2026 05:36По иммерсивности боях на световых мечах действительно до сих пор нет ничего лучше, но в Fallen Order у тебя соулс-лайн боевка, где ты дерешься и с адептами силы в т.ч. Игра неплохая, как фанат вселенной ЗВ, ставлю ей 7.

H01y
22.05.2026 05:36Не то чтобы конкурентов много. Всё остальное лайтсейберное фехтование - это аркадные экшоны. Я не то чтобы против, но хочется разнообразия.

myswordishatred
22.05.2026 05:36Не то чтобы конкурентов много.
Что удивительно, кстати. Мне кажется, что киберспортивный потенциал у игры был бы шикарный. Собственно, в мультиплеер Jedi Academy до сих пор какие-то бешеные фанаты рубятся.

Damnt
22.05.2026 05:36Во-во. Некоторое время назад попробовал под VR "Blade & Sorcery" с модом про звёздные войны - плакал от счастья как младенец
Metotron0
https://ru.wikipedia.org/wiki/Быстрый_обратный_квадратный_корень
HardWrMan
Это было даже здесь, на Хабре. Более того, подобный коммент был в исходниках Квейка, т.е. от самой Id.
Rive
Комментарии переведены по-разному, но обратившись к статье Википедии на английском языке с исходником Quake III и к исходнику Q_rsqrt() Jedi Academy можно убедиться, что эти фрагменты идентичны, включая комментарии и закомментированную строчку в конце.
То есть часть ругательств в исходниках была бережно перенесена из более древних проектов.