Razdor

Razdor is a Rust port of Discord Times for Windows, macOS, and Android that features turn-based tactical combat and kingdom exploration.

README

Razdor

Небольшой прототип на Rust по мотивам Discord Times («Времена раздора», Aterdux, 2004): путешествуйте по карте королевства, нанимайте отряд в городах, сражайтесь в пошаговых тактических боях на клетчатом поле.

Все права на оригинальный код и графику «Времён раздора» принадлежат их авторам — Николаю и Денису (Aterdux Entertainment).

Сайт: indicozy.github.io/razdor · Трейлер: youtu.be/p7g0yvwtEeM

cargo run --release
cargo test          # правила игры

Отказ от ответственности

  • «Раздор» — независимый некоммерческий фанатский проект, созданный @indicozy. Он не связан с Aterdux или иными правообладателями Discord Times, не одобрен и не спонсируется ими. Название игры и товарные знаки принадлежат их владельцам и используются только для того, чтобы указать, с какой игрой работает движок.
  • «Раздор» не содержит кода, данных, текстов, графики, звуков, музыки или карт оригинальной игры. Чтобы играть в сценарии оригинала, нужна ваша собственная законно приобретённая копия игры. Не распространяйте файлы игры вместе с «Раздором».
  • «Раздор» предоставляется «как есть», без каких-либо гарантий, явных или подразумеваемых, включая гарантии товарной пригодности, пригодности для определённой цели и ненарушения прав. Вы используете его целиком на свой страх и риск.
  • Скачивая, собирая или запуская «Раздор», вы принимаете на себя единоличную ответственность за то, как вы его используете, и за то, чтобы это было законно там, где вы живёте, и разрешено лицензией вашей копии игры. В максимальной степени, допускаемой законом, авторы и участники проекта не несут ответственности ни по каким претензиям, за убытки или иную ответственность, будь то прямые, косвенные, случайные или последующие, включая потерю данных, сохранений или файлов игры, возникающие из «Раздора» или его использования либо в связи с ними. Любые такие убытки несёте вы.
  • Если вы обладаете правами на Discord Times и у вас есть претензии к этому проекту, свяжитесь с автором (@indicozy), и они будут рассмотрены.

Лицензия

Код «Раздора» распространяется по лицензии GNU GPL версии 3 (GPL-3.0-only) с дополнительными условиями из NOTICE: форк или сборка на основе «Раздора» должны сохранять строку «Based on Razdor by indicozy — https://github.com/indicozy/razdor» в окне авторов и в README и не могут называться «Раздор» (Razdor). Версии до 1.2.4 включительно вышли под лицензией MIT и остаются под ней. Участники проекта подписывают CLA (см. CONTRIBUTING.md). Шрифты в data/fonts/ сохраняют свою лицензию (файлы *-OFL.txt и *-LICENSE.txt рядом с ними).

Чего никогда нет в репозитории

Ни один коммит не может добавлять ничего из перечисленного ниже, и это соблюдает каждый, кто вносит вклад:

  • Ничего из игры: карты, ini-данные, тексты, графика, звуки, музыка, декодированные или сконвертированные ресурсы, снимки экрана или записи оригинала (граница содержимого выше).
  • Ничего чувствительного: учётные данные, токены, ключи, личные данные (адреса почты, пути к домашней папке, имена), логи (razdor.log, razdor-play.log), сохранения, файлы настроек и всё остальное, что относится к конкретной машине.

Если что-то такое всё же попадёт в коммит, его нужно удалить из истории (переписать её и сделать force-push), а не просто удалить новым коммитом: старый коммит его сохраняет. Вся история была проверена на соответствие этим правилам 2026-09-30 и ничего такого не содержит.

Заметки по обратной разработке могут оставаться: адреса в исполняемом файле, смещения в памяти, дизассемблированный код и то, как исполняемый файл был прочитан (docs/reference/original-mechanics/, свидетельства [exe]/code в docs/reference/mechanics.md). Лицензия игры (License.txt в установленной игре, пункт 5) разрешает использовать, копировать, эмулировать, декомпилировать, дизассемблировать и изучать её код любыми средствами. При этом распространение игры она по-прежнему оставляет за её авторами (пункт 3) и запрещает сдавать её в прокат, в аренду или продавать (пункт 6), поэтому заметки описывают оригинал нашими словами и не цитируют подробно его тексты или данные (это относится к содержимому игры, см. выше).

