Данный файл основывает свою аналитику на анализе исходного кода следующих погод из следующих модификаций:

ПогодаМодВерсия при анализе
HEATWAVELethalElementsForkyv1.4.2
SOLAR FLARELethalElementsForkyv1.4.2
SNOWFALLLethalElementsForkyv1.4.2
BLIZZARDLethalElementsForkyv1.4.2
TOXIC SMOGLethalElementsForkyv1.4.2
FIRESTORMCodeRebirthv1.6.9
HURRICANEWesley's Weathers / CodeRebirthv1.2.11 / v1.6.9
TORNADOCodeRebirthv1.6.9
METEOR SHOWERCodeRebirthv1.6.9
GODRAYSCodeRebirthv1.6.9
NIGHTSHIFTCodeRebirthv1.6.9
Моды "Kenji's Weathers" и "Wesley's Weathers" распространяются по закрытому коду, поэтому анализировать логику погод/узнать подробную информацию об их поведении не является доступным.

Анализ погод

Внизу указан всех публичных и доступных обычно погод, упоминаемых в инфобуке о погодах.

HEATWAVE

  1. Зона перегрева — триггер размером с уровень, реагирует только на игрока (не на технику или сущностей).
  2. Время до теплового удара рандомизируется один раз при входе в погоду.
  3. Статус "в зоне жары" сбрасывается моментально при выходе из триггера — накопительного эффекта вне зоны нет.
  4. Интенсивность частиц завязана на яркость солнца — жара слабее к вечеру/в тени.

Подробное описание

Анализируемый файл:

  • HeatwaveWeather.cs

  • Триггер-зона теплового удара — не весь уровень, а BoxCollider с heatwaveTrigger.isTrigger = true, размером LevelBounds.size (SetupHeatwaveWeather(), ~строки 58–66). Маска коллайдера явно исключает всё, кроме игрока: excludeLayers = ~LayerMask.GetMask("Player", "PlayerRagdoll"), т.е. машины и сущности зону не триггерят (в коде есть закомментированная заглушка под круизер VehicleHeatwaveHandler, она не активна).

  • Время до теплового удара рандомизируется один раз при заходе в погоду: timeInHeatZoneMax = SeededRandom.NextDouble(TimeUntilStrokeMin, TimeUntilStrokeMax), т.е. у каждого дня своя длительность "запаса", а не фиксированный таймер.

  • Статус "в зоне жары" держится, только пока коллайдер триггерится (OnTriggerStayPlayerEffectsManager.isInHeatZone = true), и сбрасывается моментально при выходе (OnTriggerExitheatTransferRate = 1f), т.е. отступление в помещение/тень снимает эффект сразу, накопительного "остывания" не предусмотрено вне зоны.

  • Интенсивность частиц марева и сила эффекта завязаны на реальную яркость солнца через кривую: CooldownHeatwaveVFX() берёт sunLightData.intensity / startingSunIntensity, прогоняет через heatwaveIntensityCurve, и результат (reductionFactor) записывается в HeatwaveWeather.Instance.timeOfDayFactor. Жара реально слабее к вечеру/в тени.

SOLAR FLARE

  1. Одна из 4 интенсивностей выбирается один раз на весь цикл вспышки, определяет набор возможных поломок.
  2. Электрические "поломки" идут тактами, а не постоянным фоном: ~раз в 43 сек (3%) игрового дня.
  3. Затрагивает не только связь, но и врагов/ловушки: олдбёрды ("Old bird") глушатся и оглушаются, турель уходит в берсерк-режим, мины детонируют дистанционно, гнездо олдбёрдов может пересоздать нового олдбёрда сверх дневного лимита.
  4. Двери ломаются вдвое реже (раз в 6% дня) и только у хоста.
  5. Радар глушится через специальный параметр и при любой интенсивности.

Подробное описание

