Группы спавна
Группы спавна - это именованные наборы класснеймов с условиями, которые можно переиспользовать сразу в нескольких точках и делать состав спавна зависимым от времени суток, погоды и случая.
Что дают группы
- Переиспользование: одна группа (
@zombies) подключается в десятках точек; правите её в одном месте - меняется везде. - Условный состав: две группы
@dayAnimalsи@nightAnimalsв одномspawnListточки - днём спавнятся одни существа, ночью другие. - Погодные существа: волки в туман, особые зомби в грозу.
- Редкие появления: группа с
chance: 0.15попадает в спавн не каждый цикл (редкий патруль/босс).
Как это работает
Точка по-прежнему сама триггерит спавн (вход игрока, cooldown, triggerWorkingTime). Группа не спавнит сама - она лишь определяет состав пула класснеймов, из которого точка выбирает случайный элемент при каждом срабатывании.
В момент спавна точка строит "эффективный пул": разворачивает все @group-ссылки из своего spawnList с учётом условий группы и смешивает их с обычными класснеймами. Обычные точки (без @) ведут себя ровно как раньше - эффективный пул идентичен spawnList.
Режим выбора группы: combined или exclusive 2.1
Поле groupSelectMode на точке задаёт, как точка выбирает сущности из нескольких @group-ссылок за один цикл спавна.
combined (по умолчанию)
Все прошедшие условия группы разворачиваются в один плоский пул вместе с обычными класснеймами. Затем точка делает spawnMin..spawnMax случайных выборок из этого пула - каждая сущность выбирается независимо. Если поле не задано - режим combined.
spawnList: ["@Dogs", "@Boars"], spawnMin: 3, spawnMax: 5
→ за цикл может получиться: 1 собака + 2 кабана + 2 собаки (смесь из обеих групп)exclusive - одна группа за цикл
За цикл спавна точка выбирает одну группу из прошедших условия и спавнит spawnMin..spawnMax сущностей из её состава. Так получают "3-5 плотей ИЛИ 3-5 собак ИЛИ 3-5 кабанов" - каждый раз другая группа целиком.
{
"pointId": 36,
"spawnMin": 3,
"spawnMax": 5,
"groupSelectMode": "exclusive",
"spawnList": [
"@Dogs_1",
"@Plots_1",
"@Boars_1",
"@Cats_1",
"@Tushkans_1"
]
}Алгоритм exclusive:
- Из top-level
@group-ссылок точки отбираются группы, прошедшие слой доступа (isDisabled/spawnOnce/spawnTime/chance/weather).chanceбросается здесь один раз - это по-прежнему слой доступа, а не вес. - Выбирается одна случайная группа.
- Её состав разворачивается в эффективный пул (включая вложенные
@group- со своими условиями). - Дальше - как обычно:
spawnMin..spawnMaxвыборокGetRandomElementиз пула,|chanceна списке сущностей так же работает.spawnCountLimitограничивает итоговое число.
Поведение внутри выбранной группы идентично combined
Выбрав группу, точка спавнит из её состава ровно так же, как combined спавнил бы из единственного пула или списка спавна: с дубликатами (две одинаковые собаки) и элементным |chance. Никаких "по одному каждого" или "без повторов" - это сделано намеренно.
Ограничения exclusive
spawnListточки должен содержать только@group-ссылки. Прямой classname вexclusive-точке - ошибка валидации (он никогда не заспавнится: пул строится из состава выбранной группы). Если нужно заспавнить отдельный classname - заведите под него группу из одного элемента.isAiBandits-группы вexclusiveне поддерживаются (они идут отдельным путём и несовместимы с моделью "одна группа → N её сущностей"). Будет ошибка валидации при старте.- Если все группы провалили условия (или
spawnListпуст) - в этом цикле не заспавнится ничего (как и вcombinedпри пустом пуле).
Если у групп заданы spawnMin/spawnMax, счёт цикла следует выбранной группе: "3-5 волков ИЛИ ровно 1 медведь" задаётся диапазонами самих групп, а не точкой. См. spawnMin/spawnMax в списке полей.
Ссылка на группу в spawnList точки
На группу ссылаются из spawnList точки префиксом @:
"spawnList": [
"Animal_UrsusArctos",
"@dayAnimals",
"@nightAnimals"
]В этом примере эффективный пул = медведь + элементы группы @dayAnimals (если её условия пройдены) + элементы группы @nightAnimals (если её условия пройдены). Из получившегося пула точка выбирает случайный элемент, как и для обычного spawnList.
Префикс @
Префикс @ выбран потому, что ни один classname DayZ не начинается с этого символа - коллизий нет. Не ставьте пробелы вокруг @: @dayAnimals - правильно, @ dayAnimals - нет (мод почистит пробелы, но лучше писать сразу чисто).
Файлы групп
Группы хранятся в папке $profile:MPG_Spawner/Groups/. Каждый файл - массив групп (как точки в Points/):
$profile:MPG_Spawner/
├── Config.json
├── Points/
│ └── ...точки...
└── Groups/ ← папка групп спавна
├── Animals.json
├── Weather.json
└── ...Автоскан папки
Папка Groups/ сканируется целиком при запуске сервера - все *.json грузятся автоматически. Список файлов в Config.json (как pointsConfigs для точек) не нужен: просто положите .json-файл в папку, и мод его подхватит.
Группа с дублирующимся groupName (в том же или другом файле) - ошибка: в лог пишется ERROR, загружается первая встретившаяся группа с этим именем, дубликат пропускается. Имена чувствительны к регистру.
Поля группы
{
"groupName": "dayAnimals",
"isDisabled": false,
"spawnTime": "6-18",
"chance": 1.0,
"weather": [
"clear",
"cloudy"
],
"spawnList": [
"Animal_UrsusArctos",
"Animal_CanisLupus_Grey|0.5"
]
}groupName
groupName - уникальное имя группы. По нему на группу ссылаются из spawnList точки (@groupName). Не должно повторяться (дубликат → ERROR в лог).
Пример: "groupName": "dayAnimals",
isDisabled
isDisabled - отключить группу. Отключённая группа не разворачивается в пул ни в одной точке, но остаётся в файлах (удобно временно выключить набор существ, не удаляя конфиг).
Значение по умолчанию: 0 (включена). Старые конфиги без поля работают как раньше.
Пример: "isDisabled": 1,
spawnTime
spawnTime - окно игрового времени, в которое группа попадает в пул. Формат идентичен timing.workingTime точки:
всегда (значение по умолчанию): "0-24"
днём (с 6 до 18): "6-18"
ночью (с 18 до 6): "18-6" ← перенос через полночьПоддерживается перенос через полночь ("18-6" = с 18:00 до 06:00). Значение по умолчанию "0-24" - группа доступна круглосуточно.
Это игровое время
spawnTime - это игровое время (как triggerWorkingTime), а не реальное. Учитывайте настройки скорости течения игрового времени на вашем сервере.
chance
chance - групповой шанс доступа, число от 0 до 1. Бросается один раз за цикл спавна для группы: прошла → все её элементы попадают в пул; не прошла → группы в пуле нет.
Значение по умолчанию: 1.0 (всегда доступна).
Слой доступа, а не множитель
chance группы и chance отдельных элементов внутри её spawnList - разные слои:
chanceгруппы отвечает за доступ (будет ли группа в пуле вообще);chanceэлемента (через|, см. spawn.list) отвечает за выбор (выпадет ли именно этот элемент из пула).
Они не перемножаются. Пример: группа с chance: 0.15 и одним элементом Animal_UrsusArctos → в ~85% циклов спавна медведя в пуле не будет вовсе, в ~15% - он в пуле (с элементным chance 1.0, т.е. точно выпадет при выборе).
Как полностью отключить группу
Чтобы группа никогда не попадала в пул, используйте isDisabled: 1. chance: 0 тоже сработает как "никогда", но isDisabled - каноничный способ (и chance <= 0 трактуется как "поле не задано → 1.0").
weather
weather - массив типов погоды (логика ИЛИ), при которых группа попадает в пул. Пусто/отсутствует → группа доступна при любой погоде.
Допустимые значения:
| Тип | Условие (фиксированные пороги) |
|---|---|
clear | облачность < 40% |
cloudy | облачность ≥ 40% и нет дождя/снега/тумана |
rain | сила дождя ≥ 30% |
fog | сила тумана ≥ 40% |
snow | сила снегопада ≥ 30% |
storm | сила дождя ≥ 30% и скорость ветра ≥ 10 м/с |
Как это читается
["fog", "storm"] = группа в пуле, если сейчас туман ИЛИ гроза. ["rain"] = только в дождь. Пороги фиксированы и подобраны так, чтобы погода была визуально выражена - их нельзя менять из конфига намеренно (проще диагностировать). Невалидный тип (напр. "tornado") → WARN в лог, поле игнорируется, группа проверяется по остальным типам.
Пример:
доступна в дождь или грозу:
"weather": ["rain", "storm"],
доступна при любой погоде:
"weather": [],spawnOnce
spawnOnce - группа появляется один раз за сессию. После того как её контент реально заспавнился, группа больше не разворачивается в пул до рестарта сервера или перезагрузки конфига.
Значение по умолчанию: 0 (группа доступна каждый цикл спавна). Старые конфиги без поля работают как раньше.
Флаг ставится по факту реального спавна
Группа считается "заспавнившейся" только когда из неё создан объект, а не когда она попала в пул. Это значит:
- Если группа в пуле, но её элемент не выпал в выборке (точка выбрала другой элемент) - попытка не потрачена: при следующем цикле группа снова в пуле.
- Комбо с
chanceгруппы ниже 1: покаchanceне пропустит группу в пул, флаг не ставится.
Флаг НЕ снимается после смерти
spawnOnce означает "один раз за сессию", а не "один раз живой". Когда все объекты группы умрут, флаг не снимается - группа остаётся "израсходованной" до рестарта сервера или config-reload. Если нужно повторное появление после смерти - не используйте spawnOnce.
Сброс происходит при: рестарте сервера (in-memory состояние живёт только в RAM) и перезагрузке конфигурации (ResetTriggers).
Пример: уникальный босс, появляющийся один раз за рестарт:
{
"groupName": "alphaWolf",
"isDisabled": false,
"spawnTime": "18-6",
"chance": 0.3,
"weather": [
"fog",
"storm"
],
"spawnOnce": true,
"notificationTextSpawn": "⚠️ Появился Альфа-волк!",
"spawnList": [
"Animal_CanisLupus_Grey"
]
}notificationTextSpawn
notificationTextSpawn - собственная нотификация группы при реальном спавне её контента. Формат идентичен notifications.textSpawn точки: %1 = количество, %2..%5 = склонения через ; (см. GetDeclensionText).
Значение по умолчанию: "" (групповой нотификации нет).
Дополнительно к точечной
Групповая нотификация срабатывает в дополнение к точечной (если точечная задана). Игрок может получить обе за один цикл спавна: общую точечную и тематическую групповую. Они независимы - если у точки notificationTextSpawn пуст, групповая всё равно сработает.
%1 - это счётчик группы, а не общий
%1 в групповой нотификации = количество объектов именно этой группы, заспавненных в текущем цикле (а не общий queuedCount точки). Это чтобы "Появился 1 Альфа" было корректнее "Появилось 5 Альфа". Заголовок, иконка и время нотификации берутся из настроек точки - у группы их нет.
Пример:
группа-"волна" с тематическим текстом и склонением:
"notificationTextSpawn": "Накатило %1 %2.;заражённ|ый|ых|ых;"
→ при спавне 3 объектов группы: "Накатило 3 заражённых"
→ при спавне 1 объекта группы: "Накатило 1 заражённый"spawnList
spawnList группы - полностью идентичен spawnList точки: тот же формат "Class|chance|lifeTime|qty|health|foodStage". См. подробное описание в spawn.list точки.
Вложенные группы
В spawnList группы можно ссылаться на другие группы через @ - они развернутся рекурсивно. Циклы (@a→@b→@a) детектируются и пресекаются (в лог пишется WARN, повторное вхождение пропускается).
spawnMin
spawnMin - нижняя граница количества спавна самой группы. Работает в паре со spawnMax: если оба больше нуля, при "выборе" этой группы счёт берётся из её диапазона, а не из точечного или волнового. Приоритет: группа > волна > точка.
Условие срабатывания - однородный пул: за цикл в пуле остались записи только этой группы. Это гарантировано в exclusive-режиме; в combined правило действует, когда в spawnList точки одна эта группа. Смешанный пул (несколько групп, группа + прямые класснеймы) - счёт точечный, как раньше.
Значение по умолчанию: 0 - не задано. Выразить "спавнить 0" нельзя.
spawnMax
spawnMax - верхняя граница. Семантика и условие срабатывания - как у spawnMin. Правила нормализации при загрузке:
- задан только один из пары - это фиксированное количество (второй подтягивается к первому);
spawnMaxменьшеspawnMin- поднимается доspawnMin, в лог пишетсяWARN;- у
isAiBandits-группы пара игнорируется (количество задаётDynamicAIB.json), при заданных значениях -WARN.
Вложенные @group наследуют группу-источник от top-level ссылки: собственные spawnMin/spawnMax вложенной группы не действуют - счёт определяет та группа, на которую ссылается точка или волна.
isAiBandits
isAiBandits - группа ботов из стороннего мода AI_Bandits. При true группа не разворачивается в пул выбора класснеймов - вместо этого триггер запрашивает спавн целой группы AI_Bandits по имени (через bridge-мод MPG_Spawner_AIBandits).
groupName такой группы должно совпадать с GroupLocations[].name в DynamicAIB.json. Состав ботов (лут, одежду, оружие) настраивают в DynamicAIB.json, а не в spawnList этой группы - spawnList у isAiBandits-группы игнорируется (мод напишет WARN, если он задан).
Условия (spawnTime/weather/chance/isDisabled/spawnOnce) применяются к бандитской группе как к обычной. Несколько бандитских групп в одной точке спавнятся независимо: все прошедшие условия группы заспавнятся целиком в одном цикле.
Значение по умолчанию: 0 (обычная группа спавна). Подробности - в AI_Bandits интеграция.
Пример группы бандитов:
{
"groupName": "nightBandits",
"isAiBandits": true,
"isDisabled": false,
"spawnTime": "18-6",
"chance": 0.8,
"weather": [],
"spawnList": []
}spawnCountLimit уважается
Повторный спавн бандитской группы блокируется, пока живы боты точки (spawnCountLimit). spawnMin/spawnMax для ботов игнорируются - группа спавнится целиком, кол-во берётся из DynamicAIB.json.
triggerGates 2.3
triggerGates - имена гейтов - вето внешних bridge-модов на разворот группы в пул.
Проверка выполняется после остальных условий группы (isDisabled/spawnOnce/spawnTime/chance/weather) и на общем пути combined/exclusive/волн. AND-семантика; имена регистрозависимы; незарегистрированный гейт - fail-open + WARN (once). Это собственный список гейтов группы: точечный triggerGates на группы не распространяется. Заблокированная группа просто пропускается в этом цикле (DEBUG-лог) - как при провале любого другого условия.
Значение по умолчанию: null/пусто - группа не гейтится. См. Интеграция → Гейты.
Пример:
"triggerGates": ["mpg_ranks"]Полный пример
Groups/Animals.json
[
{
"groupName": "dayAnimals",
"isDisabled": false,
"spawnTime": "6-18",
"chance": 1.0,
"weather": [
"clear",
"cloudy"
],
"spawnList": [
"Animal_UrsusArctos",
"Animal_CanisLupus_Grey|0.5"
]
},
{
"groupName": "nightPredators",
"isDisabled": false,
"spawnTime": "18-6",
"chance": 0.8,
"weather": [
"fog",
"storm"
],
"spawnList": [
"Animal_CanisLupus_Grey",
"Animal_UrsusArctos|0.3"
]
}
]Использование в точке (Points/MyPoint.json)
{
"pointId": 100,
"shape": {
"position": "4246.0 0.0 5586.7",
"radius": "40.0"
},
"spawn": {
"positions": [
"4246.0 0.0 5586.7"
],
"min": 2,
"max": 5,
"list": [
"Animal_UrsusArctos",
"@dayAnimals",
"@nightPredators"
]
}
}Что делает эта точка:
- Днём (
@dayAnimals→spawnTime 6-18) + в ясную/облачную погоду → в пуле медведи и волки (50%). - Ночью (
@nightPredators→spawnTime 18-6) + в туман/грозу → в пуле ночные хищники, и сама группа появляется лишь в 80% циклов спавна (chance 0.8). - Медведь
Animal_UrsusArctosиз прямогоspawn.listточки - в пуле всегда, независимо от групп. - Из итогового пула точка выбирает случайный элемент, как обычно.
Крайние случаи
- Несуществующая группа (
@ghost, а такой группы нет ни в одном файлеGroups/) →ERRORв лог при старте и в рантайме; элемент выбрасывается из пула; точка продолжает работу. - Отключённая группа (
isDisabled: 1) → молча пропускается (как выключенный триггер). - Все группы отфильтрованы условиями (не то время/погода/
chance), а прямых класснеймов вspawnListнет → эффективный пул пуст → спавна нет (без ошибок, легальное "сейчас нечего спавнить"). - Цикл групп (
@a→@b→@a) →WARNв лог, второе вхождение пропускается, бесконечной рекурсии нет. spawnOnce-группа в пуле, но элемент не выпал в выборке → объект не создан → флаг не поставлен → попытка не потрачена, при следующем цикле группа снова в пуле.- Все объекты
spawnOnce-группы умерли → флаг не снимается до рестарта/config-reload. Группа остаётся "израсходованной". См. spawnOnce. - Несколько групп с
notificationTextSpawnв одном цикле → по одной нотификации на каждую группу (дополнительно к точечной). Порядок не гарантирован (флейвор-нотификации). - Вложенные группы и нотификация/spawnOnce → относятся к группе, указанной в точке (
@boss), а не к вложенной (@minionsвнутриboss). Origin = ближайшая группа по ссылке точки.
