Привет, модостроители!!! Наверное, создавая моды, вы когда-нибудь сталкивались с созданием новых врат (типов), вдобавок к оригинальным 25 типам врат. Но всегда вы видели весьма странный значок на всех новых вратах - "Х" - и также загадочные "???" перед названием ваших новых врат, ну и, конечно, Readtext в поле серийного номера.
В этом уроке я расскажу, как создать и корректно "внедрить" новые типы врат.
Инструментарий для работы:*
Знание Х3 Editor 2 обязательно!Необходимые файлы для работы:- Ваши новые модели врат и их сцены.
- TGates
- IconTypes
- L001-007
- x3story.obj
- x3intro.obj
Все готовы? Вперед!!!
Этап 1: Создание строк врат в файле TGates.
Открываем Х3 Editor 2 и ищем
TGates (он находится в 07. сат\types). Создаём новый каталог, называем его 14 (дат тоже, кстати). Копируем в наш архив, открываем. Вот главные элементы окна TGates:

- Номер и имя врат в списке.
- Идентификатор (ID) - очень важная часть строки врат.
- Субтип - он всегда равен "-1", (об этом чуть дальше).
- Номер строчки в языковом файле, где находится имя.
- Путь к сцене врат.
Все остальные поля без изменений.
- Копируем любую строчку правой кнопкой мыши и выбираем "Paste to end". Копируем 4 раза, так как врата имеют направление на 4 стороны: север, юг, запад, восток. ( ХАБовские врата специальные!)
- Ставим свои идентификаторы. Идентификатор имеет такой вид: SS_WG_ваше_уникальное_имя_NORTH, ..._SOUTH, ..._WEST и ..._EAST
- Дописываем в языковой файл имя своих врат, ставим сюда номер вашей строки или же используем стандартное имя (3731).
- Прописываем путь к сцене новых врат. Формат пути для примера: others\ваше_имя_scene .
- Сохраняем файл и закрываем редактор. Потом заново запускаем. Я делаю это для того, чтобы новые элементы заняли свои места нормально, хотя, может, это мой прикол...
Этап 2: Установка значков (иконок).
Все новые добавленные типы врат имеют весьма странный значок (иконку) -
"Х". Кстати, именно новые Земные врата с такой иконкой. Текущая иконка нас не устраивает, поэтому нужно всем новым типам врат установить нормальные иконки, соответствующие направлению врат, а именно:
N, S, W, E.
Для этого нужно дописать идентификаторы (ID) новых типов врат в файл
IconTypes. Берём его из 03.сат\types, копируем и переносим в наш архив. Открываем
IconTypes и листаем до тех пор, пока не найдем вот такую конструкцию:

- Название раздела - соответственно, в этом разделе прописываются значки типам врат.
- Общее количество прописанных типов врат - идентификаторов (ID).
- Весь список строк, которые хранятся в этом разделе.
1) Прописываем в конец строк свои 4 строки вот так:
- SS_WG_имя_NORTH;ICON_TRG_GATE_N;0;0;
- SS_WG_имя_SOUTH;ICON_TRG_GATE_S;0;0;
- SS_WG_имя_WEST;ICON_TRG_GATE_W;0;0;
- SS_WG_имя_EAST;ICON_TRG_GATE_E;0;0;
2) Увеличиваем общее число строк в разделе SSTYPE_WARPGATE; на 4 , так как мы добавили только 4 новых строки.
- SSTYPE_WARPGATE;
- ICON_TRG_GATE_X;0;0;
- 0;0;0;
- [b]18[/b];
Полная конструкция должна получиться вот такая:
- SSTYPE_WARPGATE;
- ICON_TRG_GATE_X;0;0;
- 0;0;0;
- 18;
- SS_WG_NORTH;ICON_TRG_GATE_N;0;0;
- SS_WG_SOUTH;ICON_TRG_GATE_S;0;0;
- SS_WG_WEST;ICON_TRG_GATE_W;0;0;
- SS_WG_EAST;ICON_TRG_GATE_E;0;0;
- SS_WG_T_NORTH;ICON_TRG_GATE_N;0;0;
- SS_WG_T_SOUTH;ICON_TRG_GATE_S;0;0;
- SS_WG_T_WEST;ICON_TRG_GATE_W;0;0;
- SS_WG_T_EAST;ICON_TRG_GATE_E;0;0;
- SS_WG_HUB_NORTH;ICON_TRG_GATE_CRC1;0;0;
- SS_WG_HUB_SOUTH;ICON_TRG_GATE_CRC2;0;0;
- SS_WG_HUB_WEST;ICON_TRG_GATE_SQR1;0;0;
- SS_WG_HUB_EAST;ICON_TRG_GATE_SQR2;0;0;
- SS_WG_HUB_UP;ICON_TRG_GATE_TRI1;0;0;
- SS_WG_HUB_DOWN;ICON_TRG_GATE_TRI2;0;0;
- SS_WG_имя_NORTH;ICON_TRG_GATE_N;0;0;
- SS_WG_имя_SOUTH;ICON_TRG_GATE_S;0;0;
- SS_WG_имя_WEST;ICON_TRG_GATE_W;0;0;
- SS_WG_имя_EAST;ICON_TRG_GATE_E;0;0;
Сохраняем файл и закрываем редактор.
Этап 3: Исправление Readtext в серийном номере новых врат.
После создания новых врат может появиться Readtext в серийном номере. Увидеть это можно только включив игру и соединив новые врата. Если все-таки вместо первых двух букв серийного номера присутствует Readtext (
Readtext-1263-строка необходимая игре серийном номере новых врат), это означает, что не загружена строка на странице
1263 "Shipclass IDs" и ее нужно создать.

