User Tools

Site Tools


kg:doc_discoc_universe

Спецификация игровых миров

Ландшафт

Размер и упаковка

Определения

Пространства: вершины и экран

Отображение этих двух пространств друг в друга искажает углы. Так, переход из вершин на экран, описывается матрицей вида: <note tip> ( 48, 24 )
(0, 30)</note> И обратное: <note tip> ( 1/48, -1/24 )
(0, 1/30)</note>

Ромбы и квадраты

Квадрат, нарисованный в одном пространстве, в другом отображается как ромб (параллелограмм). Например, прямоугольная область пространства вершин, если двигаться строго сверху-вниз, на экране будет ощутимо уползать влево. Если же вести ровно пальцем по экрану сверху-вниз, то прообраз пальца в пространстве вершин будет двигаться вниз-вправо.

Избыточный прямоугольник ландшафта (ИПЛ)

 Так как нам удобнее всегда работать с прямоугольниками, а пляшем мы всё-таки от экранного представления ландшафта, то что бы в пространстве вершин стало всё хорошо, нужно прообраз прямоугольного ландшафта, ставший в пространстве вершин ромбом, дополнить уголками слева и справа, что бы он там был прямоугольным. Эти лишние уголки на экране просто не показываются, можно их не хранить вообще нигде, но считать что как бы пространство вершин их содержит.

Такой прямоугольник в пространстве вершин, имеет избыточность порядка +50% относительно реально нужной площали, и квадратный мир в виде вершин может состоять из прямоугольника с соотношением сторон почти равным 3/2.

Живые и мёртвые точки

Избыточный прямоугольник потому и избыточный - что не все его точки нам нужны. Те точки пространства вершин, которые попадают внутрь нужной нам области ландшафта, называем “живыми”, остальные - “мёртвыми”. Вообще говоря, эти вопросы являются лишь проблемой генератора - именно он должен заботиться о том, что бы суша располагалась только в “живой” области, а “мёртвая” не должна содержать ничего интересного, так как клиент её просто физически не способен отрисовать.

Полу-живые точки

На них можно строить чанки, однако клиент их отобразить всё равно не сможет. появились из-за того, что пограничные чанки ландшафта иногда располагаются прямо на границе разрешенной к отображению области, то есть граница “живого” и “мёртвого” проходит посреди чанка, а резать его не хочется.

Реальная площадь ландшафта

Важный параметр - количество суши в ландшафте. Считается простой суммой вершин, со значением высоты не равной константе “дно морское”. Отсюда видно, что вершины под водой, но выше дна являются паразитами - отъедают ресурсы от реальной суши, потому желательно их сделать немногочисленными. Тривиальное решение ограничить “дно” значением -1 не подходит, так как выровняет везде угол ухода суши под воду. Подробнее об этом в разделе “море и берег”

Зона выхода

Часть океана вокруг ландшафта (мира), откуда мы разрешим корабликам уплывать в другие миры. Обязательно должна быть связной, то есть полностью содержать в себе всю сушу ландшафта.

Как работать с таким странным пространством

Главная наша функция показывает, с какого горизонтального индекса начинается и заканчивется строка “живых и полу-живых” вертексов в “избыточном” пространстве: <note tip>xmin(y) = ( (y - 1 ) / 2D ) * D
xmax(y) = ( y / 2D ) * D + length</note> где D - диаметр чанка в вершинах, а length = ширина чанкуемого ландшафта в вершинах Если не заметили, не все строки “живых” вершин равны по длине. Почему так - должно быть видно на рисунке.

Всё довольно просто: метрика всем уже исвестна, а вот и формулы определяющие принадлежность точки (x,y) к “живым и полу-живым” вершинам: <note tip>y >= 0 && y < height
&&
x >= xmin(y) && x < xmax(y)</note>

только не забывайте что вершин на одну больше чем фрагментов, и если у вас 1024 фрагмента, то нужно включить вершину с индексом [1024], ведь вершин у вас 1025 штук.

Важно: вообще это всё головная боль генератора - именно он должен обеспечить, что будут использованы только “живые” точки, и все нужные “зоны переходов” будут там где надо. Клиенту можно поступить проще - загрузить данные с сервера прямо в избыточный массив вершин, и строить чанки тупо циклом.