Как играть

  • Выберите героя: «Рыцарь» (ближний бой; его армия получает на 10% меньше физического урона), «Архимаг» (магия стихий: замедляет или сжигает врага), «Следопыт» (длинный лук; армия излечивается на 20% в день).
  • Демонстрационное королевство — карта из шестиугольников (data/kingdom.txt, один символ на клетку, нечётные ряды сдвинуты на полклетки): щёлкните в любом месте, чтобы увидеть самый дешёвый путь и его время, щёлкните туда же ещё раз (или дважды) — чтобы пройти его. Дороги быстрые, лес и болото медленные, вода и горы непроходимы. Правая кнопка мыши или Space останавливает.
  • Время идёт, только пока вы в пути или ждёте (Ждать 1 ч / 4 ч, клавиши 1 и 4), как в оригинале. В полдень окно отчёта показывает ваше золото и ману, доход ваших зданий и выплаченное жалованье (от стоимости каждого отряда); отряды, которым вы не можете заплатить, отказываются сражаться и уходят после недели без жалованья. Деревни пополняют дань в полночь.
  • Если войти в здание, открывается его окно с вкладками оригинала: «Главный зал» (описание, задания и слухи), «Казармы» (наём из запаса здания, который восполняется со временем; лечение раненого отряда за часть его стоимости и час; воскрешение павших в городах и церквях в течение недели, за тройную стоимость), «Гарнизон» (ваши замки и форты: оставляйте там отряды, им платят только за первый день, и они излечиваются на 10% в день), «Рынок» (товары и лавка для продажи; цены растут, если здание вас недолюбливает), «Святилище» (изучение заклинаний в книгу героя на 15 мест) и «Дань» деревни (золото и мана, или исцеление у священника, или трактирщик, который расплачивается с вашими неоплаченными людьми).
  • По карте бродят банды разбойников; они преследуют вас, когда вы рядом («!»), и нападают при встрече. Уцелевшие лагеря каждые несколько дней высылают новые банды.
  • Бои идут по правилам оригинала (docs/reference/mechanics.md). Каждая сторона стоит в построении 2×6 (широкий ряд Community Update; ванильное 3×4 с резервным рядом, если в установленной игре OptValue11 равно чему-либо, кроме 1). Как в оригинале, бой начинается, когда открывается его окно: построение — то, что было заранее задано в окне армии. Пока никто не сходил, «Быстрый бой» (Q / Enter) сразу разыгрывает его; позже «Доиграть самим» (Q) доигрывает остаток; «Смотреть» (W) позволяет посмотреть, как его играет ИИ (см. ниже).
  • Отряды ходят по инициативе (нападающий получает +1). Ходит карточка в зелёной рамке; у неё столько действий, сколько её значение Mnvr, и каждое тратится на атаку, заклинание или шаг. Наведите курсор на карточку в рамке, чтобы увидеть действие заранее («удар: -12 жизней», действие проклятия), щёлкните левой кнопкой, чтобы выполнить его, правой — для альтернативы (удар мага вместо проклятия). Щёлкните подсвеченную клетку, чтобы шагнуть туда (столбцы c−1..c+1); Space делает то же, что щелчок по собственной карточке отряда.
  • Воины сражаются только из переднего ряда и бьют три передние клетки врага напротив; если эти три пусты, дальний удар достаёт ближайшую переднюю карточку врага, вдвое снижая её защиту. Стрелки и маги в заднем ряду достают любого вне резерва. Урон — это атака минус защита, не меньше 1, без случайности; задний ряд получает +5 к защите от выстрелов. Маги бьют, проклинают, лечат или благословляют в зависимости от школы; их сила убывает с каждым ходом.
  • Когда передний ряд падёт, задний выходит вперёд. Отступления нет; через 25 ходов нерешённый бой заканчивается, и обе стороны отходят. Ваш герой выживает с 1 жизнью, пока жив хоть кто-то в его армии; вы проигрываете, когда погибла вся армия. Предел армии: 12.
  • Выжившие получают опыт («XP +N» на карточках). Уровни повышают характеристики; некоторые отряды можно повысить на экране героя и армии — скрещённые мечи на нижней панели (копейщик на 2-м уровне становится мечником). Павшие остаются в армии телами, пока их не воскресят или не похоронят; их предметы переходят в рюкзак. Окно победы показывает добытые золото, ману и предметы, а также захваченный замок, если он есть.
  • Предметы, как в оригинале: у каждого отряда 4 ячейки, одно оружие, никогда не два предмета одного типа; оружие ближнего боя для воинов, луки для стрелков, посохи для магов. Покупайте их на рынках (новые случайные товары каждые 7 дней, продажа за четверть цены), добывайте в лагерях и у банд или получайте как дань деревни. Снаряжением управляют на экране героя и армии (4 ячейки на отряд, прокручиваемый рюкзак на 40); зелья выпивают там же (лечение сразу, прочие действия длятся до конца следующего боя). Как в оригинале, перетащите предмет из рюкзака на карточку отряда, чтобы отдать его этому отряду (зелье: он его выпьет), из ячеек одного отряда на карточку другого, чтобы передать его, или в рюкзак, чтобы снять его. Там же можно распускать отряды.
  • Отряды и предметы демо — наше собственное содержимое в data/units.ini и data/items.ini, записанное в том же формате, который движок читает из установленной Discord Times.
  • Чтобы победить, уничтожьте оба лагеря разбойников. Если погибнет вся ваша армия, игра окончена.

