Grass Stealth Mod

Grass Stealth

Vegetation Concealment System · Extension for Stealth 2.31
MCM Edition · v2.0 · Ivan Danko
UAУкраїнська
ENEnglish

Про мод

З цим модом трава стає справжнім укриттям. Присів або ліг у рослинності — і вороги проходять повз, не помічаючи тебе. Встав на повний зріст — і трава вже не ховає, незалежно від того, наскільки вона густа навколо.

Стелс залежить від того, наскільки висока і густа трава на локації прямо зараз. Якщо трава низька або її зовсім немає — ховатися нема де, мод не допоможе. Але з настанням ночі, в дощ або туман — ворог бачить погано навіть на відкритому полі.

Важливо: зброя в руках не робить тебе помітнішим. Ворог не бачить тебе краще через те, що ти тримаєш автомат замість пістолета. Але кожен постріл — це звук, і всі вороги в радіусі його чують. Глушник суттєво скорочує цей радіус.

Функції та механіки

📁

level.details — бінарний ридер

Відкриває бінарний файл $game_levels$/level_name/level.details через io.open(path, "rb") і парсить структуру чанків:

Chunk 0 — заголовок сітки: зміщення ox / oz, розмір sx / sz, крок клітинки DETAIL_CELL = 2.0 м.
Chunk 2 — слот-дані: 16 байт на клітинку (f32 Y + два 32-бітних bitmask).

Позиція актора → індекс клітинки: cx = floor(pos.x / 2.0) + ox. Зчитуються два bitmask — кожен біт = один екземпляр трав'яного об'єкта в клітинці. Підраховується popcount (0–64 встановлених бітів).

🌾

Popcount → grass cover

Popcount відрізняє декоративну траву від польової:

pc ≤ 8 — асфальт або декоративна трава на дорозі (pc 4–6) → стелс не активується.
pc 15–25 — реальна польова трава → повне укриття.

Формула покриття: cover = clamp((pc − 8) / 13, 0, 1). Кешується 300 мс щоб не читати файл щокадру.

🌿

r__detail_height — м'який множник

Додатково зчитується r__detail_height з консолі рушія — м'який штраф якщо гравець знизив висоту трави в графіці: hf = clamp(h / 0.7, 0.2, 1.0). Фінальне покриття = cover × hf.

🎯

Хук on_enemy_eval

Підключається до коллбека on_enemy_eval системи Stealth 2.31 і модифікує поле flags.result. Якщо умови стелсу виконані — виявлення скасовується на поточний тік.

🛡

best_enemy() guard

Перед розрахунком перевіряється obj:best_enemy(). Якщо NPC вже має актора як активну ціль — flags.result не скидається. Захищає від помилкового стелсу під час бою.

🔊

Акустичний стелс

Хук на actor_on_weapon_fired. Визначається тип зброї та наявність silencer. Вороги у радіусі виявлення отримують відповідний стан через внутрішню чергу стану NPC.

🧠

Detection Memory

При виявленні зберігається combat_memory[npc_id] = time_global(). На наступних тіках перевіряється дельта з поточним часом. Якщо менше memory_duration — повторна перевірка пропускається.

🌙

Нічний режим

Перевіряється level.get_time_hours(). Якщо час між night_start = 21 і night_end = 6 і увімкнено night_stealth_enabled — застосовується night_factor.

🌧

Погодний множник

Зчитується level.rain_factor(). Якщо значення вище нуля — застосовується rain_bonus. Туман визначається через level.get_fog_density().

📐

Вертикальний кут огляду

Обчислюється вектор між позицією актора і NPC. Якщо ворог вище і вертикальна складова перевищує поріг, а density > sparse_threshold — захист від виявлення зверху не діє.

⚙️

MCM інтеграція

Всі параметри зберігаються через ui_mcm.get(). Значення зчитуються щотіку в on_enemy_eval — зміни набирають чинності без перезапуску гри.

🔗