Тоже важно: такие вольности, как треть сусорных вершин в буфере допустимы потому, что всё равно в них мусор. Когда таскать мусор надоест, можно переписать код и не слать их. Но вообще-то обычный алгоритм архивации сделает это за нас, так как он мастер находить нулевые последовательности в строках

Чанки в "полном пространстве"

 Чанки повторяют по форме треугольники, только крупнее. И так же как и треугольники, мы их разделим на “красные” и “зелёные”. Что бы не мучаться, будем работать сразу с парами чанков, “кр+зел”, исключив случаи когда у кого-то нет пары. Правда цена тому - несколько однозначно невидимых никогда чанков на левой и правой границе области… ну и чёрт с ними!

Размеры областей

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

  1. видимый мир должен вписываться в квадрат 2048х2048 (фрагментов), что даёт 2049х2049 вершин. С неровным числом 2n+1 вершин можно что-то сделать, и вопрос - нужно ли остаётся открытым.
  2. ИПЛ максимального (2049^2 вершин) мира имеет размер 3073х2048 вершин
  3. площадь суши должна быть примерно равна половине полной площади, то есть, если сушу аккуратно нарезать и сложить в прямоугольник, он будет равен 2048х1024 (2Кх1К) фрагментов.
  4. суша не должна приближаться к границе полного квадрата ближе чем на определённую величину, порядка 20 вершин

Первое условие вводится по большей части для удобства. Так как нам никто не мешает вытянуть ландшафт в длинную колбаску или бублик, теоретически, полный квадрат ландшафта может быть и не квадрат.. однако что бы упростить себе жизнь - на построении минимапов, и в многих других мелочах, будем использовать это жёсткое ограничение. Так же важно, что из-за кривой (параллелограмм) координатной сетки вертексов в мире, можно работать с прямоугольником 3Кх2К в пространстве вершин, от которого потом будут оттяпаны углы, как показано на рисунке справа.

Второе условие может строго не соблюдаться, однако большие отклонения в любую сторону от указанной цифры нежелательны. Ландшафт лучше пакуется, когда в нём больше моря, да и балансируется игра так что бы на каждого игрока приходилось определённое количество суши, и не хочется выяснять, как заклинит баланс, если суши не хватит или будет слишком много.

Третье условие должно выполняться потому, что во-первых, нужно каждый мир окружить водой - что бы в него с любой стороны можно было приплыть. Во-вторых, надо как-то отображать край карты на клиенте, и легче это сделать когда узкая полоса на границе (которая у нас рваная) отдана под мёртвую зону,и скроллинг туда невозможен.

Как можно схитрить с лишними вершинами

Так как мы пренебрегаем краем ландшафта, и там у нас гарантированно вода, то ландшафт можно незаметно зациклить и горизонтально и вертикально, что сделает количество фрагментов и вершин равным. И вершин станет “хорошее число”. Однако на клиенте при построении геометрии придётся использовать деление по модулю… а оно нам надо?

Моря и берега

<note important>С версии от 4.12.2011, подводными треугольниками можно пренебречь. Однако вопрос ещё не закрыт - можно поэкспериментировать с водой</note>

Сейчас моря реализованы так: если треугольник ландшафта имеет хоть одну точку ниже уровня 0, рисуется треугольник лежащий ровно на уровне 0, и выглядящий как синяя блямба. Запрещены треугольники, с гранями по разные стороны высоты 0. Из этого однозначно следует, что уровень моря (высота 0) весь представлен сплошной изо-линией, что можно уже увидеть в текущих версиях клиента.

Модификаторы

Алгоритм

Серевер обрабатывает модификаторы текстур в развёрнутом виде - ему так удобно. Клиенту же нужен только результат - то есть какой вариант текстурирования применить. Общий вид алгоритма:

  1. Имеем на сервере развёрнутую структуру модификатора (MODS):
    1. GRASS - целое, значения [0..3], где:
      1. 0 == нет травы
      2. 1 == 33% травы
      3. 2 == 66% травы
      4. 3 == сплошная трава
    2. SNOW - целое, “заснеженность”, значения [0..2]:
      1. 0 == эффект отсутствует
      2. 1 == 50% заснеженность
      3. 2 == полная заснеженность
    3. BURNED - целое, выжженость земли, значения [0..2]:
      1. 0 == эффект отсутствует
      2. 1 == 50% выжженость
      3. 2 == полная выжженость
  2. обрабатываем модификаторы на сервере, используя правила:
    1. если температура ниже 0 - включаем снег на 50%
    2. если температура ниже -10 - включаем снег по полной
    3. если температура выше 10(константа будет тюниться) - включаем GRASS-1
    4. если ещё выше - GRASS-2
    5. если стоит здание - вытаптываем траву, GRASS-0
    6. (и так далее, алгоритм может меняться и зависеть от многих параметров)
  3. выбираем самый значащий модификатор и превращаем в индекс в диапазоне [0..7], понятный клиенту:
    1. если “выжжено” больше 0, - результат [6 или 7]
    2. иначе, если “снег” больше 0 - результат [4 или 5]
    3. иначе возвращаем значение GRASS, результат [0, 1, 2, 3]