- Страница 1263 "Shipclass IDs"
- Строки на этой странице.
Для устранения этой проблемы нужно выполнить несколько действий:
- Открываем с помощью Х3 Editor 2 языковый файл L001-007.
- Прокручиваем список и находим страницу 1263 "Shipclass IDs".
- Создаем новую строку с номером тем, что требует игра. Возможно, нужно будет создать несколько таких строк.
Сохраняем и закрываем Х3 Editor 2. Больше он нам не понадобится.
Этап 4: Правка x3story.obj - прописывание новых типов врат.
Итак, мы подошли к предпоследнему и очень важному этапу. Править
x3story.obj мы будем WordPadoм, предварительно дизассемблировав его. Делаем вот так:
- Качаем Ассемблер и Дизассемблер
- Создаем отдельную для удобства папку с произвольным именем, я назвал "OBJ".
- В ней создадим ещё две папки с понятными названиями: COMPILE и DECOMPILE (названия произвольные, лишь бы вам понятно было).
- В папку COMPILE распаковываем архив с ассемблером (xa4_10b_824.zip) в папку DECOMPILE - дизассемблер (do4_13b_122.zip).
- Достаем самый свежий x3story.obj версии 3.1, находящися в 13.сат\.
- В папке DECOMPILE берем и тащим x3story.obj на dobj.exe и ждем, пока обж будет декомпилирован.
- После декомпиляции в этой папке получается много файлов, нас же интересует файл x3story.asm, открываем его WordPadoм.
- Теперь нам нужно найти функции, которые отвечают за типы врат. Вбиваем в поиск первую функцию:
- [b]function GATE.GetDirectionName()[/b]
WordPad находит секцию с именем: GetDirectionName, листаем немного вниз. Нас интересует длинный список команд:
- L00086379: xjump 25d, 0
- .long L00086373 ; 0 : default
- .long L00086337 ; 1 : 0
- .long L00086343 ; 2 : 1
- .long L0008634F ; 3 : 2
- .long L0008635B ; 4 : 3
- .long L00086373 ; 5 : 4
- .long L00086337 ; 6 : 5
- .long L00086343 ; 7 : 6
- .long L0008634F ; 8 : 7
- .long L0008635B ; 9 : 8
- .long L00086367 ; 10 : 9
- .long L00086367 ; 11 : 10
- .long L00086367 ; 12 : 11
- .long L00086367 ; 13 : 12
- .long L00086367 ; 14 : 13
- .long L00086367 ; 15 : 14
- .long L00086367 ; 16 : 15
- .long L00086367 ; 17 : 16
- .long L00086367 ; 18 : 17
- .long L00086367 ; 19 : 18
- .long L00086367 ; 20 : 19
- .long L00086367 ; 21 : 20
- .long L00086337 ; 22 : 21
- .long L00086343 ; 23 : 22
- .long L0008635B ; 24 : 23
- .long L0008634F ; 25 : 24
Сверху - 25d - это общее число прописанных адресов (типов врат). На данный момент их 25. Увеличиваем это число на 4, то есть должно выйти:
Дальше переходим к самим командам. Обратите внимание на запись цифр после каждого адреса вида L00086ХХ. Первая цифра - это номер врат по порядку в TGates, вторая - субтип. Я раньше говорил про Субтип врат и что он равен -1. Вот вторая цифра и означет "номер врат -1". Для прописывания своих типов врат копируем эти строки в конец:
- .long L00086337 ; 1 : 0
- .long L00086343 ; 2 : 1
- .long L0008634F ; 3 : 2
- .long L0008635B ; 4 : 3
и меняем вот так:
- .long L00086337 ; 26 : 25
- .long L00086343 ; 27 : 26
- .long L0008634F ; 28 : 27
- .long L0008635B ; 29 : 28
В результате выходит код с 29 строками:
- L00086379: xjump 29d, 0
- .long L00086373 ; 0 : default
- .long L00086337 ; 1 : 0
- .long L00086343 ; 2 : 1
- .long L0008634F ; 3 : 2
- .long L0008635B ; 4 : 3
- .long L00086373 ; 5 : 4
- .long L00086337 ; 6 : 5
- .long L00086343 ; 7 : 6
- .long L0008634F ; 8 : 7
- .long L0008635B ; 9 : 8
- .long L00086367 ; 10 : 9
- .long L00086367 ; 11 : 10
- .long L00086367 ; 12 : 11
- .long L00086367 ; 13 : 12
- .long L00086367 ; 14 : 13
- .long L00086367 ; 15 : 14
- .long L00086367 ; 16 : 15
- .long L00086367 ; 17 : 16
- .long L00086367 ; 18 : 17
- .long L00086367 ; 19 : 18
- .long L00086367 ; 20 : 19
- .long L00086367 ; 21 : 20
- .long L00086337 ; 22 : 21
- .long L00086343 ; 23 : 22
- .long L0008635B ; 24 : 23
- .long L0008634F ; 25 : 24
- .long L00086337 ; 26 : 25
- .long L00086343 ; 27 : 26
- .long L0008634F ; 28 : 27
- .long L0008635B ; 29 : 28
- Следующая на очереди функция. Вбиваем в поиск вот эту функцию:
- [b]function GATE.GetDirectionFromSubtype()[/b]
WordPad находит секцию с именем: GetDirectionFromSubtype. В этой секции сделать так же, как в пункте 8! Единственное, тут другие адреса, но также брать вот эти:
- .long L000864C7 ; 1 : 0
- .long L000864C9 ; 2 : 1
- .long L000864CB ; 3 : 2
- .long L000864CD ; 4 : 3
- Последнее, что нужно править в x3story.obj - это версию. Просто при любой компиляции .obj файла версия игры будет "?". Это происходит, если вы начнете новую игру, сохранитесь и захотите загрузить эту сохранку. Тем более, вам по-любому придётся начать заново, ведь имена назначения врат записываются в сохранения - старые сохрания больше не поддерживаются!
Итак, вносим в поиск эту функцию:
- [b]function GetVersionString(arg1)[/b]
попадаем в секцию
GetVersionString - здесь можно увидеть все версии, которые были пропатчены до версии 3.1. Листаем в конец списка, нужно найти вот этот кусочек:
- L00000D68: pushw 3600d ; 0E10h
- if SP[0]<=SP[1] then push 0 else push 1
- if SP[0]=0 then jump L00000D77
- get_strg S0001B993 ; "v3.1"
- ret
- L00000D77: get_strg S0000055B ; "?"
- ret
- ; push 0
- ; ret
Менять нужно самую последнюю строчку:
- L00000D77: get_strg S0000055B ; "?"
Нужно скопировать адрес строки версии 3.1 ("v3.1") и вставить вместо адреса строки для неизвестной версии ("?"), вот так:
- L00000D68: pushw 3600d ; 0E10h
- if SP[0]<=SP[1] then push 0 else push 1
- if SP[0]=0 then jump L00000D77
- get_strg S0001B993 ; "v3.1"
- ret
- L00000D77: get_strg [i][b]S0001B993[/b][/i] ; "?"
- ret
- ; push 0
- ; ret
Далее, после всех операций, сохраняем наш
asm файл.
Правка
x3story.obj успешно завершена, можете его компилить, перетащив
x3story.asm на асемблер
xa_asm.exe, ждем компиляции. Если вы не сделали ошибок при правке
x3story.asm, то в папке с асемблером появится файлик с именем:
x3story.cod, теперь смело меняем расширение файла
.cod на
.obj. Все, новый
x3story.obj у вас есть, можете его переместить в ваш модархив.
Этап 5: Правка x3intro.obj - установка соотвествия значений версий игры.
Это последний этап даного урока, идентичный последнему пункту из этапа 4. Чтобы версия игры правильно отображалась, мало изменить адрес строки версии в
x3story.obj. Необходимо, чтобы строки версии
x3story.obj и
x3intro.obj совпадали, иначе вместо версии 3.1 так и останется "?".
1) Дизассемблируем
x3intro.obj так же как и
x3story.obj. Открываем WordPadом и вписываем в поиск уже знакомую функцию:
- [b]function GetVersionString(arg1)[/b]
Снова находим кусочек кода:
- L00002B7D: pushw 3600d ; 0E10h
- if SP[0]<=SP[1] then push 0 else push 1
- if SP[0]=0 then jump L00002B8C
- get_strg S00000AD2 ; "v3.1"
- ret
- L00002B8C: get_strg S00000AD7 ; "?"
- ret
- ; push 0
- ; ret
Меняем адрес к строке версии, должно выглядеть вот так:
- [code]L00002B7D: pushw 3600d ; 0E10h
- if SP[0]<=SP[1] then push 0 else push 1
- if SP[0]=0 then jump L00002B8C
- get_strg S00000AD2 ; "v3.1"
- ret
- L00002B8C: get_strg [i][b]S00000AD2[/b][/i] ; "?"
- ret
- ; push 0
- ; ret
Сохраняем
asm файл. Компилируем точно так же, как и
x3story.asm и меняем расширение
.cod на
.obj ,
x3intro.obj - успешно изменён.