Залежності

Розширює Stealth 2.31 без заміни його файлів — патчить через RegisterScriptCallback. Потребує MCM для налаштування. Сумісний з будь-якими модами що не замінюють on_enemy_eval.

-- MCM параметри (grass_stealth_mcm.script)
enabled -- bool · вмикає / вимикає мод повністю
stealth_multiplier -- float · множник видимості у траві · за замовч. 0.04
min_grass_height -- float · мін. висота трави для активації · 0.7
sparse_grass_threshold -- float · поріг рідкої трави · 0.55
dense_grass_threshold -- float · поріг густої трави · 0.35
prone_bonus -- float · множник лежачи · 0.5
detection_distance -- float · макс. дистанція дії стелсу · 80 м
memory_duration -- int · час памʼяті виявлення · 15 с
rain_bonus -- float · знижка виявлення при дощі · 0.5
night_stealth_enabled -- bool · нічний режим (21:00–06:00)
night_factor -- float · множник видимості вночі · 0.15

Головне що треба знати

🧎

Тільки в присяді або лежачи

Стелс від трави працює виключно коли ти присів або лежиш. Встав — і ти одразу видимий, навіть якщо стоїш у найгустіших заростях.

⬇️

Ляж — стань майже невидимим

Лежачи ти вдвічі непомітніший ніж просто у присяді. У густій траві лежачи ворог може пройти буквально поруч і не помітити. Завжди лягай якщо є час.

🔦

Ліхтар — це провал

Увімкнений ліхтар миттєво скасовує весь стелс. Ані трава, ані ніч, ані дощ — вже не мають значення. Перед тим як ховатися — завжди вимикай світло.

🌙

Ніч — найкращий час

З 21:00 до 06:00 ворог бачить дуже погано. Навіть на відкритій місцевості без жодної трави — шанс що тебе помітять мінімальний. Плануй найнебезпечніші маршрути на ніч.

🔊

Постріл видає звуком

Зброя в руках нічого не міняє — тебе бачать однаково. Але після пострілу всі вороги в радіусі чують де ти. Глушник у 3–6 разів скорочує цей радіус.

🏔

Ворог зверху бачить краще

Якщо ворог стоїть на пагорбі або даху і дивиться вниз — трава дає значно менший захист. Уникай низин де ворог знаходиться вище тебе.

🌧

Дощ і туман — твоя перевага

У погану погоду вороги реагують пізніше і з меншої відстані. Замість того щоб чекати на ясну погоду — використовуй дощ щоб підійти ближче або перетнути відкриту ділянку.

🏃

Засікли — спочатку відірвись

Якщо ворог вже стріляє в тебе — трава не допоможе. Потрібно спочатку відійти за укриття, перечекати, і тільки після того як він заспокоїться — знову ховатися.

🌿

Не вся трава однакова

Висока і густа трава — надійне укриття. Низька або рідка — майже не допомагає. Якщо трава нижча за коліно або зовсім відсутня — стелс від рослинності не спрацює.

👊

Удар ближнього бою скасовує стелс

Будь-який удар ножем, рукою або прикладом тимчасово вимикає стелс на кілька секунд. Якщо бʼєш — роби це і відразу відходь, не чекай.

🧠

Ворог памʼятає тебе деякий час

Після того як ворог тебе помітив — він памʼятає де ти ще 15 секунд. У цей час повторно сховатися неможливо. Спочатку відійди, потім ховайся.

🎯

Різні вороги — різна пильність

Зомбі і бандити помічають тебе погано. Армія, Борг і Моноліт — максимально уважні. Підходити до армійського блокпоста вдень значно небезпечніше ніж до табору ренегатів.

Як поводитися в грі