Правило: MODS.BURNED > MODS.SNOW > MODS.GRASS То есть, когда включается BURNED не важно уже что там в остальных полях, клиенту по крайней мере.

Формат модели модификаторов сервера
struct modifiers {
  int2 grass;
  int2 snow;
  int2 burned;
}
assert( grass >= 0 && grass < 4 )
assert( snow >= 0 && snow < 3 )
assert( burned >= 0 && burned < 3 )
Таблица значений модификатора (клиент)
ID Name
0 DEFAULT
1 GRASS1
2 GRASS2
3 GRASS3
4 SNOW1
5 SNOW2
6 BURNED1
7 BURNED2
Таблица текстур
Базовый тип name ID нет модиф. слабая трава сильная трава полная трава слабый снег полный снег слабо выжжено полностью выжжено
DEFAULT GRASS-1 GRASS-2 GRASS-3 SNOW-1 SNOW-2 BURNED-1 BURNED-2
полный декоратор –/– –/– –/– –/– –/– decor.grass –/– decor.snow –/– decor.burned
Дно моря BOTTOM 0 bottom.default bottom.default bottom.default bottom.default bottom.snowWeak bottom.snowWeak bottom.default bottom.default
Скала CLIFF 1 cliff.default cliff.grassWeak cliff.grassWeak cliff.grassWeak cliff.snowWeak cliff.snowHard cliff.burnedWeak decor.burned
Каменистый STONE 2 stone.default stone.grassWeak stone.grassMed stone.grassMed stone.snowWeak decor.snow stone.burnedWeak decor.burned
Сухой грунт DRY 3 dry.default dry.grassWeak dry.grassMed decor.grass dry.snowWeak decor.snow dry.burnedWeak decor.burned
Мягкий грунт SOFT 4 soft.default soft.grassWeak soft.grassMed decor.grass soft.snowWeak decor.snow soft.burnedWeak decor.burned
Грязь(болото) DIRT 5 dirt.default dirt.grassMed dirt.grassMed dirt.grassMed dirt.snowWeak decor.snow dirt.burnedWeak decor.burned
Песок SAND 6 sand.default sand.default sand.default sand.grassHard sand.snowWeak sand.snowWeak sand.default sand.burnedHard

Комментарии к таблице:

  • “STONE” используется для более-менее ровных поверхностей, горы же надо заливать “CLIFF”
Альтерации текстур

Каждая текстура в сете имеет “альтерации”, то есть набор текстур с одним именем, и дополнительным расширением (цифра). Например, текстуры snow.png нет. Есть только текстуры snow.0.png или snow.1.png

При отрисовке номер альтерации берётся из константы вершины “номер альтерации”

Выбор текстуры

Итак, зная базовую текстуру и набор модификаторов, выбрав из модификатор один с максимальным приоритетом, получаем из таблицы текстуру. Там три варианта:

  1. В таблице прочерк : это значит у нас бага, сервак что-то не то выдал. Можно отрисовать базовую текстуру (умолчание)данной местности, как будто модификаторы нулевые и не забываем альтерацию, например: dry.0.png
  2. В таблице *модификатор*, например *snow* : Рисуем тупо текстуру с именем SHOW, выбирая нужную альтерацию snow.0.png или snow.1.png
  3. В таблице имя.текстуры, например stone.barren : Рисуем ту текстуру, учитывая альтерацию, например stone.tramp.1.png

Статические данные хранят базовый тип и альтерацию. Это три бита + 1 бит:

