step_supply sent every free truck into the return branch whenever any S-400 had a pending ground_return, even when that return could not proceed (the system moving, damaged, reloading or preparing, its round already claimed by another truck, the route marked unreachable, or no depot with room). The branch then found no target, cleared the job and stopped the truck, so independent typed supply requests starved. The return now keeps its priority only while it is executable: a carrier holding a reserved round looks for a depot with room in reach, an empty one for a system ready to hand a round over. Otherwise the claim stays untouched and only real RM48U demand (a requesting system with depot stock, or ground rounds aboard for one) pulls the truck into the typed supply branch; without such demand it holds its watch exactly as before. Redirecting a reserved round to a waiting request clears return_cargo once the last one leaves the truck, and a stale return_cargo with an empty hold no longer sends the truck to a depot handover it cannot complete. Regressions: three sim tests (moving claimant, pickup claimed by another truck with damaged/save-restore phases, unreachable route) and one full-drive lib test with a mid-flight state round trip; the rounds are conserved in every phase and the actual return completes once the claimant is back. All three sim tests fail on the old code. Checks: core release 200 passed/8 ignored + 8 scenarios; adapter 67 unit + 1 boundary + 5 scenarios; real WASM test-wasm 30 steps.
AirDef — дальнобойные дроны и ПВО для Horizon
Клиентский sandbox-мод для Horizon (Minecraft 26.3 на Rust): налёты дронов и ракет, эшелонированная ПВО, раздельные батареи, наземная логистика, разведка, РЭБ, повреждения, повторы и экспорт видео. Характеристики и временные масштабы игровые; это не тренажёр реальных комплексов.
Работает на своём форке Horizon
(horizon/ — сабмодуль, закреплённый SHA): в нём добавлен API отрисовки
3D-моделей, которого нет в основном Horizon.
Рабочая ветка — kimi-work. Подробный проверенный объём и оставшаяся приёмка:
состояние задач. Для передачи разработки:
технический журнал и handoff. Открытый issue не означает отсутствие
реализации: по просьбе владельца агенты оставляют комментарии, но не закрывают задачи.
Запуск
Пошаговый гайд для Windows и macOS (готовая сборка из релиза или сборка из исходников): docs/INSTALL.md. Устройство HD-рендера, его статус и план доработки: docs/HD-RENDERER.md.
Коротко, из исходников:
git switch kimi-work
git pull --ff-only
git submodule update --init --recursive # также выполняется командой all
python3 tools/airdef.py all # получить закреплённый движок, собрать игру и мод, установить мод
python3 tools/airdef.py play # запустить (аргументы игры — после: --world "Имя мира")
all синхронизирует URL сабмодуля из .gitmodules, включая обновление со старого upstream.
Продолжение 4 ноября: модели, границы ядра, общий каталог, API29 и массовая акустика.
Диагностика в игре: /airdef capabilities показывает доступность API, принятие запроса и
подготовку дыма, акустики и захвата именно этого мода. Подготовка не означает готовый GPU-кадр или MP4.
Для разработчика: python3 tools/airdef.py test-wasm — лёгкий ABI-тест;
python3 tools/airdef.py test-budgets — отдельный тяжёлый сценарий с JSON-отчётом.
Для разработки: ./install.sh перегенерирует модели (tools/gen_models.py, нужен Pillow) и звуки
(tools/gen_sounds.py, нужны numpy и ffmpeg), собирает и ставит мод. Сгенерированные файлы лежат в репозитории,
так что для обычной сборки нужен только Rust.
CI: .gitea/workflows/build.yml на каждый пуш собирает только мод (airdef.hmod), а пуш в main публикует его
релизом build-N. Игру-форк собирают вручную: .gitea/workflows/game.yml (Linux) и .gitea/workflows/desktop.yml
(macOS и Windows, на раннерах с метками macos-latest / windows-latest); оба запускаются из Actions с тегом
готового релиза build-N. Перед сборкой workflow проверяет, что такой релиз создан build.yml (имя релиза = тег,
есть airdef.hmod), иначе падает с ошибкой; затем выкачивает ровно коммит этого тега (а не ветку, с которой запущен),
сверяет его с коммитом релиза и дописывает архивы только в этот релиз.
Как играть
/airdef give выдаёт пульты. Все срабатывают на ПКМ.
| Предмет | Что делает |
|---|---|
| Целеуказатель | ставит или снимает цель на блоке под прицелом (до 512 блоков) |
| Пуск: Шахед-136 / Герань-3 / Ланцет-3 / Х-101 / Калибр / Х-22 / Циркон / Искандер-М / Кинжал | запускает дрон или ракету в точку под прицелом |
| Развернуть Patriot / Гепард / Панцирь-С1 / С-400 / С-500 | ставит комплекс на блок под прицелом, носом по взгляду |
| Свернуть ПВО | убирает ближайший комплекс у точки под прицелом |
Командный пункт: клавиша N или /airdef menu. В нём список комплексов: выбери комплекс и включай или выключай классы целей
(дроны, реактивные дроны, крылатые, сверхзвуковые, баллистика), есть сброс по умолчанию. Там же кнопки «Командный
пункт» (сетка), «Налёт…» и «Огонь, ремонт, эффекты…» (огонь ПВО, ремонт всех, эффекты, разрушения).
Налёт (меню N → «Налёт: состав и запуск…»): на первой странице состав — клик по типу листает число (0, 1, 2, 3, 4, 6, 8, 10, 15, 20, 30, 40); на второй — готовый вариант («Рой Шахедов», «Массированный удар», «Баллистика», «Гиперзвук», «Орешник с прикрытием», «Подавление ПВО»), откуда (один сектор, два, со всех сторон, волнами по типам), дальность старта, цели и ПУСК. Цели:
- только объекты — всё летит по отмеченным объектам (или по игроку, если их нет);
- объекты и ПВО — треть ударных средств бьёт по случайным комплексам;
- умный противник — планировщик использует наблюдённые контакты и последние известные позиции комплексов: ведёт дроны и крылатые ракеты маршрутами в обход зон поражения, низко, за рельефом и через мёртвые зоны; «Герберы» прилетают на 15 с раньше, чтобы оттянуть ракеты; «Ланцеты» идут по Гепардам и Панцирям, Х-22/Циркон и часть баллистики — по дальнобойным комплексам; на наблюдённые РЛС дальнего обнаружения выделяются 2–3 быстрых ударника (Х-22, Циркон, Искандер, Кинжал, затем Х-101, Герань-3, Ланцет, Шахед; не больше четверти налёта); всё остальное стартует со сдвигом так, чтобы прилететь одновременно.
После налёта приходит отчёт: сколько сбито и прорвалось, ракет ПВО потрачено, комплексов потеряно, урон объектам.
Обнаружение. РЛС видит цель не дальше, чем позволяют:
- её размер: дальность растёт как корень четвёртой степени из ЭПР — Х-101 и Ланцет видно примерно вдвое ближе, чем Х-22;
- радиогоризонт: низколетящую цель видно поздно (Шахед на 25 м — с ~250 м, баллистику — издалека);
- рельеф и лес: за холмом цель не видна (каждый комплекс строит свой горизонт по 48 лучам; рельеф известен в прогруженных чанках);
- вблизи (24 м) видно всё.
Радар игрока и мониторы показывают только то, что держат РЛС; в сводке видно «Вне видимости РЛС: N». Мёртвые зоны — ближе минимальной дальности ракет (Patriot 10 м, Панцирь 25, С-400 30, С-500 40).
Сохранение. Комплексы, объекты, их повреждения и настройки сохраняются отдельно для каждого мира (и для каждого сервера); уничтоженный комплекс остаётся остовом и после перезахода, пока его не отремонтируют.
Сеть ПВО. Единицы обмениваются измеренными треками в пределах игровой связи; повреждение связи сокращает её дальность. Можно поставить несколько С-400/С-500 без собственной РЛС и общие радары поиска, сопровождения и мачтового обзора: N → «Разместить элементы батареи…». Поисковый радар даёт подсказку; огневой должен сам измерить цель, прежде чем разрешить пуск. Старая сборная конфигурация сохранена. Команды, источники и ограничения. P1-SUN также использует чужие данные. Пушкам (Гепард, пушки Панциря) нужна своя цель: они стреляют только по тому, что видят сами. Уничтоженная РЛС — дыра в сети.
Радиомолчание. /airdef radar <номер> off|on или кнопка в карточке техники на карте
выключает/включает собственный радар. Приём разрешённых внешних треков сохраняется; чужой трек
не заменяет обязательное собственное сопровождение. Выключение не стирает старые сведения противника:
он продолжает использовать последнюю наблюдённую позицию, а пуски и РЭБ могут снова раскрыть технику.
Логистика. Пока нет ни одного склада, магазины пополняются сами, как раньше. Как только поставлен склад, боекомплект считается: комплекс без ракет пишет «ЖДЁТ БК»; в 60 м от склада он перезаряжается прямо с него, а дальние обслуживают ТЗМ: заправляются на складе (2 перезарядки), сами едут к ждущим комплексам, ближайшим первым, и возвращаются. Запас склада — 30 перезарядок, он виден в сводке. Склад и ТЗМ детонируют всем грузом.
Ударная RM48U у С-400 — отдельный условный игровой боеприпас, который делит четыре ячейки
с ракетами ПВО. /airdef ground-stock <склад> <количество> задаёт конечный начальный запас
sandbox-сценария, /airdef ground-load <С-400> загружает одну ракету рядом со складом либо
создаёт заявку на доставку ТЗМ. Груз едет физически; снятая ракета ПВО возвращается на склад.
Заявка и груз сохраняются в пути. /airdef ground-unload <С-400> выгружает ракету у склада,
а вдали создаёт заявку на обратный вывоз ТЗМ. Одна ракета резервируется от пуска до забора;
/airdef ground-cancel <С-400> отменяет ещё ожидающую доставку или вывоз.
После забора ракета находится в машине и едет на склад. Отмена заявки не возвращает уже вывезенный груз в ПУ.
Без склада этот ударный боеприпас сам не появляется. Бук и остальные комплексы такого профиля пока не имеют.
Порядок подготовки, разведка и номера двух списков: как ударить по ПУ.
Перемещение. Пульт перемещения: навестись на технику (выбрать), затем на точку на земле — она
сворачивается (С-400 и другие с вертикальным пуском дольше, Гепард и Панцирь быстро), едет по рельефу и
разворачивается; всё это время не стреляет и не светит РЛС. Или /airdef move <номер> — к тому месту, где ты стоишь.
РЭБ. Клавиша U (или /airdef ew on|off) включает все станции. Станция в радиусе 350 м сбивает
спутниковую навигацию у Шахедов, Герань, Гербер, Х-101 и Калибров: они теряют маршрут и уводятся с цели
(баллистике и Ланцетам с оптикой всё равно). Передатчик работает до 20 с и перегревается; остывает ~35 с,
пока не остынет — не включить. Включённая станция себя выдаёт: умный противник запоминает её и шлёт на неё
Ланцеты и Х-22, а маршруты спутниковых дронов прокладывает в обход.
Умный противник учится. Он запоминает, откуда его налёты сбивали, а откуда они прорывались, и следующий налёт ведёт с лучшего направления; помнит комплексы, выдавшие себя пуском, и станции РЭБ, и во время налёта перенацеливает ещё не взлетевшие Ланцеты и Шахеды на них; если цель-комплекс уничтожен, дроны идут к следующему известному. Дроны под обстрелом прижимаются к земле.
Ночь. Исправные пушки с собственным свежим радарным сопровождением не теряют точность из-за темноты.
Цели освещают прожекторы (луч ведёт ближайшую
цель из сети, приоритет — цели пушек) и осветительные ракеты: пушечные комплексы пускают их сами (раз в
25 с на цель в темноте), игрок — осветительным пистолетом или /airdef flare. Ракета висит ~30 с и
освещает всё вокруг на ~60–90 м.
Графика: три пресета (меню N → «Огонь, ремонт, эффекты…» → «Эффекты», или /airdef shader off|on|hd):
выкл — ванильная картинка; обычные — шейдерные огненные шары, ударная волна и подсветка; HD — свой рендер
освещения в форке: мир дополнительно рисуется в G-буфер (цвет без света и нормали), и все источники света мода
освещают его попиксельно в HDR — факелы ракет и двигатели, раскалённые боевые блоки, осветительные ракеты, вспышки
выстрелов, трассеры, взрывы (вспышка и догорающий шар), горящие остовы, пятна прожекторов, — затем bloom и мягкий
тонмаппинг (ванильный диапазон не трогается, сжимается только то, что ярче). Источники передаются движку новым
API мода render.set-lights (до 512, плавно интерполируются), режим — render.set-lighting.
В HD дымовые следы ракет немного уплотнены; число сегментов и время появления/выгорания сохранены. Это относится к ракетам ПВО, RM48U, крылатым, сверхзвуковым и баллистическим средствам; дым пожаров и слабая дымка винтовых дронов остались прежними.
Сетка J после сбития ещё 3,5 с держит камеру на сбитой цели, и комплекс в это время не пропадает из сетки.
Повреждения. Взрыв рядом с комплексом повреждает его: он хуже поворачивается, хуже видит и попадает,
дымит, ниже 35% горит. Уничтоженный остаётся горящим остовом, его боекомплект детонирует: чем больше ракет
оставалось, тем мощнее взрыв и дольше вторичные (у Гепарда рвутся снаряды); соседние комплексы тоже могут
пострадать. Объекты (Целеуказатель или /airdef target here) имеют прочность, она видна в сводке. Ремонт —
кнопкой в меню или /airdef repair.
Известные стены и рельеф ослабляют непрямой урон корпусу, узлам и объектам; проёмы дают частичное воздействие. Используется геометрия, известная перед разрушением. При неизвестной или устаревшей геометрии сохраняется прежний урон без защиты; поздний ответ его повторно не наносит. Прямое вооружённое попадание этим ослаблением не отменяется.
Монитор комплекса: клавиша K листает комплексы по очереди, после последнего монитор скрывается. Слева вверху показано:
- состояние комплекса (поиск, сопровождение, доворот, захват, пуск, огонь, перезарядка, огонь запрещён);
- его РЛС: цели, по которым он работает, красным, остальные серым, текущая цель жёлтым;
- камера комплекса: настоящий вид мира из точки комплекса (второй рендер форка), с зумом на цель — тепловизор при сопровождении, в поиске днём цвет, ночью ПНВ; рамка захвата, дальность, высота, скорость и пеленг.
Командный пункт ПВО (сетка): клавиша J (или /airdef grid, или кнопка в меню N) — на весь экран сетка
до 8 комплексов: у каждого состояние, РЛС, живая камера, прочность и боекомплект. Если комплексов больше, показываются
самые занятые (стреляют, держат захват, сопровождают, горят), раз в 2 секунды; комплекс с монитора K — всегда.
Повторное J закрывает.
Повторы. Каждый налёт записывается сам: с первой цели в небе до момента, когда небо 5 с чисто (хранятся 3 последних). Меню N → «Повторы…» или клавиша R:
- карта налёта — вид сверху: комплексы и их зоны, объекты, треки целей (красные), ложных целей (серые) и перехватчиков (жёлтые), сбития (x), прилёты, шкала времени с событиями; время идёт само, колесо мыши перематывает;
- повтор момента — клик по событию в списке: «призраки» дронов и ракет снова летят в мире, камера идёт за целью, потом за перехватчиком (или смотрит из пушки, со стороны на прилёт), в момент сбития время замедляется;
- полный повтор — весь налёт, камера-режиссёр сама выбирает, за чем следить; колесо — перемотка, стрелки — скорость;
- лучшие моменты — нарезка до 8 самых интересных событий (перехват баллистики и гиперзвука, поражения объектов, потерянные комплексы, разделение «Орешника») с титрами и замедлением; колесо листает моменты.
Повтор идёт на весь экран с леттербоксом; звук слышен так, как его слышала бы камера. Управление (подсказка показывается в начале, после нажатия и на паузе): ← → — перемотка на 5 с (в нарезке — соседний момент), ↑ ↓ — скорость (×0.25–×32), Пробел — пауза (в конце — сначала), колесо — время / моменты, R или Backspace — выход, N — выйти в меню. В конце повтор встаёт на паузу.
Чтобы в повторах и камерах комплексов была видна земля далеко от игрока, мод включает дальний ландшафт (48 чанков, упрощённый); выключается в меню N → «Огонь, ремонт, эффекты…» → «Дальний ландшафт».
Клавиши N, K, J, R и U можно переназначить в «Настройки → Моды».
Команды:
/airdef wave <тип> [кол-во] [дальность]— налёт на ближайшую цель. Дальность старта — от 60 до 4000 блоков (в меню: 200–4000); землю для площадок, которой нет в загруженных чанках, игра подгружает сама (API 22,render.load-chunks, пока идёт поиск), а где подгрузить нельзя (сервер) или нет пригодного места, дроны всё равно стартуют: «за картой», с высоты полёта на заказанной дальности, без площадки. Типы:shahed,geran3,lancet,gerbera,kh101,kalibr,kh22,zircon,iskander,kinzhal,oreshnikиmix(комбинированный удар двумя секторами: «Герберы», шахеды, Герани-3, Х-101, «Калибры», Х-22, Циркон, «Искандер», «Кинжал», при 30+ — «Орешник»);/airdef replay [map|full|reel|stop]— повтор последнего налёта;/airdef replay film [best|all|N]— фильм режиссёра: для каждого перехвата/прилёта несколько планов (комплекс, пуск, погоня за ракетой, взгляд с цели, замедленный крупный план поражения, общий план после), склейки, плавные движения камеры, камера не уходит под землю; играется в максимальном качестве (HD, мир в полном разрешении, больше шагов облаков и тумана; настройки возвращаются после);/airdef replay export [имя] [best|all|N] [fps=60] [size=1920x1080] [crf=14] [sec=N] [noaudio]— тот же фильм кадр за кадром с фиксированным шагом (скорость компьютера не важна) в MP4 с звуком:<HORIZON_HOME>/airdef-films/<имя>.mp4(нуженffmpegв PATH илиHORIZON_FFMPEG; без него — PNG-последовательность и готовая команда ffmpeg). Прогресс в чате, отмена —/airdef replay stop. Окно игры держите в фокусе (пауза останавливает съёмку); чат попадает в кадр./airdef import— перенести в текущий мир комплексы и цели из старой версии мода (до 0.2.x они были общими для всех миров);/airdef raid— налёт, настроенный в меню;/airdef target here— отметить объект под ногами;/airdef repair— ремонт;/airdef lastchance <on|off>— «последний шанс»: комплекс стреляет и по классу вне ролей, если цель вот-вот попадёт (по умолчанию вкл; сохраняется);/airdef sites— известные пусковые площадки (ПУ). РЛС с прямой видимостью может заметить сам пуск и получить неточную позицию; несколько наблюдённых пусков уточняют её. Обнаруженный позже дрон даёт только слабое предположение об обратном курсе: скрытые координаты площадки и время невидимого старта не используются. Повторные треки одного полёта не создают ложную точность./airdef strike <номер ПУ>— ручной удар по разведанной площадке из готового физического С-400 с отдельно загруженной RM48U (игровой профиль, #118). Четыре ячейки делятся с боезапасом ПВО; приказ резервирует носитель и ячейку, открывает крышку и списывает одну ударную ракету при выбросе. Выбирается готовый комплекс с наибольшим остатком RM48U, затем ближайший к цели. Есть открытие ТПК, выброс, отложенное включение двигателя и разгон, ограниченная игровая траектория, столкновения и запись пуска. Несуществующее «ПВО площадки» не перехватывает ракету по броску вероятности./airdef ground-stock <номер склада> <количество>— задать остаток RM48U для sandbox-сценария (по умолчанию 0)./airdef ground-load <номер С-400>загружает одну ракету у склада либо заказывает ТЗМ;ground-unloadвозвращает её у склада либо заказывает вывоз;ground-cancelотменяет ожидающую заявку. Доставка и обратный вывоз через ТЗМ реализованы, запас и груз сохраняются. Пошаговый пример. Совместимость профиля основана на публикации ГУР; это сообщение ведомства, не независимая сертификация. Дальность, форма полёта и оформление условны для Minecraft./airdef deploy s400_launcherиs500_launcher— отдельные пусковые без своей РЛС;radar_search,radar_track,radar_height— обзорная, сопровождающая и мачтовая игровые РЛС. Они также доступны через меню N → «Разместить элементы батареи…»./airdef batteryпоказывает состав и связь;/airdef battery <номер> integrated|launcherменяет конфигурацию,/airdef radar <номер> multi|search|engagement|height— роль отдельной РЛС. Обзорная РЛС передаёт подсказки; станция сопровождения должна сама получить свежее измерение, чтобы разрешить пуск. Старые С-400/С-500 сохраняют упрощённую сборную конфигурацию. Устройство игровой батареи и пуска./airdef roles— показать, по каким классам целей работает каждый комплекс;/airdef roles <patriot|gepard|pantsir|s400|s500|all> <классы|default>— задать (классы через запятую:drone,jet,cruise,supersonic,ballisticилиall), например/airdef roles s400 cruise,ballistic;/airdef doctrine— доктрины комплексов (#47; в меню N: «Доктрины…»):/airdef doctrine <номер|all> reserve <K>— держать K ракет для срочных целей (баллистика или до удара меньше 12 с);salvo eco|normal|heavy— сколько перехватчиков на цель (только базовые / как обычно / на один больше);sector <центр°> <полуширина°>илиsector off— сектор ответственности (0° — север);guard <объект№>[,<№>]илиguard off— стрелять только по тому, что идёт на охраняемые объекты (отметка:/airdef target here). По умолчанию ограничений нет; последний шанс сильнее доктрины;/airdef why <номер>называет, какая настройка остановила или разрешила пуск; сохраняется с миром и сценариями. Карта охраны и пробелов в ней — вместе с картой (#48)./airdef deploy <patriot|gepard|pantsir|s400|s500>— поставить комплекс в 8 блоках перед собой;/airdef hold on|off— запретить или разрешить ПВО огонь, удобно для съёмки ударов;/airdef damage on|off— разрушать ли ландшафт взрывами (через TNT, нужны читы);/airdef shader on|off— шейдерные эффекты;/airdef clear— убрать дроны и ракеты;/airdef targets clear— снять все цели;/airdef stats— сводка.
Интерфейс:
- сверху справа — сводка: тревога, цели по типам, ближайшая угроза (дальность, высота, скорость), перехватчики в воздухе, по каждому комплексу боезапас или перезарядка, его текущая цель и число сбитых, итоговый счёт;
- снизу справа — радар на 500 м со сканирующим лучом. Отметки гаснут после прохода луча. Красное — цели (с хвостом по курсу), жёлтое — ракеты, синее — ПВО с кругами дальности, крест — цели удара.
Комплексы ПВО и цели сохраняются между сессиями.
Техника
| Дрон / ракета | Поведение |
|---|---|
| Шахед-136 | 43 км/ч в игре, 45 м над целью, 18 м над рельефом, крен в поворотах, пикирует, винт крутится |
| Герань-3 | реактивный, 115 км/ч, факел из сопла |
| Ланцет-3 | Х-образные крылья, низко (25 м), манёвренный, его труднее сбить |
| Гербера | ложная цель из пенопласта, без боевой части: отвлекает ракеты ПВО |
| Х-101 | крылатая ракета, 170 км/ч, огибает рельеф на 12 м, мощная боевая часть |
| Калибр | крылатая ракета, 150 км/ч, огибает рельеф на 15 м |
| Х-22 | сверхзвуковая, 290 км/ч, идёт на 140 м и круто пикирует издалека |
| Циркон | гиперзвуковая, 400 км/ч, её трудно сбить |
| Искандер-М | баллистическая: стартует за 1 км, дуга с апогеем ~250 м, на конечном участке доворачивает на цель |
| Кинжал | аэробаллистическая, 540 км/ч, стартует за 1,5 км; реально сбивает только С-500 |
| Орешник | баллистическая средней дальности: стартует за 2,6 км, над целью разделяется на 6 блоков, каждый — на 6 светящихся суббоеприпасов («огненный дождь», ~5 с); С-500 успевает сбить лишь несколько |
Сила взрыва зависит от боевой части: ложные цели — хлопок, дроны — средний взрыв, Шахед — сильный, Х-101/Х-22/Калибр — тяжёлый (двойной удар, столб земли, тряска до 160 м), Искандер/Кинжал — самый мощный (огненный шар 13 м, тряска до 240 м); у каждого уровня свой звук.
| ПВО | Вооружение | Дальность |
|---|---|---|
| Patriot | 4 × PAC-3, пусковая разворачивается на цель | 10–450 |
| Гепард | 2 × 35 мм, башня и стволы со слежением и упреждением, 160 очередей | 135 (слежение с 195) |
| Панцирь-С1 | 12 × 57Э6 и 2 × 30 мм; модуль поворачивается, пакеты и стволы поднимаются | ракеты 25–225, пушки 90 |
| С-400 | 4 × 48Н6, вертикальный холодный старт, РЛС обзора на прицепе | 30–720 |
| С-500 | 2 × 77Н6, холодный старт, самые быстрые ракеты | 40–1050 |
| IRIS-T SLM | 8 ракет, вертикальный пуск, быстрые и манёвренные | 15–600 |
| NASAMS | 6 × AMRAAM, наводимая пусковая на прицепе | 10–450 |
| Бук-М2 | 4 × 9М317 на направляющих, башня с РЛС подсвета | 20–675 |
| Тор-М2 | 8 × 9М338 вертикально из башни, быстрая реакция против дронов | 8–240 |
| P1-SUN | 8 дронов-перехватчиков против Шахедов и Герань; своей РЛС нет — стреляет по данным сети | 5–675 |
Обслуживающая техника (тоже пультами или /airdef deploy <ключ>): РЛС дальнего обнаружения (radar,
видит на 2,5 км с высокой мачты, хуже прячутся за рельефом), склад боеприпасов (depot), ТЗМ (tzm),
станция РЭБ (ew), прожектор (light). Новые комплексы: irist, nasams, buk, tor, p1sun.
Согласование огня. Комплексы делят цели между собой: на обычную цель идёт одна ракета, на баллистическую две; чем ближе цель к своей точке попадания, тем больше перехватчиков разрешено на неё сразу (за ~12 с до удара ещё один, за ~5 с — ещё один). Комплекс, у которого кончились ракеты или идёт перезарядка, цель не держит; тот, кто не смог навестись за ~2 с, отпускает её другим. Пушки расходятся по разным целям. Первыми бьют по самым опасным (быстрым и тяжёлым) целям, при этом ложные «Герберы» выглядят для них как настоящие. Геометрия встречи проверяется по движению обоих объектов за тик, а остаточный шанс учитывает фактическую скорость перехватчика.
Энергетика перехватчика. После холодного выброса ракета разгоняется, но двигатель работает конечное игровое время. После выгорания ракета летит по инерции, теряет скорость и манёвренность; при недостаточной скорости сопровождение срывается. Факел, звук двигателя и новый дым прекращаются при выгорании и в live, и в повторе; уже созданный дым продолжает рассеиваться.
Последний шанс (/airdef lastchance on|off, по умолчанию вкл). Комплекс стреляет и по классу целей вне своих ролей
(С-400, С-500 и Patriot по умолчанию не бьют дроны), если цель долетит до своей точки меньше чем за 10 с и на ней ещё нет
ничьего перехватчика. Комплексу с пустыми ролями (огонь запрещён) это не касается. /airdef why пишет «последний шанс».
Дальний пуск по РЛС. С-400, С-500 и Patriot могут стрелять дальше своей дальности (до 1,6×) по цели, которую держит
свежим треком РЛС дальнего обнаружения в радиусе связи: не чаще раза в 15 с, при не менее чем половине боезапаса, только по
своим ролям и только пока в обычной дальности нет цели; шанс поражения на краю вдвое ниже. /airdef why: «дальний пуск по РЛС».
Роли по умолчанию (в сводке в квадратных скобках: Д — дроны, Г — реактивные, К — крылатые, С — сверхзвуковые, Б — баллистика): Гепард ДГК, Панцирь ДГКС, Patriot ГКСБ, С-400 ГКСБ, С-500 СБ. Сбитый дрон падает с остатком скорости, и его боевая часть может сдетонировать на земле.
Звук
Все звуки синтезированы (tools/gen_sounds.py: шум, тоны, фильтры и эхо на numpy, кодирует ffmpeg), сэмплов нет.
У каждого объекта свой звук и своя дальность слышимости (attenuation_distance в sounds.json):
- двигатели: двухтактный мопед шахеда (220 м), турбина Герани-3, электромотор Ланцета, тяжёлый рёв крылатых ракет (320 м),
ракетный рёв Х-22, Циркона и перехватчиков, нарастающий визг падающей баллистики и её ударная волна (700–900 м);
Двигатели дронов и ракет — постоянные источники звука (API 20,
render.sound-sources, #95): один источник на объект идёт за его настоящей позицией, зажигается с нарастанием, при сбитии «захлёбывается» (тон падает, громкость гаснет за секунду) и замолкает вместе с объектом; в повторе и экспорте источники берутся из записанных траекторий и времени повтора (перемотка и смена плана пересоздают их). Одновременно звучат 24 ближайших и громких, остальные «виртуальные». Взрывы, пуски и выстрелы остались разовыми, с задержкой по скорости звука. Баллистика (визг при падении) тоже разовая. Зацикливается устойчивая часть файла (начало и затухание в конце обрезаны), стык — 50 мс. - пуски: хлопок и рвущийся рёв Patriot, свистящий старт Панциря, глухой газовый выброс и затем огромный рёв С-400, у С-500 ещё ниже и дольше (до 1 км);
- пушки: тяжёлые 35-мм очереди Гепарда и частые 30-мм Панциря;
- взрывы: хлопок, суббас, рокот и треск обломков с длинным эхом, у разных калибров по-разному (до 900 м).
Эффекты
Мод передаёт движку шейдер пост-обработки (airdef-mod/shaders/effects.wgsl):
- объёмный огненный шар: шум, «прошитый» лучом камеры, с переходом раскалённое ядро → пламя → чёрный дым, который поднимается и рассеивается;
- вспышка с ореолом и засветкой всего кадра;
- ударная волна, искажающая картинку за собой;
- тепловое марево над огнём;
- свечение факелов ракет, дульных вспышек, красных трассеров и маркеров цели;
- освещение от огня: взрывы, факелы и трассеры подсвечивают землю и технику, ночью намного сильнее.
У Гепарда и Панциря каждый снаряд — летящий красный трассер.
Всё размещено в мире и скрывается за тем, что стоит перед ним (по глубине сцены). Выключить: /airdef shader off.
Устройство
.gitmodules URL отдельного репозитория движка
horizon/ git submodule: точный SHA форка Horizon. Что в нём меняется:
crates/horizon-mod-sdk/wit/horizon.wit render.set-models, spawn-particles, play-sound,
query-ground / ground
crates/horizon-mods/src/runtime.rs хост этих функций
crates/horizon-client/src/game/mod_models.rs интерполяция и отрисовка моделей, частицы
crates/horizon-client/src/gfx/mod_post.rs пост-проход мода: render.set-post / set-params
airdef-core/ SDK-free сборка общего ядра; использует те же исходники sim, без копии
airdef-mod/ адаптер: Rust → WebAssembly
src/sim/mod.rs симуляция: дроны, ракеты, ПВО, эффекты (20 тиков/с)
src/sim/battery.rs конфигурации пусковых и роли общей РЛС
src/sim/launch.rs резервирование ячеек и анимация крышек ТПК
src/lib.rs предметы, команды, сохранение, передача в движок
src/panel.rs сводка, src/radar.rs — радар, src/monitor.rs — монитор комплекса
assets/airdef/sounds звуки (генерирует tools/gen_sounds.py)
shaders/effects.wgsl шейдер взрывов и свечения
assets/, data/ модели, текстуры, предметы (генерирует tools/gen_models.py)
tools/gen_models.py генератор моделей и текстур
legacy/ первая версия: датапак на командах и контент-мод
run-home/ тестовая игровая папка (для проверок через horizon-ctl)
Как рисуются модели. Мод раз в тик отдаёт список объектов: блок-модель, позиция, кватернион и масштаб. Движок держит для каждого id две последние позы и в каждом кадре рисует объект между ними:
- позиция интерполируется линейно, поворот — через slerp;
- освещение учитывает поворот модели;
glowдаёт полную яркость (пламя, вспышки).
Модели — обычные блочные JSON-модели, по одной на часть: корпус, винт, башня, стволы. Их генерирует
tools/gen_models.py. Координаты элементов должны быть в пределах −16..32, иначе Horizon отбросит модель.
Рельеф и коллизии приходят асинхронно через ground/ray/section queries. Высотной карты недостаточно для точного попадания: известные блоки и формы проверяются отдельно; ожидание/Unknown не считается доказанным свободным путём. Историческое отображение повтора отделено от live-геометрии симуляции.
Известные ограничения
- Для #122 воспроизведено и исправлено исчерпание fuel при массовых взрывах: каждый взрыв больше не обходит всю карту высот. Проверка на конкретном Windows-компьютере ещё нужна; прирост FPS этим исправлением не обещается.
- Мод клиентский: дроны и ПВО видит только тот, у кого он стоит. Мультиплеер не поддерживается.
- Окно Horizon на macOS не рисует кадры, пока оно перекрыто другими окнами (это поведение движка).
- Шейдер работает, только если не включён шейдер-пак Horizon (они взаимоисключающие).
Разработка и обновление закреплённого движка: docs/ENGINE.md.