Найважливіше правило: стоячи стелс не працює ніколи. Навіть у найгустішій траві, вночі, під дощем — якщо ти на повний зріст, ти видимий.
  • 1 Перед зоною ворогів — одразу сідай або лягай. Не чекай поки тебе помітять. Заходь у зону пригнувшись ще до того як побачиш ворога. Ляж якщо є підозра що хтось дивиться у твій бік.
  • 2 Лягти — найефективніший варіант у стелсі. Так, це повільніше. Але лежачи в густій траві ворог може пройти в двох метрах від тебе і не зупинитися. Вставай і біжи тільки коли ти впевнений що навколо нікого немає.
  • 3 Шукай маршрут через рослинність, обходи відкриті ділянки. На голому полі без трави — лежати безглуздо, стелс не спрацює. Завжди шукай де є рослинність і прокладай маршрут через неї. Відкрите поле перебігай тільки коли інших варіантів немає.
  • 4 Вимкни ліхтар — це перше що треба зробити. Якщо ліхтар увімкнений — весь стелс вимкнений автоматично. Ніколи не заходь у стелс зі світлом. Краще орієнтуватись у темряві повільно, ніж бути видимим з ліхтарем.
  • 5 Постріл — це шум на всю округу. Стріляй усвідомлено. Навіть якщо ворог тебе не бачить — він чує постріл. Штурмова гвинтівка без глушника чутна на 100 метрів, снайпер — на 120. Пістолет без глушника — 60 метрів. Глушник скорочує ці цифри у кілька разів. Якщо не хочеш підіймати тривогу — або стріляй здалеку, або використовуй зброю з глушником.
  • 6 Не бий кулаком або холодною зброєю якщо збираєшся далі ховатись. Удар ближнього бою тимчасово вимикає стелс. Ворог, що стояв поруч, може тебе помітити у ці кілька секунд. Якщо вже б'єш — роби це і одразу відходь, не зупиняйся.
  • 7 Уникай місць де ворог вище тебе. Ворог на пагорбі, даху або підвищенні дивиться вниз під кутом і бачить крізь траву краще. Якщо бачиш що ворог займає позицію вище — шукай густу рослинність або обходь його збоку, а не знизу.
  • 8 Плануй найнебезпечніші переходи на нічний час. Після 21:00 і до 06:00 у тебе величезна перевага — ворог бачить погано навіть на відкритій місцевості. Якщо потрібно перетнути відкрите поле, пройти між ворожими позиціями або підійти до охоронюваного об'єкта — дочекайся ночі.
  • 9 Дощ і туман — не перешкода, а шанс. У поганих погодних умовах ворог реагує пізніше. Замість того щоб чекати на ясну погоду і нервувати — використовуй дощ щоб підійти ближче, перетнути відкриту зону або відійти після бою.
  • 10 Якщо ворог тебе помітив — не намагайся одразу сховатися в траву. Після виявлення ворог памʼятає тебе близько 15 секунд. Він продовжує стріляти і йти туди де тебе бачив. Спочатку відійди за тверде укриття — стіна, камінь, будівля. Перечекай. Тільки після того як він заспокоїться і почне оглядатись — знову лягай у траву.
  • 11 Ворог що активно стріляє в тебе — не «забуде» через траву. Якщо NPC вже веде вогонь по тобі — він ігнорує стелс до кінця бою. Трава не допоможе поки він у активному контакті. Потрібно повністю розірвати контакт — вийти з зони видимості, сховатись за рельєф — і тільки тоді стелс знову запрацює.
  • 12 Знай хто перед тобою — пильність у всіх різна. Зомбі і бандити помітять тебе рідко. Армія, Борг, Моноліт — майже завжди. Якщо йдеш до армійського блокпоста вдень — без ночі або дощу це дуже ризиковано. До табору ренегатів або бандитів — значно простіше. Дивись таблицю нижче.

Наскільки гострий зір у ворогів

Шанс що тебе помітять вдень при ясній погоді. Вночі та в дощ — значно нижче у всіх.