T A S type filename
0 0 0 BOTTOM bottom.default.0.png
1 8 bottom.default.1.png
1 0 1 CLIFF cliff.default.0.png
1 9 cliff.default.1.png
2 0 2 STONE stone.default.0.png
1 10 stone.default.1.png
3 0 3 DRY dry.default.0.png
1 11 dry.default.1.png
4 0 4 SOFT soft.default.0.png
1 12 soft.default.1.png
5 0 5 DIRT dirt.default.0.png
1 13 dirt.default.1.png
6 0 6 SAND sand.default.0.png
1 14 sand.default.1.png

Декораторы (новый лес)

Начиная с 4 декабря, в динамические данные ландшафта засунули целый байт, отвечающий за “декоратор” данной точки. Частным случаем декораторов являются “ресурсные точки”, деревья - так же частный случай декоратора. Особо нервных просьба не паниковать, размер вершины не вырос и остался равным 16 бит. Из динамики неё выброшены четыре бита, отвечавшие за деревья, и мы по-прежнему даже имеем резерв для дополнительных высот или чего ещё.

Вообще, декораторы угодили в динамические объекты неспроста: их свойства никак не позволяют отнести их к статике, а как полноценные объекты их реализовывать не очень эффективно - не думаю что нам нужен “лишний” список из сотни тысяч объектов, и каждый с позицией в 8 байт. В лучае подселения декораторов в вершины мы эти самые 100.000 * 8 байт и сэкономим.

Свойства декораторов

  1. В каждой вершине может быть не более одного декоратора
  2. Декоратор может быть проходимым или непроходимым.
  3. Любой декоратор может быть уничтожен игроками. Проходимые уничтожаются бесплатно, сразу и автоматически.
  4. Совместно со зданиями в одной вершине декораторам существовать запрещено. Проходимые пропадают сразу, непроходимые нужно уничтожить.

Типы декораторов

Декораторы могут быть такими:

  1. Нету (значение 0)
  2. Ничего не значащие проходимые фиговины + резерв(значения 1-47)
  3. Проходимые ресурсы (48-63)
  4. “Мусорные” деревья (значения 64-127)
  5. Ничего не значащие непроходимые фиговины (128-171)
  6. Непроходимые ресурсы (176 - 255)

То есть через всё у чего индекс меньше 64 перелезть можно.. этот факт может прмочь при построении карты проходимости местности на клиенте *Внимание* деревья ,как ресурсы разбежались в две группы: “мусорные деревья” и пробрались в группу “непроходимые ресурсы”. Это неслучайно: нам нельзя засаживать ценными породами деревьев всю карту, и лысой её держать не хочется. Потому, “мусорные деревья” поставляют базовую “древесину”, а всё что лучше неё - редкие вкрапления декораторов из группы “непроходимые ресурсы”.

Вариации

Исключительно в декоративных целях, можно отрисовывать один и тот же декоратор в разных вариантах. Дла этого мы когда-то ввели в статическую часть вертекса параметр “номер набора декораторов”. Те декораторы, которым вариации не нужны, могут игнорировать этот параметр - ничего страшного, лежит, не мешает себе. Сейчас допустимое число вариаций для каждого декоратора должно нацело делиться на 16 и быть не больше 16.

Жизненный цикл

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

Деревья
Пшеница, коровы и Ко
Ресурсные точки
Разломы, гейзеры и прочие штуковины

Работа с игровой картой

Алгоритм работы

  1. Генератор создаёт карту, сохранив файлы ландшафта в шаблонном состоянии
  2. Сервер начинает работу:
    1. загружает карту
    2. если карта в шаблонном состоянии:
      1. финализирует карту
      2. сохраняет карту в рабочем состоянии
      3. прекращает работу
    3. иначе, если карта в рабочем состоянии:
      1. перейти к “сервер работает”
  3. Сервер работает:
    1. модифицирует карту
    2. иногда сохраняет карту
    3. иногда делает сброс карты в шаблонное состояние (для тестирования)
      1. удаляет все данные кроме шаблонных
      2. прекращает работу

Примечания:

  1. Сервер сам финализирует свежесозданную карту. Делается это для того, что бы сервер имел монополию на игровой код, например, на функцию “развить город”. Алгоритм действий по финализации карты приводится ниже. Из этого следуют частные решения:
    1. начальное состояние модификаторов карты убрано из генератора и создаётся сервером на основе карты климата
    2. города НПЦ расставляются и развиваются до начального игрового состояния самостоятельно сервером