Анализируемый файл:

  • SolarFlareWeather.cs

  • Интенсивность выбирается случайно из 4 значений FlareIntensity (Weak/Mild/Average/Strong) при входе в погоду (строка ~124), и от неё зависит, какие конкретно IsDoorMalfunction/IsTurretMalfunction/IsRadMechMalfunction включены во FlareData — то есть тип "поломок" является фиксированным набором.

  • Раз в 3% игрового дня (normalizedTimeOfDay % 0.03f < 1e-4, Update() строка 213) — это примерно раз в ~43 сек за 24-мин игровой день — запускается моргание всех запитанных ламп (LightFlickerCoroutine) и попытка электрической поломки (ElectricalMalfunctionCoroutine).

  • Эта попытка проходится по каждому найденному турели/RadMech-гнезду/мине (собраны один раз при входе в погоду через FindObjectsByType), и для каждого типа — свой шанс и свой флаг: RadMechMalfunctionChance, TurretMalfunctionChance, LandmineMalfunctionChance — все настраиваемы через конфиг.

  • Что происходит при "поломке" (ElectricMalfunctionCoroutine, строки 308–395):

    • RadMech: моргает "лицом", на RadMechStunDuration секунд оглушается, потом снова включает прожектор.
    • Турель: получает Hit(1, ...), что переводит её в берсерк-режим (турель начинает стрелять хаотично) до конца случайного тайминга. Имитация удара лопатой по турели.
    • Гнездо RadMech (EnemyAINestSpawnObject): гнездо уничтожается и на его месте заново спавнится RadMech, если позволяет лимит currentMaxOutsidePower, т.е. вспышка может внепланово "родить" дополнительного RadMech-а сверх обычного дневного лимита спавна.
    • Мина: получает Hit(1, ...), детонируя дистанционно. Имитация эффекта будто игрок пробежался по мине/ударил её.
    • Двери: раз в 6% дня (% 0.06f) запускается DoorMalfunctionCoroutine, притом только у хоста (isHostingGame) и только если flareData.IsDoorMalfunction включён для текущей интенсивности. Каждая большая дверь получает случайное состояние open/closed независимо от того, что нажимали игроки.
  • Радар глушится техническим Custom Pass Volume (CPV) на камеру радара при входе в погоду (GlitchRadarMap()) и не связано с интенсивностью — глюк на радаре есть при любой силе вспышки.

SNOWFALL / BLIZZARD

  1. Замедление от снега начинается не с нуля, а с порога толщины 0.4, дальше растёт линейно до потолка ~2.5.
  2. "Под снегом" считается по высоте глаз игрока — можно буквально утонуть в сугробе с головой.
  3. Занижение конфига урона от обморожения компенсируется дополнительным замедлением, а не просто "смягчает" снег.
  4. Каждый шаг игрока протаптывает тропу, ускоряющую движение по ней. Протаптывание игроком троп равнозначно любому изменению луны руками.
  5. Ветер определяется линкастом от головы игрока — простое укрытие за любым объектом полностью убирает эффект.
  6. Направление ветра меняется циклично с плавной интерполяцией с определенным интервалом.
  7. Ледяные волны летят строго по направлению ветра на момент запуска и автоматически не действуют внутри помещений — не нужно прятаться от них внутри комплекса вообще.
  8. В машине скорость охлаждения снижена (в 20 раз) — частичная защита без полного укрытия.

Подробное описание