Зомбі 15%
Бандит 25%
Ренегат 25%
Сталкер 30%
Свобода 30%
ЧН 30%
Еколог 30%
ЗСС / GReh 35%
Кілер 35%
ІСГ 35%
Армія 40%
Борг 40%
Моноліт 40%

Мутанти

На мутантів час доби та погода не впливають — вони орієнтуються не тільки зором.

Полтергейст 98%
Контролер 95%
Псисакер 90%
Фрактура 88%
Кровосос 85%
Пси-собака 80%
Химера 80%
Кабан 75%
Бюрер 75%
Карлик 70%
Пес / псевдопес 70%
М'ясник 65%
Тушкан 65%
Снорк 60%
Кіт 60%
Зомбі (моб) 45%

На яку відстань чутно постріл

Всі вороги в цьому радіусі чують постріл і знають звідки він. Глушник суттєво скорочує цю відстань.

Тип зброї Без глушника З глушником
ВСС / ВАЛ / ВСК-94 5 м 5 м
Пістолет 60 м 10 м
Пістолет-кулемет 80 м 15 м
Дробовик 80 м 80 м
Штурмова гвинтівка 100 м 40 м
Снайперська гвинтівка 120 м 30 м

* Дробовик — глушник практично не дає ефекту через конструктивні особливості. ВСС / ВАЛ / ВСК-94 — завжди тихі незалежно від глушника.

About the Mod

With this mod, grass becomes real cover. Crouch or go prone in vegetation — and enemies walk right past you without noticing. Stand up — and all that grass around you stops mattering instantly.

Stealth depends on how tall and dense the grass actually is in the current location. If the grass is low or absent — there's nowhere to hide, the mod won't help. But at night, in rain, or in fog — enemies can barely see you even in open terrain.

Important: what weapon you hold does not make you more visible. Enemies don't spot you more easily because you're carrying a rifle instead of a pistol. But every shot you fire is a sound — and every enemy within range hears exactly where you are. A suppressor significantly cuts that radius.

Functions & Mechanics

📁

level.details — Binary Reader

Opens the binary file $game_levels$/level_name/level.details via io.open(path, "rb") and parses its chunk structure:

Chunk 0 — grid header: offset ox / oz, size sx / sz, cell step DETAIL_CELL = 2.0 m.
Chunk 2 — slot data: 16 bytes per cell (f32 Y + two 32-bit bitmasks).

Actor position → cell index: cx = floor(pos.x / 2.0) + ox. Two bitmasks are read — each bit = one grass detail object instance in that cell. Popcount (0–64 set bits) is calculated.

🌾

Popcount → Grass Cover

Popcount distinguishes decorative grass from real field grass:

pc ≤ 8 — asphalt or road decoration (pc 4–6) → stealth does not activate.
pc 15–25 — real field grass → full cover.

Cover formula: cover = clamp((pc − 8) / 13, 0, 1). Cached for 300 ms to avoid reading the file every frame.

🌿

r__detail_height — Soft Multiplier

Reads r__detail_height from the engine console as a soft penalty when the player has reduced grass height in graphics settings: hf = clamp(h / 0.7, 0.2, 1.0). Final cover = cover × hf.

🎯

on_enemy_eval Hook

Hooks into the on_enemy_eval callback of Stealth 2.31 and modifies flags.result. If stealth conditions are met — detection is cancelled for the current tick.

🛡

best_enemy() Guard

Before each stealth calculation, obj:best_enemy() is checked. If the NPC already has the actor as an active target — flags.result is not cleared. Prevents false stealth during active combat.

🔊

Acoustic Stealth

Hooks actor_on_weapon_fired. Determines weapon type and silencer presence. Enemies within the detection radius receive a hostile state via the NPC internal state queue.

🧠

Detection Memory

On detection, stores combat_memory[npc_id] = time_global(). Subsequent ticks compare the delta against the current time. If below memory_duration — the check is skipped.

🌙

Night Mode

Reads level.get_time_hours(). If the time falls between night_start = 21 and night_end = 6 and night_stealth_enabled is true — night_factor is applied.