Формат данных карты

  • Генератор создаёт карту в шаблонном состоянии:
    • Финальные данные для клиента (read-only):
      • client.const.landscape.binary - некомпрессированные статические данные карты
      • client.const.minimap.binary - некомпрессированная миникарта (картинка)
    • Финальные данные для сервера (read-only):
      • world.config - текстовый файл, содержащий минимальную информацию по карте
      • server.const.analytics.binary - набор непакованных массивов данных, вроде списков точек для появления городов, локаций НПЦ и так далее
      • server.const.landscape.binary - непакованный полный прямоугольник, содержащий в набор вершинной информации, актуальной для сервера
  • Сервер создаёт и далее модифицирует (переписывает) данные по результатам своей работы:
    • server.state.landscape.binary - для простоты, сохраняем в один файл всё состояние карты
  • Сервер сохраняет для клиента:
    • client.const.landscape.z - компрессированный вариант client.const.landscape.binary
    • client.state.landscape.z - компрессированная динамика ланда
    • (кусочки) динамической части карты, передаваемые пакетами

Форматы файлов

Все одномерные массивы содержатся в формате: {n, [data]}, а двумерные массивы в виде {x,y,[data]}, где:

  • n - размер массива (int32)
  • x,y - размеры двумерного массива (int32, int32)
  • [data] - данные массива без разделителей
cleint.const.landscape.binary

Серверу запрещено использовать этот файл, необходимые данные для работы сервера, содержащиеся в этом файле, дублируются в других местах. Файл содержит двумерный массив структур по 16 бит каждая:

  • высота, 8 бит, беззнаковая (реально используются младшие 6 бит)
  • вариация декоратора, 4 бита, беззнаковая
  • альтерация текстуры, 1 бит (угадайте, знаковая или беззнаковая?)
  • тип поверхности, 3 бита, беззнаковый:
    • BOTTOM == 0
    • CLIFF == 1
    • STONE == 2
    • DRY == 3
    • SOFT == 4
    • DIRT == 5
    • SAND == 6
    • резерв == 7 (пока запрещаем использовать)
client.const.minimap.binary

Серверу запрещено заглядывать внутрь этого файла Здесь записана информация по миникарте, в формате, о котором надо спрашивать у Coolaceum'а

world.config

Формат файла может меняться. На данный момент это текстовый файл, который выглядит так:

  • world.identifier = <int> (нулевой запрещён)
  • world.innerName = <string>
  • world.size.x = <int> (в фрагментах, их на 1 меньше, чем вершин!)
  • world.size.y = <int>
server.const.analytics.binary

находится в разработке

server.const.landscape.binary

Файл содержит массив полных данных по вершинам ландшафта в его шаблонном состоянии. Раз прочитанный сервером, этот файл перестаёт быть нужным, и сервер переносит работу на свой файл базы данных ландшафта “server.state.landscape.binary”. Структура, описывающая одну вершину такова:

  • height (unsigned int8), используется [0..63]
  • terrainType (unsigned int8), используется [0..6]
  • decorators…
    • .tree…
      • .age (unsigned int8), используется [0..4] (пять состояний, как их расшифровать - см. доку выше. Например, ноль == “нет дерева”)
      • .type (unsigned int8), используется [0..14] (см. Приложение про деревья)
    • .minor (unsigned int8), используется [0..47] ( 0 == “пусто” )
    • .resource (unsigned int8), используется [0..18] ( 0 == нет ресурса )
  • climath…
    • .temperature (signed int8), используется [-100..100]
    • .wetness (signed int8), используется [0..100] (знак оставлен на всякий случай)
  • connections (unsigned int8), битовая маска, используются младшие 7 бит, 6 на соседей и самый старший из всех, 7й бит - на собственную “входимость”
server.state.landscape.binary

файл является базой данных по карте, в версии сервера. Видимо, содержит данные, эквивалентные “server.const.landscape.binary”. Антон Георгич, Вам слово!

client.const.landscape.z

Является компрессированной копией файла “client.const.landscape.binary”. Пофвился ввиду того, что текущий техпроцесс на сервере предпочитает сохранять монополию на упаковку файлов. Ожидаются незначительные потери производительности, так как файл должен компрессироваться и готовиться к раздаче один раз, при старте сервера, и накладные расходы не должны проявлятся во время реальной работы сервера.