Ваша копия Discord Times

«Раздор» становится движком для сценариев оригинальной игры. Он читает данные из вашей собственной установленной копии Discord Times (Community Update) во время работы; в репозитории нет оригинальных карт, данных, текстов или графики, и ничего из вашей установки никогда не копируется и не записывается. Если игры нет, главное меню объясняет, что нужна своя копия (версия 1.8 с Community Update 1.2), и ведёт к инструкции по установке и в Discord, где её берут.

export RAZDOR_DT_DIR="/path/to/Discord Times"   # the folder with DiscordTimes.exe
cargo test                                      # also checks the readers against your files

Тесты скорости ИИ на картах рассчитаны на быстрые ядра; на медленных задайте множитель бюджета, например RAZDOR_PERF_BUDGET_SCALE=2.

Установленная игра ищется по порядку: RAZDOR_DT_DIR (читается также из файла .env в текущей папке или рядом с программой, RAZDOR_DT_DIR="/path/to/Discord Times"); собственная папка программы, так что Razdor.exe (Windows), razdor (Linux) или razdor-macos (macOS), скопированные рядом с DiscordTimes.exe, играют эту копию (на Mac — в папке игры внутри бутылки Wine или CrossOver); папка, запомненная с прошлого запуска; поиск в ~/Games, ~/Downloads и домашней папке. Сделано для Community Update 1.2 (игра 1.8.1).

Моды. Поддерживается мод Evolution (проверен с версией 9.0 на Community Update: 161 отряд, его дерево улучшений, предметы, заклинания и карты). Мод Discord Times — это изменённая установка (свои файлы Rus_*.ini, листы графики и карты), поэтому укажите в RAZDOR_DT_DIR копию игры с установленным модом. «Раздор» читает ini-файлы так же снисходительно, как оригинал: значение, которое он не может прочитать, считается отсутствующим, запись без пригодного GlobalIndex (или предмет без Type) пропускается, и каждый такой случай записывается в razdor.log, а не приводит к отказу от установки. Моды, которые изменяют сам DiscordTimes.exe, не поддерживаются. Проверки, которые cargo test запускает на вашей установке, рассчитаны на чистый Community Update, поэтому многие из них не проходят на модифицированной.