Анализируемые файлы:

  • SnowfallWeather.cs

  • BlizzardWeather.cs

  • Замедление от снега — не бинарное "в снегу/не в снегу", а формула с порогом: snowMovementHindranceMultiplier = 1 + (5 * Mathf.Clamp01((snowThickness + metaSnowThickness - 0.4f) / 2.1f)) (SnowfallVFXManager.Update()) — штраф начинает копиться только после толщины снега 0.4, дальше растёт линейно и упирается в потолок при толщине ~2.5, т.е. мелкий снег в начале дня практически не мешает.

  • "Под снегом" (isUnderSnow) считается по высоте глаз игрока: feetPositionY + snowThickness >= localPlayerEyeY - eyeBias — если накопившийся снег доходит выше уровня глаз минус 0.2, экран засвечивается ("забелен"). Буквально означает, что можно физически утонуть в снегу с головой, если сугроб вырос достаточно.

  • Обморожение зависит от настроенного конфига урона: если в настройках снизить FrostbiteDamage относительно стандартных 10 — движок компенсирует это дополнительным замедлением, а не просто уменьшает урон линейно (metaSnowThickness в формуле выше).

  • В метель (BLIZZARD) добавляется отдельная механика ветра: isLocalPlayerInWind вычисляется рейкастом/линкастом от головы игрока в сторону источника метели на 20 метров (FixedUpdate()) — если по пути нет преград (стен, географии), считается что игрок обдувается, и тогда externalForces += windDirection * windForce физически толкает игрока. Простое укрытие за любым объектом ландшафта полностью убирает эффект ветра — необязательно помещение, подойдёт любая скала/стена.

  • Направление ветра меняется циклично, windChangeInterval секунд (по умолчанию поле 30), плавной интерполяцией поворота (ChangeWindDirectionCoroutine).

  • Ледяные волны (GenerateChillWaveCoroutine) идут строго по прямой через весь уровень против направления ветра на момент их запуска — то есть волна всегда летит "оттуда, откуда дует", а не случайным образом; количество волн и интервал между сериями рероллятся каждый раз (MinWaveCount..MaxWaveCount, MinWaveInterval..MaxWaveInterval), и волна автоматически скрывается, если игрок находится внутри помещения (!localPlayerController.isInsideFactory в while-цикле).

  • В машине (physicsParent != null) скорость охлаждения снижена (heatTransferRate = 0.05f против 1f на улице) — машина частично защищает от холода ветра, даже без полного укрытия.

TOXIC SMOG

  1. Ядовитые облака — не сплошная зона, а дискретные точечные ловушки, раздельно снаружи/внутри, с масштабом количества под размер подземелья.
  2. Спавн облаков гарантированно избегает входов (20 м) и не кучкуется теснее 5 м друг к другу.
  3. Общий туман (не облака) — отдельный объёмный туман с рандомной плотностью каждый день.

Подробное описание

Анализируемые файлы:

  • ToxicSmogWeather.cs

  • Облака ядовитых испарений — не сплошная зона, а **дискретные точечные ловушки (hazardPrefab), которые спавнятся отдельно снаружи (fumesContainerOutside, привязаны к outsideAINodes) и отдельно внутри комплекса (fumesContainerInside, привязаны к insideAINodes), причём количество внутри — не то же самое, а домножено на модификатор размера подземелья: factoryFumesAmount = Ceil(fumesAmount * FactoryAmountMultiplier * dungeonSize) — на больших подземельях облаков внутри пропорционально больше.

  • Спавн облаков гарантированно избегает входов: minDistanceFromBlockers = 20f от EntranceTeleport (и от границ корабля — снаружи), и облака не спавнятся друг к другу ближе minDistanceBetweenHazards = 5f (IsPositionValid) — то есть облака физически не могут "затопить" точку входа/выхода целиком, почти всегда останется безопасный коридор прямо у входа.

  • При переключении между "снаружи" и "внутри" контейнеры физически включаются/выключаются реципрокно (OnEnable/OnDisable): пока игрок снаружи, внутренние облака выключены — то есть переход в помещение полностью убирает нагрузку от внешних испарений, они не тикают в фоне, пока неактивны.

  • Туман (не облака, а общая дымка) генерируется как LocalVolumetricFog на весь уровень с рандомной плотностью (smogFreePath между MinFreePath/MaxFreePath из конфига) — плотность каждый день своя.

TORNADO

  1. Три типа с разным поведением: Water вдвое медленнее и без урона (заглушка), Fire — урон горением на средней зоне статус-эффекта, Smoke — единственный тип, который физически подбрасывает игрока, и его зона статус-эффекта самая дальняя.
  2. Подбрасывает только Smoke-тип, при накоплении таймера у "глаза" торнадо (≤10 м), фиксированно на 10 секунд, с последующей спиральной силой вокруг точки броска.
  3. Притяжение к торнадо не обнуляется без прямой видимости — падает до 12.5%, а не до нуля; Smoke тянет в 3.75 раза сильнее Fire/Water.
  4. Полный иммунитет даёт нахождение в здании, в корабле, на ховерборде/технике/лестнице.