🌧

Weather Multiplier

Reads level.rain_factor(). If the value is above zero — rain_bonus is applied. Fog is determined via level.get_fog_density().

📐

Vertical Angle Check

Computes the vector between actor and NPC positions. If the enemy is above and the vertical component exceeds the threshold while density > sparse_threshold — overhead protection is disabled.

⚙️

MCM Integration

All parameters are read via ui_mcm.get() on every tick inside on_enemy_eval. Changes take effect immediately — no game restart required.

🔗

Dependencies

Extends Stealth 2.31 without replacing any of its files — patches via RegisterScriptCallback. Requires MCM for configuration. Compatible with any mod that does not override on_enemy_eval.

-- MCM parameters (grass_stealth_mcm.script)
enabled -- bool · master on/off switch
stealth_multiplier -- float · visibility multiplier in grass · default 0.04
min_grass_height -- float · minimum grass height for activation · 0.7
sparse_grass_threshold -- float · sparse grass threshold · 0.55
dense_grass_threshold -- float · dense grass threshold · 0.35
prone_bonus -- float · prone stealth multiplier · 0.5
detection_distance -- float · max stealth range · 80 m
memory_duration -- int · detection memory duration · 15 s
rain_bonus -- float · detection reduction in rain · 0.5
night_stealth_enabled -- bool · night mode toggle (21:00–06:00)
night_factor -- float · night visibility multiplier · 0.15

What you need to know

🧎

Crouch or Prone Only

Vegetation stealth only works while crouching or lying prone. Stand up — and you're immediately visible, even if you're standing in the thickest overgrowth.

⬇️

Go Prone — Become Invisible

Lying down makes you twice as hard to spot compared to crouching. In dense grass, an enemy can pass within arm's reach and not notice you. Always go prone if you have time.

🔦

Torch = Instant Fail

An active flashlight instantly cancels all stealth. Grass, night, rain — none of it matters anymore. Always turn your light off before going into stealth.

🌙

Night Is Your Best Friend

From 21:00 to 06:00 enemies can barely see. Even in open terrain with no grass at all — the chance of being spotted is minimal. Plan your most dangerous routes after dark.

🔊

Shots Give Away Your Position

Your weapon in hand changes nothing. But after firing, every enemy within range hears exactly where you are. A suppressor cuts that radius by 3–6x.

🏔

Enemies Above See Further

An enemy on a hill, rooftop, or any elevated position looking down has a better angle through the grass. Avoid terrain depressions where enemies are positioned above you.

🌧

Rain and Fog Are Your Allies

In bad weather enemies react slower and at shorter range. Instead of waiting for clear skies — use rain to close distance or cross open ground.

🏃

Spotted? Break Contact First

If an enemy is already shooting at you — grass won't help. You need to disengage behind hard cover first, wait for the enemy to calm down, and only then return to stealth.

🌿

Not All Grass Is Equal

Tall, dense grass is reliable cover. Short or sparse grass barely helps. If the vegetation barely reaches your knees or is absent entirely — vegetation stealth won't activate.

👊

Melee Breaks Stealth

Any melee hit — knife, fist, or butt-stock — temporarily disables stealth for a few seconds. If you strike, do it and move immediately. Don't linger.

🧠

Enemies Remember You

After spotting you, an enemy remembers your position for 15 seconds. You cannot re-enter stealth during that window. Break contact first, then hide again.

🎯

Different Enemies, Different Vigilance

Zombies and bandits rarely notice you. Army, Duty, and Monolith are always alert. Approaching an army checkpoint in daylight is far more dangerous than sneaking past a renegade camp.

How to Play with This Mod