scripts/dist.sh собирает обе программы в dist/: razdor для Linux и Razdor.exe для Windows (x86_64, один файл без собственных DLL; кросс-сборка с помощью llvm-mingw, см. скрипт), с их SHA-256 в dist/SHA256SUMS. Выпуски собираются на GitHub (.github/workflows/release.yml): укажите версию в Cargo.toml, превратите «Не выпущено» в CHANGELOG.md в раздел этой версии, сделайте коммит, затем отправьте тег vX.Y.Z. Конвейер запускает тесты, собирает обе программы тем же скриптом и теми же зафиксированными инструментами (Rust в rust-toolchain.toml, llvm-mingw в workflow) и публикует выпуск с разделом журнала изменений и SHA-256. Razdor.exe получается одинаковым из одного и того же коммита на любой машине. Программа для Linux зависит ещё и от системы, на которой она компонуется (её библиотеки C и компоновщика): конвейер собирает её на Ubuntu 22.04, благодаря чему она работает и на более старых дистрибутивах, поэтому выпуски берут её оттуда.

Значок в меню приложений Linux: положите razdor в папку из PATH (например, ~/.local/bin) и выполните install -Dm644 data/icon/razdor-256.png ~/.local/share/icons/hicolor/256x256/apps/razdor.png и install -Dm644 data/icon/razdor.desktop ~/.local/share/applications/razdor.desktop.

scripts/dist-macos.sh собирает razdor-macos на Mac (нужен SDK от Apple из Xcode или его Command Line Tools): одна универсальная программа для Apple Silicon и Intel, macOS 11 и новее, добавляется в dist/SHA256SUMS. Конвейер собирает её на раннере GitHub с macOS 15. Как и программа для Linux, она зависит от системы, на которой компонуется (здесь — SDK и компоновщик Xcode): один и тот же коммит на одном и том же образе раннера даёт тот же SHA-256, другой Xcode может дать другой. Она не подписана разработчиком, поэтому macOS блокирует её после скачивания: перед первым запуском выполните xattr -d com.apple.quarantine razdor-macos (или правая кнопка → Open в Finder). При запуске двойным щелчком она открывается в Terminal. Запуск конвейера вручную (Actions → Release → Run workflow) собирает три программы коммита как артефакты запуска, ничего не публикуя.

Если не запускается или не играется: каждый запуск пишет razdor.log (%APPDATA%\razdor\ в Windows, ~/.local/share/razdor/ в Linux, ~/Library/Application Support/razdor/ в macOS; предыдущий — razdor.previous.log): версию и коммит, систему, папку программы и рабочую папку, переменные RAZDOR_* и файлы .env, как была найдена установленная игра или почему папка ею не является, версию OpenGL, затем каждый шаг запуска, так что последняя строка показывает, где он остановился. Паника (с трассировкой стека) или падение тоже записываются туда, а в Windows ещё и показываются в окне сообщения. При запуске без терминала всё, что выводят программа и её библиотеки, попадает в лог; при запуске из cmd или терминала оно выводится и туда. RAZDOR_LOG=<file> переносит лог; RAZDOR_CRASH_TEST=panic или crash намеренно вызывает сбой, чтобы проверить отчёт.

Журнал игры, razdor-play.log в той же папке (предыдущий — razdor-play.previous.log), записывает сеанс, чтобы его можно было перечитать, когда что-то играется не так, каждую строку — с игровой датой: начало или загрузку игры (карта, герой, деньги), каждый экран, каждое сообщение, каждый заданный переход, события мира (столкновения, встречи, посещённые и захваченные здания, полуденные отчёты, события сценария и задания по номеру и названию) и каждый бой полностью: обе стороны отряд за отрядом (ячейка, уровень, жизни, все характеристики, защиты, бонусы, надетые предметы), весь журнал боя и итог. Он остаётся на компьютере игрока.

«WGL_ARB_pixel_format is required» / нет драйвера OpenGL (Windows): «Раздору» нужен OpenGL 2, а машина предлагает только запасной OpenGL 1.1 из Windows. Так бывает в сеансе удалённого рабочего стола (RDP), который скрывает видеокарту от программ OpenGL, или без графического драйвера (часто в виртуальных машинах). Положите программный OpenGL от Mesa (opengl32.dll, а в новых выпусках ещё и libgallium_wgl.dll, из папки x64 mesa-dist-win) рядом с Razdor.exe, или подключитесь не через RDP (Parsec, VNC, консоль виртуальной машины), или установите графический драйвер. Тогда «Раздор» сам покажет этот совет вместо голой ошибки.

