Введение:
Я благодарю аудиторию KOTOR на Playground: если бы не их интерес к достаточно сложной теме, а именно к модификации ресурсов игры, этой статьи бы не было!
На правах автора я позволю себе лирическое вступление.
Я удивлён, что именно KOTOR стал той игрой, для которой мне захотелось выделить время и изучить фундаментальные разработки BioWare; эти инструкции стали частью этого мира! К сожалению, я сегодня наблюдаю очень тревожную картину, и я рад, что именно сага Джорджа Лукаса помогает мне сегодня подобрать слова, которые я буду писать ниже. О грустном я говорить не буду: я буду описывать, что КОТОР нам дал и почему я сегодня отдаю честь этому апостолату на кладбище. Среди разработчиков очень много ненависти к аура/одисей-движкам BioWare, и я понимаю, с чем это связано: я попробовал, и теперь мои слова не будут пустыми. Эти движки действительно тяжёлые в освоении, местами неудобные, капризные и беспощадные к ошибкам. Они не прощают поверхностного подхода, не ведут разработчика за руку и постоянно требуют внимания к мелочам. Но именно в этой суровости и проявляется их сила: они заставляют разбираться в логике игры по-настоящему, а не просто нажимать кнопки в редакторе.
Именно КОТОР, как он есть, — прекрасная игра, которая прививает дисциплину с детства. Я помню первое прохождение, как я читерил, чтобы убить ранкора палкой; помню первое прохождение без читов, первые чувства, что ты победил скрипт (у меня потом это WoW'ом закончилось, но не важно). И самое главное: эта игра была беспощадна. Постоянные вылеты, краши, битые белые сейвы затрудняли прохождение и вынуждали постоянно делать бекап. Такой, казалось бы, банальный, привитый с детства навык в будущем ещё не раз вспомнят добрым словом джедаи, которые росли на КОТОР. В 2026 году я решил сразиться в этой игре с боссом, которого ещё не убивал, и эта статья посвящена знаниям, которые я получил в этой битве. Возможно, все эти буквы станут тем самым датападом с подсказкой; как минимум это станет ещё одним подтверждением алгоритма для CLI-систем.
Босса я сделал. Описывать весь техпроцесс мне, если честно, просто лень: этот путь джедай должен пройти самостоятельно, когда захочет поиграть в КОТОР следующего уровня.
Я расскажу о техпроцессе, который был затронут в ходе обсуждения комментария пользователя Wolfryu21. Это очень удобный частный случай, на котором я бы хотел описать, как КОТОР даёт по щам на этом уровне сложности.
Приступаем к работе
Наша цель – создать модификацию для КОТОР, которая будет менять компаньона в слоте 7 посредством диалогов в игре.
Скачиваем архив `KOTOR_HANDMADE.zip`. В архиве компилятор, инструкции и исходные файлы; в каталоге `05_release` также лежат готовые файлы для сравнения, чтобы было видно, что в итоге должно получиться.
В примере будем использовать путь `D:\KOTOR_HANDMADE`.
Вы можете расположить каталог по такому же пути для удобства дальнейшей работы.
Я уже поместил исходные файлы мода Sleheyron + RU by jenkeee в каталог `01_original`. Там лежат файлы из лайв-клиента, с ними мы и будем работать. Убедитесь, что файлы в вашем каталоге `Override` побайтно равны моим.
Если они отличаются, то инструкция, которую я пишу ниже, является лишь примером, а не точным руководством.
Каталог `01_original`, надо наполнить файлами вашего клиента. С этими данными будет связана вся дальнейшая работа. Для продолжения работы нам потребуется Python.
Важная предустановка.
скачай установщик `Python 3` для Windows
запусти установщик
на первом экране обязательно включи галочку `Add Python to PATH`
нажми `Install Now`
дождись конца установки
Главное место здесь – галочка `Add Python to PATH`.
Если её не включить, команды `python ...` в `cmd` могут не работать.
Подготовив инструменты, переходим к безудержному веселью.
Декомпиляция
Открой `cmd` и выполни:
cd /d D:\KOTOR_HANDMADE\tools\nwnnsscomp
Дальше:
nwnnsscomp.exe -d "D:\KOTOR_HANDMADE\01_original\t3_return.ncs" -o "D:\KOTOR_HANDMADE\02_decompiled\t3_return_decomp.nss"
Дальше:
nwnnsscomp.exe -d "D:\KOTOR_HANDMADE\01_original\recruit_vima.ncs" -o "D:\KOTOR_HANDMADE\02_decompiled\recruit_vima_decomp.nss"
Как итог, мы получим дизассемблированный байткод `.ncs` — то есть compiled NWScript из движка BioWare в доступном для чтения и редактирования `NSS`-формате. Пока полученный байткод не трогаем!
Чтение DLG
Дальше ещё веселее. Мы будем читать `DLG`-файлы. Мы будем использовать предустановленный Python для этого. Выполните команду:
python "D:\KOTOR_HANDMADE\tools\python\inspect_dlg_entries.py" "D:\KOTOR_HANDMADE\01_original\party_vima.dlg" 6 117 24
Так мы сможем увидеть, как построен диалог с Вимой и имеющиеся вхождения.
Командой ниже мы изучим диалог с Т3.
python "D:\KOTOR_HANDMADE\tools\python\inspect_dlg_entries.py" "D:\KOTOR_HANDMADE\01_original\k_htmd_dialog.dlg" 4
Следующим шагом мы соберём данные из `UTC`-файла Вимы и посмотрим конкретные нужные нам строки.
python "D:\KOTOR_HANDMADE\tools\python\kotor_inspect.py" gff "D:\KOTOR_HANDMADE\01_original\p_vimasunrider.utc" --field TemplateResRef --field Tag --field Conversation
Ты должен увидеть примерно это:
`TemplateResRef: p_vimasunrider`
`Tag: p_vimasunrider`
`Conversation: party_vima`
Теперь, изучив полученные данные, мы готовы к бою.
Создаём руками файлы в папке `03_scripts`.
Первый файл назовём:
vima_call_t3.nss
И наполняем его C-подобным содержимым:
void SpawnSlot7(location lSpot) {
SpawnAvailableNPC(7, lSpot);
}
void main() {
object oCurrent = OBJECT_SELF;
object oHost = GetFirstPC();
location lSpot = GetLocation(oCurrent);
object oTempT3 = GetObjectByTag("x_t3m4", 0);
object oRealT3 = GetObjectByTag("t3m4", 0);
RemoveAvailableNPC(7);
AddAvailableNPCByTemplate(7, "availnpc7_t3");
AssignCommand(oHost, SetGlobalFadeOut(0.0, 0.35, 0.0, 0.0, 0.0));
if (GetIsObjectValid(oTempT3)) {
AssignCommand(oHost, DelayCommand(0.40, DestroyObject(oTempT3)));
}
if (GetIsObjectValid(oRealT3)) {
AssignCommand(oHost, DelayCommand(0.40, DestroyObject(oRealT3)));
}
AssignCommand(oHost, DelayCommand(0.40, DestroyObject(oCurrent)));
AssignCommand(oHost, DelayCommand(0.45, SpawnSlot7(lSpot)));
AssignCommand(oHost, DelayCommand(0.80, SetGlobalFadeIn(0.0, 0.35, 0.0, 0.0, 0.0)));
}
================================================================================
Теперь создадим:
t3_call_vima.nss
И также наполним его, но уже другим содержимым.
================================================================================
void SpawnSlot7(location lSpot) {
SpawnAvailableNPC(7, lSpot);
}
void main() {
object oCurrent = OBJECT_SELF;
object oHost = GetFirstPC();
location lSpot = GetLocation(oCurrent);
object oTempT3 = GetObjectByTag("x_t3m4", 0);
object oRealT3 = GetObjectByTag("t3m4", 0);
object oVima = GetObjectByTag("p_vimasunrider", 0);
RemoveAvailableNPC(7);
AddAvailableNPCByTemplate(7, "p_vimasunrider");
AssignCommand(oHost, SetGlobalFadeOut(0.0, 0.35, 0.0, 0.0, 0.0));
if (GetIsObjectValid(oTempT3)) {
AssignCommand(oHost, DelayCommand(0.40, DestroyObject(oTempT3)));
}
if (GetIsObjectValid(oRealT3)) {
AssignCommand(oHost, DelayCommand(0.40, DestroyObject(oRealT3)));
}
if (GetIsObjectValid(oVima) && oVima != oCurrent) {
AssignCommand(oHost, DelayCommand(0.40, DestroyObject(oVima)));
}
AssignCommand(oHost, DelayCommand(0.40, DestroyObject(oCurrent)));
AssignCommand(oHost, DelayCommand(0.45, SpawnSlot7(lSpot)));
AssignCommand(oHost, DelayCommand(0.80, SetGlobalFadeIn(0.0, 0.35, 0.0, 0.0, 0.0)));
}
================================================================================
Модим диалоги
Дальнейший шаг достаточно объёмный и уже не очень про NWScript, а больше про Python. Я не стал его описывать. Просто выполните в cmd:
python "D:\KOTOR_HANDMADE\tools\python\student_build_vima_t3_patch.py" --source-dir "D:\KOTOR_HANDMADE\01_original" --output-dir "D:\KOTOR_HANDMADE\04_build"
Этой командой мы добавим новые строки в диалоги. Пересобранные файлы уже лежат в `04_build`. Можете посмотреть результат так:
вима
python "D:\KOTOR_HANDMADE\tools\python\inspect_dlg_entries.py" "D:\KOTOR_HANDMADE\04_build\party_vima.dlg" 6 117 24
теперь т3
python "D:\KOTOR_HANDMADE\tools\python\inspect_dlg_entries.py" "D:\KOTOR_HANDMADE\04_build\k_htmd_dialog.dlg" 4
Финал
И самый последний и ответственный шаг: нам осталось скомпилировать свои `NSS` в `NCS`.
Надо перейти в папку компилятора
cd /d D:\KOTOR_HANDMADE\tools\nwnnsscomp
Скомпилировать первый скрипт
nwnnsscomp.exe "D:\KOTOR_HANDMADE\03_scripts\vima_call_t3.nss" -o "D:\KOTOR_HANDMADE\04_build\vima_call_t3.ncs"
Скомпилировать второй скрипт
nwnnsscomp.exe "D:\KOTOR_HANDMADE\03_scripts\t3_call_vima.nss" -o "D:\KOTOR_HANDMADE\04_build\t3_call_vima.ncs"
Теперь у нас почти всё готово для рабочего патча Т3/Вима. Нам осталось подготовить файл `availnpc7_t3.utc`; о том, как его подготовить, кому интересно, почитайте в `README` в этом каталоге `04_build`.
Если вы выполнили это руководство у вас уже есть готовые файлы в каталоге `04_build`.
фаил availnpc7_t3.utc я уже подготовил и положил в 04_build
gz gl hf
Получившиеся 5 файлов — это наш готовый патч. Переносим эти файлы в каталог `Override`, проверяем результат в игре.
P.S. Лирическое отступление.
Эта публикация является финальной в моей трилогии постов, посвящённых КОТОР; следующие публикации будут не скоро, если вообще суждено им появиться. Эти публикации — побочный продукт моих экспериментов над ресурсами игры. Эти публикации и темы не случайны: я специально выбрал два очень разных по структуре мода, для того чтобы посмотреть, как изменилась техника джедаев за 20 лет. Первая публикация, посвящённая моду Слехерон, — это прекрасный показатель того, как к КОТОР сегодня подходят модерн-программисты. Тут есть дисциплина в организации файлов, и это, в принципе, выглядит как масштабируемый проект. Мод Явин — он совершенно другой: это легаси из тех самых лет, когда не было нормального компилятора и Python не был таким, чтобы применять его так же легко, как в руководстве выше. Мод Явин впечатлил меня очень сильно; тот отпечаток, который оставили разработчики этого мода, показал мне изящные способы, которые имеют право на жизнь в крайне сложных ситуациях. Я надеюсь, следующие джедаи, которые придут в КОТОР, смогут сделать то, что не смогли мои предшественники, но я ещё не закончил. Моя реставрация Явина требует доработки, и этот мод я доделаю, чтобы оставить свой след в истории проекта, который создал из меня достаточно сильного джедая, который принимает вызовы и способен их решать!
олсо ~ Приглашаю всех на форум. Wolfryu21 оказывается делает сборку всех модов, как я уже говорил я удивлен тем, что над котором все еще кто-то работает. А удивляет меня в этой жизни только хорошее. Так что сабж достойный обсуждения готов - Нужен ли КОТОР 1 адекватный мод менеджер, и кто готов принять участие в подобном проекте?. чтобы решить максимально приемлемо, нужно мнение разных джедаев. Только ситхи все возводят в абсолют! а сегодняшние ситхи стадо овец, ситхов должно быть только двое, это вечная борьба за абсолютное доминирование, путем неприкрытого покорения. Ситхов тоже приглашаю, возмущение силы сегодня запредельно. в последнее время, чаще всего я вижу перед собой не джедаев и не ситхов, а лишь сгустки комплексов.