Way-файлы: различия между версиями
(Уточнение значения attr_a) |
|||
| (не показаны 2 промежуточные версии 1 участника) | |||
| Строка 13: | Строка 13: | ||
и размер полезной нагрузки в байтах: | и размер полезной нагрузки в байтах: | ||
| − | < | + | <pre> |
struct ChunkHeader { | struct ChunkHeader { | ||
char tag[4]; | char tag[4]; | ||
uint32_t size; // little-endian | uint32_t size; // little-endian | ||
}; | }; | ||
| − | </ | + | </pre> |
После полезной нагрузки добавляются нулевые байты до границы 4 байт. Размер | После полезной нагрузки добавляются нулевые байты до границы 4 байт. Размер | ||
чанка в заголовке не включает ни сам заголовок, ни это выравнивание. | чанка в заголовке не включает ни сам заголовок, ни это выравнивание. | ||
| − | < | + | <pre> |
padding = (4 - (size mod 4)) mod 4 | padding = (4 - (size mod 4)) mod 4 | ||
| − | </ | + | </pre> |
Все числа записываются в порядке байтов ''little-endian''. | Все числа записываются в порядке байтов ''little-endian''. | ||
| Строка 31: | Строка 31: | ||
Подтверждённое дерево чанков имеет следующий вид: | Подтверждённое дерево чанков имеет следующий вид: | ||
| − | < | + | <pre> |
WTWR | WTWR | ||
├── MNAM | ├── MNAM | ||
| Строка 39: | Строка 39: | ||
├── RNOD × N | ├── RNOD × N | ||
└── RSEG × N | └── RSEG × N | ||
| − | </ | + | </pre> |
{| class="wikitable" | {| class="wikitable" | ||
| Строка 66: | Строка 66: | ||
Контейнер <code>RNOD</code> состоит из трёх обязательных чанков: | Контейнер <code>RNOD</code> состоит из трёх обязательных чанков: | ||
| − | < | + | <pre> |
RNOD | RNOD | ||
├── NNAM | ├── NNAM | ||
├── POSN | ├── POSN | ||
└── FLAG | └── FLAG | ||
| − | </ | + | </pre> |
{| class="wikitable" | {| class="wikitable" | ||
| Строка 92: | Строка 92: | ||
обязательных чанков: | обязательных чанков: | ||
| − | < | + | <pre> |
RSEG | RSEG | ||
├── ATTR | ├── ATTR | ||
├── WDTH | ├── WDTH | ||
└── VDAT | └── VDAT | ||
| − | </ | + | </pre> |
=== ATTR === | === ATTR === | ||
| Строка 103: | Строка 103: | ||
<code>ATTR</code> всегда имеет размер 16 байт: | <code>ATTR</code> всегда имеет размер 16 байт: | ||
| − | < | + | <pre> |
struct SegmentAttributes { | struct SegmentAttributes { | ||
| − | uint32_t | + | uint32_t path_flags; |
double attr_value; | double attr_value; | ||
uint32_t attr_b; | uint32_t attr_b; | ||
}; // последовательная упаковка: <IdI | }; // последовательная упаковка: <IdI | ||
| − | </ | + | </pre> |
| − | В исследованных файлах встречаются <code> | + | path_flags - набор битовых флагов описывающих текущий сегмент. Приблизительные значения каждого флага: |
| + | {| class="wikitable" | ||
| + | ! Флаг !! Описание !! Где встречается | ||
| + | |- | ||
| + | | 00000001 || Строит Bezier кривую по <b>4</b> точкам || Большинство дорог | ||
| + | |- | ||
| + | | 00000010 || Строит путь по точкам || Часто встречается в Алмазном | ||
| + | |- | ||
| + | | 00000100 || Скрывает левую полосу || Односторонние разьезды на базах | ||
| + | |- | ||
| + | | 00001000 || Скрывает правую полосу || Односторонние разьезды на базах | ||
| + | |- | ||
| + | | 00010000 || Путь, который не отображается на миникарте || Невидимые заезды на СТО, заправки | ||
| + | |- | ||
| + | | 00100000 || Путь, который скрыт по умолчанию, но заполняется во время проезда || Скрытые срезки на карте(шахты, болото и т.д.) | ||
| + | |- | ||
| + | | 01000000 || Пути, где не спавнится трафик? || Встречается только в заброшенных шахтах | ||
| + | |} | ||
| + | |||
| + | В исследованных файлах встречаются <code>path_flags</code> со значениями 1, 2, 6, | ||
22, 34, 53, 57, 97 и 98; <code>attr_b</code> — 1, 2 и 3. Это наблюдаемые | 22, 34, 53, 57, 97 и 98; <code>attr_b</code> — 1, 2 и 3. Это наблюдаемые | ||
значения, а не расшифрованные типы дороги. | значения, а не расшифрованные типы дороги. | ||
| − | В частности, <code> | + | В частности, <code>path_flags = 98</code> нельзя однозначно считать тупиком: |
в разных картах он встречается как на коротких соединителях, так и на длинных | в разных картах он встречается как на коротких соединителях, так и на длинных | ||
цепочках. Автоматически менять этот атрибут без проверки в игре небезопасно. | цепочках. Автоматически менять этот атрибут без проверки в игре небезопасно. | ||
| Строка 123: | Строка 142: | ||
<code>WDTH</code> имеет размер 16 байт: | <code>WDTH</code> имеет размер 16 байт: | ||
| − | < | + | <pre> |
struct SegmentWidth { | struct SegmentWidth { | ||
double width_left; | double width_left; | ||
double width_right; | double width_right; | ||
}; | }; | ||
| − | </ | + | </pre> |
Обычно оба значения одинаковы: например, <code>3.0 / 3.0</code>, | Обычно оба значения одинаковы: например, <code>3.0 / 3.0</code>, | ||
| Строка 139: | Строка 158: | ||
<code>VDAT</code> содержит вершины полилинии: | <code>VDAT</code> содержит вершины полилинии: | ||
| − | < | + | <pre> |
struct VertexData { | struct VertexData { | ||
uint32_t count; | uint32_t count; | ||
struct { double x, y, z; } points[count]; | struct { double x, y, z; } points[count]; | ||
}; | }; | ||
| − | </ | + | </pre> |
Размер полезной нагрузки должен соответствовать формуле: | Размер полезной нагрузки должен соответствовать формуле: | ||
| − | < | + | <pre> |
VDAT.size = 4 + count × 24 | VDAT.size = 4 + count × 24 | ||
| − | </ | + | </pre> |
Начальная и конечная вершины часто совпадают с концами других сегментов и тем | Начальная и конечная вершины часто совпадают с концами других сегментов и тем | ||
| Строка 160: | Строка 179: | ||
Координаты точек и узлов хранятся как три <code>float64</code>: | Координаты точек и узлов хранятся как три <code>float64</code>: | ||
| − | < | + | <pre> |
X, Y, Z | X, Y, Z | ||
| − | </ | + | </pre> |
Для двумерного отображения обычно используются <code>X</code> и | Для двумерного отображения обычно используются <code>X</code> и | ||
| Строка 187: | Строка 206: | ||
Требуют дальнейшего исследования: | Требуют дальнейшего исследования: | ||
| − | * точная игровая роль полей | + | * точная игровая роль полей <code>attr_value</code> и <code>attr_b</code>; |
| − | |||
* значение <code>FLAG</code> у разных видов RNOD; | * значение <code>FLAG</code> у разных видов RNOD; | ||
* направление движения по массиву точек; | * направление движения по массиву точек; | ||
Текущая версия на 20:12, 26 июля 2026
WAY-файлы — бинарные файлы дорожной и маршрутной сети в игре Дальнобойщики 2 / Hard Truck 2: King of the Road. Обычно находятся в папке ENV и имеют имена, соответствующие участкам карты: например, aa.way, ab.way или da.way.
Файл хранит геометрию маршрутов в трёхмерных координатах, ширину сегментов, служебные узлы и набор атрибутов. Точная игровая семантика части атрибутов пока не установлена; ниже описана подтверждённая бинарная структура.
Содержание
Общая структура
Файл состоит из вложенных чанков. Каждый чанк имеет четырёхсимвольный ASCII-тег и размер полезной нагрузки в байтах:
struct ChunkHeader {
char tag[4];
uint32_t size; // little-endian
};
После полезной нагрузки добавляются нулевые байты до границы 4 байт. Размер чанка в заголовке не включает ни сам заголовок, ни это выравнивание.
padding = (4 - (size mod 4)) mod 4
Все числа записываются в порядке байтов little-endian.
Подтверждённое дерево чанков имеет следующий вид:
WTWR
├── MNAM
└── GDAT
└── GROM × N
├── RNAM
├── RNOD × N
└── RSEG × N
| Чанк | Назначение | Тип |
|---|---|---|
WTWR |
Корневой контейнер файла | контейнер |
MNAM |
Короткое имя карты, например aa |
строка с NUL в конце |
GDAT |
Данные дорожного графа | контейнер |
GROM |
Дорожная комната/группа сегментов | контейнер |
RNAM |
Имя комнаты | строка с NUL в конце |
RNOD |
Именованный служебный узел | контейнер |
RSEG |
Сегмент маршрута | контейнер |
Строки в исследованных файлах совместимы с ASCII и Windows-1251; при чтении
строка заканчивается на первом байте 00.
Узлы RNOD
Контейнер RNOD состоит из трёх обязательных чанков:
RNOD ├── NNAM ├── POSN └── FLAG
| Чанк | Размер | Содержимое |
|---|---|---|
NNAM |
переменный | имя узла или служебной позиции |
POSN |
24 байта | double x, double y, double z
|
FLAG |
4 байта | uint32 flag
|
Примеры имён: node_store_1000, pos_hidden_0100,
STO_AA. Встречаются значения FLAG 0 и 1, но их точное
значение для игровой логики не подтверждено.
Сегменты RSEG
Контейнер RSEG описывает одну полилинию и состоит из трёх
обязательных чанков:
RSEG ├── ATTR ├── WDTH └── VDAT
ATTR
ATTR всегда имеет размер 16 байт:
struct SegmentAttributes {
uint32_t path_flags;
double attr_value;
uint32_t attr_b;
}; // последовательная упаковка: <IdI
path_flags - набор битовых флагов описывающих текущий сегмент. Приблизительные значения каждого флага:
| Флаг | Описание | Где встречается |
|---|---|---|
| 00000001 | Строит Bezier кривую по 4 точкам | Большинство дорог |
| 00000010 | Строит путь по точкам | Часто встречается в Алмазном |
| 00000100 | Скрывает левую полосу | Односторонние разьезды на базах |
| 00001000 | Скрывает правую полосу | Односторонние разьезды на базах |
| 00010000 | Путь, который не отображается на миникарте | Невидимые заезды на СТО, заправки |
| 00100000 | Путь, который скрыт по умолчанию, но заполняется во время проезда | Скрытые срезки на карте(шахты, болото и т.д.) |
| 01000000 | Пути, где не спавнится трафик? | Встречается только в заброшенных шахтах |
В исследованных файлах встречаются path_flags со значениями 1, 2, 6,
22, 34, 53, 57, 97 и 98; attr_b — 1, 2 и 3. Это наблюдаемые
значения, а не расшифрованные типы дороги.
В частности, path_flags = 98 нельзя однозначно считать тупиком:
в разных картах он встречается как на коротких соединителях, так и на длинных
цепочках. Автоматически менять этот атрибут без проверки в игре небезопасно.
WDTH
WDTH имеет размер 16 байт:
struct SegmentWidth {
double width_left;
double width_right;
};
Обычно оба значения одинаковы: например, 3.0 / 3.0,
4.0 / 4.0 или 8.0 / 8.0. Вероятнее всего, это ширина
слева и справа от осевой линии сегмента, однако это ещё не подтверждено
исходным кодом игры.
VDAT
VDAT содержит вершины полилинии:
struct VertexData {
uint32_t count;
struct { double x, y, z; } points[count];
};
Размер полезной нагрузки должен соответствовать формуле:
VDAT.size = 4 + count × 24
Начальная и конечная вершины часто совпадают с концами других сегментов и тем самым задают геометрические связи маршрута. Удаление или перенос этих точек может разорвать дорожную сеть.
Координаты
Координаты точек и узлов хранятся как три float64:
X, Y, Z
Для двумерного отображения обычно используются X и
-Y, поскольку в SVG и на экране ось Y направлена вниз. Координата
Z соответствует высоте.
Безопасное редактирование
При записи WAY-файла необходимо:
- сохранять порядок чанков и неизвестные чанки без изменений;
- пересчитывать размеры изменённых чанков и их контейнеров;
- сохранять выравнивание до 4 байт;
- записывать числа в little-endian;
- завершать строки нулевым байтом;
- создавать резервную копию исходного файла;
- после записи повторно разобрать файл и проверить структуру.
Для файла без изменений корректный сериализатор должен давать побайтно тот же результат, что и исходный файл.
Неизвестные части формата
Требуют дальнейшего исследования:
- точная игровая роль полей
attr_valueиattr_b; - значение
FLAGу разных видов RNOD; - направление движения по массиву точек;
- односторонность, полосы движения и скрытые ссылки между сегментами;
- безопасное добавление и удаление RSEG без изменения других ресурсов игры.
Утилиты
Для просмотра и аккуратного редактирования формата существует
HT2 WAY Tool. Утилита поддерживает
просмотр структуры, экспорт JSON/SVG/CSV, резервные копии и проверку сегментов
с attr_a = 98.