Что читается (только читается, никогда не изменяется): Rus_Units.ini, Rus_Artefacts.ini, Rus_Spells.ini, _Global.ini и карты сценариев Maps_Rus/*.DTm. Код чтения находится в src/dt/ (dt::install::DtInstall::from_env()); форматы описаны в docs/reference/. rules::content::Content::from_dt превращает их в определения, которыми пользуются правила. Без переменной всё по-прежнему работает, а тесты, которым нужны настоящие файлы, пропускаются.

Если переменная задана, игра открывается главным меню оригинала; «Новая игра» перечисляет одиночные сценарии и первую карту каждой кампании из вашей Maps_Rus с картой, её статусом, размером и описанием (прочитанными из ваших файлов во время работы). Выберите одну, затем одного из трёх героев карты. Карта мира использует текстуры местности, объекты, здания и фигурки на карте из оригинала; наведите курсор на армию или здание, чтобы увидеть подсказку (построение, предводитель, владелец, «дань уже собрана»); пока вы идёте, белые стрелки отмечают путь, а полоска показывает оставшееся время; колесо мыши или +/- — масштаб. Враждебные армии преследуют вас и сражаются при встрече, дружественные приветствуют; враждебные замки, форты и руины с гарнизоном сражаются, когда вы входите в их ворота, и завоёванный замок или форт становится вашим вместе с доходом (пустой враждебный захватывается простым входом). Города, замки, форты, церкви, деревни, рынки и таверны открывают окна зданий с запасами, ценами и заклинаниями карты.

События и задания карты работают, как описано в руководстве к редактору оригинала: окна сюжета (заголовок, текст, картинка, полученное, OK) открываются с течением времени, когда вы входите в здание или ступаете на точку события, после боя или когда вы встречаете армию в пути; движение останавливается, чтобы вы могли их прочитать, и пока окно открыто, время стоит. У вопросов есть «Да» / «Нет». Принятые задания попадают в дневник героя (флаг на нижней панели, клавиша J) со своими текстами, а выполненные там отмечаются; главный зал перечисляет задания здания и предлагаемые слухи (по 10 золотых). Событие победы или поражения сценария завершает игру. Туман войны скрывает то, чего герой ещё не видел (неисследованная земля чёрная, по ней нельзя пройти и по ней нельзя щёлкнуть); M или спиральная кнопка «карта» на нижней панели открывает мини-карту исследованных земель, а щелчок по ней перемещает камеру. «Верфь» продаёт корабль за ShipCost золотых (250): щёлкните по воде рядом с ней, чтобы выйти в море, щёлкните по берегу, чтобы высадиться; корабль ждёт там, где вы его оставили, пока вы снова на него не взойдёте (только один корабль за раз; если уйти с верфи пешком, он теряется). Пиратские корабли плавают и нападают, как враждебные армии, торговые корабли никогда не нападают. Деревни раз в день вместо дани предлагают исцеление у священника, расплату с неоплаченными, долгое благословение, меха, стоящие больше золота, или магический ритуал ради маны. Герой начинает в стартовом здании заготовки, если карта его называет, а экран выбора класса принимает для него имя (#HERONAME; пустое — имя класса). Для русского текста нужен шрифт TrueType с кириллицей: распространённый системный шрифт находится автоматически, или задайте RAZDOR_FONT=/path/to/font.ttf (без него имена пишутся транслитом).

Обновления

«Раздор» при каждом запуске ищет на GitHub более новый выпуск в отдельном потоке: игра никогда его не ждёт, и ничего не показывается, если новой версии нет (src/update.rs). Затем в спокойный момент (титульный экран, настройки, карта без других окон, никогда — в бою) окно предлагает её вместе с изменениями с вашей версии («Обновлять всегда» делает то же самое и переключает настройку на «Всегда»): «Обновить» скачивает её, пока вы играете, сверяет с SHA256SUMS выпуска и ставит на место программы; она работает со следующего запуска (титульный экран такж