client.state.landscape.z

Является заменой старого statics.z, то есть содержит в читаемом клиентом виде динамическую часть вершинной информации карты. Забота сервера создать этот файл, используя его, сервера, динамические данные. Файл является двумерным массивом структур:

  • (резерв) 4 бита (младшие 1го байта)
  • модификатор, 4 бита (старшие 1го байта). Реально используются значения [0..5], где отображается наиболее значимый модификатор
    • 0 == нет модификатора
    • 1 == трава
    • 2 == подлесок
    • 3 == вытоптано
    • 4 == снег
    • 5 == выжжено
  • декоратор, 8 бит, unsigned int8. Используется весь диапазон [0..255], где 0 - отсутствие декоратора. Рассчитывается по принципу приоритетов, где деревья затирают минорные декораторы, а ресурсы затирают деревья.

Алгоритм финализации карты (сервером)

Свежесгенерированная карта ещё не готова к употреблению: она нуждается в следах работы игровой логики. Если угодно, в “обкатке”. Занимается этим сервер, так как только он должен иметь в себе игровой код. Загрузив карту в необкатанном, то есть шаблонном состоянии, сервер выполняет следуюший алгоритм:

  1. С учётом карты климата и выбранного сервером времени старта карты (в масштабе клиента), карта заполняется снегом

Приложения

Таблица декораторов

Кодировка
  • p проходимый
  • n непроходимый
  • R ресурс
  • T дерево (мусорное, то есть не ресурс)
  • F то есть чисто декоративная фигня
  • m собственный для определённого типа или признака местности
Список

  • #0 - отсутствие декоратора
  • #1 - #47 (пока пусто)
  • #48 - #63: pR: декораторы генерящихся фермами ресурсов: 4 типа по 4 шага. X - тип, A - фаза
    • X == 0 (#48-51) “пшеница”
    • X == 1 (#52-55) “сад”
    • X == 2 (#56-59) “свинка”
    • X == 3 (#60-63) “овцы”
  • #64-#127: nT: “мусорные” деревья по 4 шага(S):№ = 64+(4*Х)+S. Порядок S: “мелкое одиночное”, “взрослое одиночное”, “взрослое и мелкие вокруг”, “много взрослых”.
    • X == 0, S==0 (#64-67) “хвойные”
    • X == 1, S==0 (#68-71) “хвойные/лиственные сухие”
    • X == 2, S==0 (#72-75) “хвойные/лиственные влажные”
    • X == 3, S==0 (#76-79) “лиственные сухие”
    • X == 4, S==0 (#80-83) “лиственные сухие/лиственные влажные”
    • X == 5, S==0 (#84-87) “лиственные влажные”
    • X == 6, S==0 (#88-91) “лиственные сухие/субтропические”
    • X == 7, S==0 (#92-95) “лиственные сухие/субтропические”
    • X == 8, S==0 (#96-99) “субтропические”
    • X == 9, S==0 (#100-103) “субтропические/джунгли”
    • X == 10, S==0 (#104-107) “субтропические/пальмы”
    • X == 11, S==0 (#108-111) “пальмы”
    • X == 12, S==0 (#112-115) “пальмы/джунгли”
    • X == 13, S==0 (#116-119) “джунгли”
    • X == 14, S==0 (#120-123) “специальный: у воды в умеренной зоне (ивы)”
    • X == 15, S==0 (#124-127) “(резерв)”
  • #176-193: “ресурсные точки” <resourcePoints.xxxx.png> для уровней ресурса 2 и выше.
    • (#176-181) “металлы”: олово, марганец, серебро, ртуть, мифрил, адамантит
    • (#182-187) “камни”: уголь, сера, соль, мрамор, хрусталь, ЛК
    • (#188-193) “дерево”: каучук, палисандр, красное, эбен, игнатор, стальдрево

Кнопки редактора

1-2-3-4-5-6-7-0 модификаторы (трава, снег, …)

Таблица значений модификатора (клиент)

q-w-e-r-t-y-u - материал

8-9 поднять-опустить вертекс ландшафту

Файлы карты

analytics.binary

Описание карты. не помещающееся в регулярную структуру (вертексы).

  1. Список создаваемых по-умолчанию деревень (городов нулевого уровня)
kg/doc_discoc_universe.txt · Last modified: 2022/04/07 13:12 (external edit)