Killing Floor: количество мобов на волне, MaxZombiesOnce и задержка между сквадами
В 2016 году на killingfloor.ru спросили, как сделать, чтобы мобы выходили больше и быстрее, не трогая настройки песочницы: поднять MaxZombiesOnce и сократить паузу между сквадами. Flame ответил разбором KFGameType.SetupWave() и таймера спавна. Здесь его краткое изложение.
Весь состав мутантов Killing Floor, от Клота до Патриарха, в двух вариантах текстур. Каждый из них учитывается в лимитах ниже.
Два разных ограничения
| Переменная | Смысл |
|---|---|
TotalMaxMonsters | Сколько мобов всего будет за волну (не одновременно) |
MaxMonsters | Сколько мобов может быть живо одновременно. На практике равна MaxZombiesOnce |
Во время волны мобы спавнятся, пока число живых не дойдёт до MaxMonsters. Убили моба — число упало — появляется новый. И так, пока не кончится общий лимит волны.
Как SetupWave считает мобов
- Берётся
WaveMaxMonstersтекущей волны из массиваWaves:
Waves[0]=(WaveMask=2013265920,WaveMaxMonsters=20,WaveDuration=180,WaveDifficulty=3.000000)
- Умножается на модификатор сложности:
| Сложность | GameDifficulty | Модификатор |
|---|---|---|
| Новичок | 1 | 0.7 |
| Нормально | 2+ | 1.0 |
| Сложно, Самоубийственно | 4, 5 | 1.3 |
| Ад на земле | 7 | 1.7 |
Комментарий в коде всё ещё называет ветку 7+ «Suicidal»: он написан до появления «Ада на земле».
- И на модификатор числа игроков (игроки плюс боты):
| Игроков | 1 | 2 | 3 | 4 | 5 | 6 | больше |
|---|---|---|---|---|---|---|---|
| Модификатор | 1 | 2 | 2.75 | 3.5 | 4 | 4.5 | игроки × 0.8 |
- Результат ограничивается:
NewMaxMonsters = NewMaxMonsters * DifficultyMod * NumPlayersMod;
TotalMaxMonsters = Clamp(NewMaxMonsters, 5, 800);
MaxMonsters = Clamp(TotalMaxMonsters, 5, MaxZombiesOnce);
Clamp(x, min, max) держит x в пределах отрезка. Отсюда два вывода:
- Стандартный KF никогда не даст больше 800 мобов за волну, что бы ни стояло в
WaveMaxMonsters. Чтобы снять предел, нужно поменять константу вSetupWave()своего геймтайпа. В SRGameType из темы стоялоClamp(NewMaxMonsters,5,1100). TotalMaxMonstersпочти всегда большеMaxZombiesOnce, поэтомуMaxMonstersна деле равнаMaxZombiesOnce.
Пример: 6 игроков на «Аде на земле» при WaveMaxMonsters=20 дают 20 × 1.7 × 4.5 = 153 моба за волну, одновременно живых не больше MaxZombiesOnce.
Где что прописывать
Waves—config-массив, объявленный вInvasion. Каждый унаследованный геймтайп читает свою секцию, так что если вKillingFloor.iniесть секция[ServerPerks.SRGameType]со строкамиWaves, значения берутся оттуда.MaxZombiesOnceобъявлена вKFGameTypeкакglobalconfigи читается только из[KFMod.KFGameType]. В[ServerPerks.SRGameType]её менять бесполезно.
[KFMod.KFGameType]
MaxZombiesOnce=64
Интерфейс песочницы не даёт поставить больше 64, но в ini значение может быть выше. Подумайте, прежде чем это делать: у игроков со слабыми ПК начнутся тормоза, а к 6-й волне нагрузка копится и вылезает рассинхрон (пропадает оружие, не видно мобов). 64 — разумный потолок, а ускорить спавн сквадов обычно полезнее.
Пауза между сквадами
В таких обсуждениях всегда всплывает WaveStartSpawnPeriod, но, по разбору кода от Flame, эта переменная нигде не используется. Настоящая задержка находится в Timer() состояния MatchInProgress, в ветке bWaveInProgress:
if ( nextSpawnSquad.length > 0 )
NextMonsterTime = Level.TimeSeconds + 0.2;
else
NextMonsterTime = Level.TimeSeconds + CalcNextSquadSpawnTime();
Пока сквад выставляется, мобы идут каждые 0.2 с. Между сквадами пауза берётся из CalcNextSquadSpawnTime(), в среднем около 1.5 с на «Аде на земле». Чтобы спавн шёл почти непрерывно, переопределите состояние в своём геймтайпе и поставьте константу:
state MatchInProgress
{
function Timer()
{
// copy the whole stock KFGameType.MatchInProgress.Timer() body here,
// then replace the NextMonsterTime branch with:
NextMonsterTime = Level.TimeSeconds + 0.2;
}
}
Скопируйте тело стандартного Timer() целиком и поменяйте только эту строку. Остальные функции состояния копировать не нужно.
Что делает CalcNextSquadSpawnTime()
Стандартную функцию KFMod.KFGameType.MatchInProgress.CalcNextSquadSpawnTime() Flame выложил в теме «Популяция монстров» на форуме killingfloor.ru (вопрос был, как заставить мобов быстрее выходить из спаунеров, если MaxZombiesOnce поднят до 64). Базовое значение — KFLRules.WaveSpawnPeriod, дальше оно умножается на коэффициенты по числу игроков:
| Игроков | Ранние волны | Поздние волны |
|---|---|---|
| 3 и меньше | 1.0 (без изменений) | 1.1 |
| 4 | 0.85 | 1.0 |
| 5 | 0.65 | 0.75 |
| 6 и больше | 0.3 | 0.60 |
«Ранние волны» — это WaveNum < 2 для короткой игры, WaveNum < 4 для обычной и WaveNum < 7 для длинной. При своей длине игры (GL_Custom) коэффициенты ранних волн (0.85 / 0.65 / 0.3) действуют на всех волнах. На «Сложно» и выше (GameDifficulty >= 4.0) время дополнительно умножается на 0.85. В конце синусоида добавляет «пики и спады» интенсивности спавна:
SineMod = 1.0 - Abs(sin(WaveTimeElapsed * SineWaveFreq));
...
NextSpawnTime += SineMod * (NextSpawnTime * 2);
Поэтому менять нужно переменную var() float SineWaveFreq; — она задаёт частоту этой синусоиды, а с ней скорость и интенсивность появления зедов.
WaveCountDown — совсем другое: это отсчёт времени у трейдера между волнами, а не задержка спавна.
Итог
| Цель | Где |
|---|---|
| Мобов одновременно | MaxZombiesOnce в [KFMod.KFGameType] |
| Мобов за волну | WaveMaxMonsters в Waves, в секции своего геймтайпа |
| Больше 800 за волну | Поменять Clamp в своём SetupWave() |
| Быстрее сквады | Переопределить MatchInProgress.Timer() в своём геймтайпе |
| Время между волнами | Время трейдера, а не код спавна |
Вопросы и ответы
- Почему MaxZombiesOnce в секции [ServerPerks.SRGameType] ничего не меняет?
- MaxZombiesOnce объявлена в KFGameType как globalconfig, поэтому читается только из секции [KFMod.KFGameType] файла KillingFloor.ini, какой бы геймтайп ни стоял на сервере.
- Меняет ли WaveStartSpawnPeriod задержку между появлением мобов?
- По разбору кода на killingfloor.ru — нет: эта переменная в коде игры нигде не используется. Пауза между сквадами берётся из CalcNextSquadSpawnTime().