The most important rule: standing up disables stealth completely. Even in the densest grass, at night, in the rain — if you're standing upright, you are visible.
  • 1 Crouch or go prone before you enter enemy territory — not after. Don't wait until you're spotted. Approach any enemy zone already crouching. Drop prone if there's any chance an enemy is looking your way.
  • 2 Prone is your primary movement mode in stealth. Yes, it's slow. But lying in dense grass, an enemy can walk within two meters of you and keep going. Stand up and run only when you're sure the area is clear.
  • 3 Find routes through vegetation — avoid open ground. In a bare field with no grass, lying down is pointless — stealth won't activate. Always look for a path through vegetation. Cross open ground only when there's no other option.
  • 4 Turn your flashlight off — it's the first thing to do. An active light source disables all stealth automatically. Never enter stealth with your light on. Better to move slowly in the dark than to be fully visible with a torch.
  • 5 Every shot is a signal. Shoot with purpose. Even if the enemy can't see you — they hear the shot. An assault rifle without a suppressor is audible at 100 meters. A sniper rifle — 120 meters. A pistol — 60 meters. A suppressor cuts those numbers significantly. If you don't want to trigger an alarm — either shoot from extreme range or use a suppressed weapon.
  • 6 Don't melee if you plan to stay hidden afterwards. A melee hit temporarily disables stealth. Any enemy nearby during those seconds can spot you. If you strike — commit and move away immediately, don't wait.
  • 7 Avoid positions where enemies are above you. An enemy on a hill or rooftop looks down at an angle and sees through grass more clearly. If an enemy holds high ground — go around to the side rather than approaching from below.
  • 8 Plan your most dangerous moves at night. After 21:00 and before 06:00 you have a major advantage — enemies can barely see even in open terrain. Crossing open fields, moving between enemy positions, approaching guarded objectives — save all of this for after dark.
  • 9 Rain and fog are opportunities, not obstacles. In poor weather enemies react slower and at shorter distances. Instead of waiting for clear skies — use the rain to close distance, cross open zones, or disengage after a fight.
  • 10 If spotted — don't immediately dive back into grass. After detection the enemy remembers you for about 15 seconds. They keep shooting and moving toward where they last saw you. First get behind solid cover — a wall, rock, or building. Wait. Only after they calm down and start searching does stealth work again.
  • 11 An enemy actively shooting at you won't be fooled by grass. An NPC in active combat with you ignores stealth for the duration of the fight. Grass won't save you while they're locked on. You need to fully break contact — get out of their line of sight, use terrain — only then does stealth kick back in.
  • 12 Know who you're up against — vigilance varies a lot. Zombies and bandits miss you often. Army, Duty, Monolith — almost never. Going near an army checkpoint in broad daylight without night or rain is very risky. A renegade camp is far more forgiving. See the table below.

How Sharp Are Enemy Eyes

Base detection chance during daytime in clear weather. At night and in rain — much lower for everyone.

Zombie 15%
Bandit 25%
Renegade 25%
Stalker 30%
Freedom 30%
Clear Sky 30%
Ecologist 30%
GREH / ZSS 35%
Killer 35%
ISG 35%
Army 40%
Duty 40%
Monolith 40%

Mutants

Mutants don't rely on sight alone — time of day and weather have no effect on them.

Poltergeist 98%
Controller 95%
Psy-sucker 90%
Fracture 88%
Bloodsucker 85%
Psy-dog 80%
Chimera 80%
Boar 75%
Burer 75%
Karlik 70%
Dog / Pseudodog 70%
Flesh 65%
Tushkano 65%
Snork 60%
Cat 60%
Zombie (mob) 45%

How Far Your Shot Is Heard

Every enemy within this range hears your shot and knows where it came from. A suppressor cuts the distance significantly.

Weapon Type No Suppressor With Suppressor
VSS / VAL / VSK-94 5 m 5 m
Pistol 60 m 10 m
SMG 80 m 15 m
Shotgun 80 m 80 m
Assault Rifle 100 m 40 m
Sniper Rifle 120 m 30 m

* Shotgun — suppressor has virtually no effect due to how the weapon operates. VSS / VAL / VSK-94 — always quiet regardless of suppressor.