Подробное описание

Анализируемые файлы:

Сама погода (TornadoWeather.cs) — простая обёртка: -3/+6/-3 лимиты, ждёт 20 сек, находит точку через GetRandomTargetPosition и спавнит одно торнадо-энтити (Tornados).

  • Три типа торнадо (TornadoType: FIRE/SMOKE/WATER), у каждого свой набор эффектов:
    • WATER: скорость движения торнадо сразу делится пополам при инициализации (initialSpeed /= 2) — самый медленный тип. Урон по игроку не реализован (// Drown the player. — комментарий-заглушка), статус-эффект WATER действует только в ближней зоне (closeRange = 10f).
    • FIRE: статус-эффект действует в средней зоне (midRange = 20f), при близком контакте (см. ниже) наносит 3 урона с причиной смерти Burning.
    • SMOKE: статус-эффект действует дальше всех (longRange = 30f), наносит 2 урона, и это единственный тип, для которого вообще проверяется затягивание внутрь и подбрасывание игрока (HandleLocalPlayerInsideTornado вызывается только if (tornadoType == TornadoType.Smoke)) — FIRE и WATER торнадо никогда физически не подбрасывают игрока, только тянут и жгут/окуривают.
  • Затягивание (только SMOKE): если игрок ближе 10 м от "глаза" торнадо и выполняются базовые условия (TornadoConditionsAreMet), таймер timeSinceBeingInsideTornado копится, иначе плавно спадает; при достижении конфиг-порога ConfigTornadoInsideBeforeThrow игрока подбрасывает (SetPlayerFlingingServerRpc) на фиксированные 10 секунд (StopFlingingPlayer ждёт ровно 10 сек), после чего он крутится по спирали вокруг throwingPoint (CalculateSpiralForce = крест-произведение направления к центру и направления вверх, плюс сама тяга к центру).
  • Притяжение к торнадо действует всегда (кроме WATER — там весь HandleTornadoDamageAndPulling вообще не вызывается: if (tornadoType != TornadoType.Water) HandleTornadoDamageAndPulling(...)), и сила зависит от прямой видимости через несколько "глаз" (eyes[]): если есть чистая линия обзора хотя бы до одного глаза — тяга полная, если её нет ни у одного — тяга всё равно есть, но всего 12.5% от полной (0.125f * ConfigTornadoPullStrength). Дополнительно у Smoke-типа общий множитель тяги в 3.75 раза больше, чем у Fire/Water (0.75f против 0.2f) — Smoke-торнадо реально доминирующий тип по притяжению.
  • Урон применяется только на расстоянии ≤4 м прямой видимости (bestDistanceLOS > 4f — досрочный выход), раз в 0.5 сек (DamageTimer).
  • Полный иммунитет к торнадо даёт нахождение внутри фабрики, внутри корабля, в вагонетке/анимации с транспортом, на ховерборде, на лестнице, в анимации с врагом или уже во время самого подбрасывания (TornadoConditionsAreMet — все эти флаги должны быть false, иначе торнадо игрока полностью игнорирует).

Погода: METEOR SHOWER ("Метеоритный дождь")

  1. Фоновые "красивые" метеоры в небе декоративны и не падают — угрозу несут только метеоры, запускаемые отдельным таймером через 25 сек после старта.
  2. Направление атаки фиксируется один раз на весь день (если не выбран Random) — все метеоры дня летят с одной стороны света.
  3. Спавн новых метеоров прекращается по истечении доли дня, но уже летящие долетают.
  4. Удар может заспавнить один из 6 видов кристаллов и создаёт взрыв + уничтожение деревьев в радиусе 15 м.

Подробное описание

Анализируемые файлы:

  • MeteorShower.cs

  • Meteors.cs

  • При активации сразу спавнит декоративные фоновые метеоры высоко в небе (SpawnOverheadVisualMeteors, 15–45 штук + один "большой" с масштабом 7.5–12.5) — они не падают и не угрожают, только летают по кругу (SetupAsLooping, StopMoving()).

  • Опасные метеоры начинают падать только через 25 секунд после старта погоды (MeteorSpawnerHandler), пачками от minMeteorsPerSpawn до maxMeteorsPerSpawn штук с рандомной паузой между пачками.

  • Направление атаки выбирается один раз за весь день случайно из 5 вариантов (Random/East/West/North/South), если выпало не Random, то все метеоры этого дня будут падать с одной и той же стороны света (CalculateSkyOrigin), что даёт возможность заранее понять, откуда ждать угрозу, посмотрев на пару первых падений.

  • Спавн новых метеоров автоматически прекращается по достижении normalisedTimeToLeave (доля игрового дня, конфигурируема), но уже летящие в этот момент метеоры долетают и падают как обычно, просто новых больше не появляется.

  • При ударе о землю: шанс (ConfigMeteorShowerMeteoriteSpawnChance) заспавнить один из 6 видов кристаллов-руды (Аметист/Сапфир/Изумруд/Кварц/Рубин/Топаз) прямо в точке падения, плюс взрыв (CRUtilities.CreateExplosion, радиус 15, сила 4) и уничтожение деревьев в радиусе 15 м, плюс кратер, который висит 60 секунд и потом исчезает.

Анализ скрытых погод

Искомые погоды никак не анализируются.

FIRESTORM / HURRICANE

Важное открытие сразу: у FireStormWeather и HurricaneWeather фактическое создание торнадо — мёртвый код. В обоих файлах метод SpawnTornado() содержит только пустой for-цикл с закомментированной строкой создания энтити (// var tornado = RoundManager.Instance.SpawnEnemyGameObject(...)). Рабочая версия спавна есть только в TornadoWeather.cs: RoundManager.Instance.SpawnEnemyGameObject(target, -1, -1, LethalContent.Enemies[CodeRebirthEnemyKeys.Tornado].EnemyType). Это стоит явно пометить в инфобуке как "на момент разбора кода не функционирует / вероятно WIP-заглушка", а не описывать так, будто механика активна.

Анализируемый файл:

  • FireStormWeather.cs

  • Меняет лимиты спавна врагов: outsidePower: -3, insidePower: +6, dayTimePower: -3, т.е. меньше уличных угроз, но заметно больше внутренних, и это единственный реально работающий эффект на данный момент.

  • При включении собирает список outsideAINodes, отфильтрованных по близости (CullNodesByProximity(nodes, 5.0f, true, true)), и через 20 секунд после старта дня пытается выбрать точку спавна — но дальше упирается в пустой цикл.

GODRAYS

Исходный код:

  • GodRaysWeather.cs

  • Каждый GodRay описывается верхней точкой в "небе" (TopPosition) и нижней точкой на земле (BottomPosition) с своими радиусами — GodRaySpotlightData вычисляет через теорему косинусов угол и позицию света так, чтобы луч визуально сходился в правильную точку неба.

  • У основания каждого луча стоит триггер-коллайдер с уроном (DoTheThingWithColliderBetterCooldownTrigger), настроенный на смерть от сгорания (DeathAnimation.Burnt, CauseOfDeath.Burning), с сообщением игроку "Melting..." / "Your body is melting.........".

  • Меш триггера строится как конус из pointCount (по умолчанию 40) точек вокруг основания луча — то есть зона поражения не точка, а полноценная окружность заданного BottomRadius, и стоять на самом краю круга физически безопаснее, чем в центре, но триггер есть по всей площади круга.

  • Луч динамически подстраивается под положение и farClipPlane камеры игрока (OnBeginCameraRendering) — рескейлится каждый раз, когда меняется дальность прорисовки или позиция камеры.

Built with LogoFlowershow