From b0eec872486f34985fc7fc9d60de131fbbb00928 Mon Sep 17 00:00:00 2001 From: "dami.sirbu" Date: Wed, 27 May 2026 04:21:27 +0300 Subject: [PATCH 1/2] feat(ai): runtime cvars scaling stalker rank-dispersion curve Adds ai_dispersion_novice_k and ai_dispersion_experienced_k as CCC_Float cvars that scale the per-rank weapon-dispersion multiplier on top of vanilla's rank curve. CAI_Stalker::GetWeaponAccuracy keeps the existing base *= m_fRankDisperison line (vanilla rank curve baked at net_Spawn). One new block right after applies the cvar-driven scale factor, interpolated by NPC rank. Defaults g_ai_dispersion_novice_k = 1.0f and g_ai_dispersion_experienced_k = 1.0f produce identity scaling; vanilla behavior is bit-identical without any cvar override. A cvar write from console, user.ltx, MCM, or exec_console_cmd takes effect on every stalker NPC's next shot. Pure addition; no vanilla code is removed or modified. The m_fRankDisperison field, its net_Spawn assignment, and the pSettings->r_float reads of [ranks_properties] dispersion keys are all preserved untouched. DLTX patches to those LTX keys continue to work and compose multiplicatively with cvar overrides. Manifest entry added to gamedata/scripts/lua_help_ex.script console commands block per modded-exes PR standard. --- gamedata/scripts/lua_help_ex.script | 3 +++ src/xrGame/ai/stalker/ai_stalker_fire.cpp | 7 +++++++ src/xrGame/console_commands.cpp | 6 ++++++ 3 files changed, 16 insertions(+) diff --git a/gamedata/scripts/lua_help_ex.script b/gamedata/scripts/lua_help_ex.script index 77e26af8f..88dbbd4df 100644 --- a/gamedata/scripts/lua_help_ex.script +++ b/gamedata/scripts/lua_help_ex.script @@ -65,6 +65,9 @@ g_decouple_horz_recoil // calculate horz recoil independently of vert recoil g_use_non_linear_inertia // enable non linear weapon inertia movement + ai_dispersion_novice_k [0; 10] // Stalker NPC weapon-dispersion scale on top of vanilla rank curve, at rank 0; live per shot. Default 1.0 (identity). + ai_dispersion_experienced_k [0; 10] // Stalker NPC weapon-dispersion scale on top of vanilla rank curve, at rank 100; live per shot. Default 1.0 (identity). + } lua extensions { diff --git a/src/xrGame/ai/stalker/ai_stalker_fire.cpp b/src/xrGame/ai/stalker/ai_stalker_fire.cpp index 6abbd831e..d6c7711c5 100644 --- a/src/xrGame/ai/stalker/ai_stalker_fire.cpp +++ b/src/xrGame/ai/stalker/ai_stalker_fire.cpp @@ -71,11 +71,18 @@ static float const min_throw_distance = 10.f; float g_dispersion_base = 1.0f; float g_dispersion_factor = 1.0f; +float g_ai_dispersion_novice_k = 1.0f; +float g_ai_dispersion_experienced_k = 1.0f; float CAI_Stalker::GetWeaponAccuracy() const { float base = PI / 180.f; base *= m_fRankDisperison; + // cvar-driven rank-curve scale on top of vanilla, identity at defaults (1.0 / 1.0) + CHARACTER_RANK_VALUE rank = Rank(); + clamp(rank, 0, 100); + float rank_k = float(rank) / 100.f; + base *= g_ai_dispersion_experienced_k * rank_k + g_ai_dispersion_novice_k * (1.f - rank_k); CWeapon* W = smart_cast(inventory().ActiveItem()); if (!movement().path_completed()) diff --git a/src/xrGame/console_commands.cpp b/src/xrGame/console_commands.cpp index a90f58d04..03e12fa34 100644 --- a/src/xrGame/console_commands.cpp +++ b/src/xrGame/console_commands.cpp @@ -3025,6 +3025,12 @@ void CCC_RegisterCommands() extern float g_ai_aim_max_angle; CMD4(CCC_Float, "ai_aim_max_angle", &g_ai_aim_max_angle, 0.f, 10.f*PI); + extern float g_ai_dispersion_novice_k; + CMD4(CCC_Float, "ai_dispersion_novice_k", &g_ai_dispersion_novice_k, 0.f, 10.f); + + extern float g_ai_dispersion_experienced_k; + CMD4(CCC_Float, "ai_dispersion_experienced_k", &g_ai_dispersion_experienced_k, 0.f, 10.f); + #ifdef DEBUG extern BOOL g_debug_doors; CMD4(CCC_Integer, "ai_debug_doors", &g_debug_doors, 0, 1); From 47712d0fea759beff5fe1fa4675c718af862c037 Mon Sep 17 00:00:00 2001 From: "dami.sirbu" Date: Wed, 27 May 2026 04:46:19 +0300 Subject: [PATCH 2/2] feat(ui): expose ai_dispersion cvars in Stalkers options menu Wires the two cvars added in the preceding commit (ai_dispersion_novice_k, ai_dispersion_experienced_k) into the Stalkers section of the modded exes options menu introduced by PR #523. Adds track sliders (def 1.0, min 0.0, max 10.0, step 0.1) to options_modded_exes_stalkers.script. Adds English and Russian translation strings to ui_mm_modded_exes.xml in both text/eng and text/rus, following the existing entry pattern. Russian XML round-tripped through iconv (windows-1251 -> UTF-8 -> windows-1251) so the Edit tool could insert UTF-8 Cyrillic strings while preserving the file's declared encoding and tab indentation. Direct xmlstarlet ed reformatted the file whitespace; the iconv path keeps the diff to the four new elements only. Cvar names follow the vanilla LTX naming convention in game_relations.ltx [ranks_properties] (novice_k applies at rank 0, experienced_k applies at rank 100); the description strings correctly identify the actual rank tiers (novice at rank 0, legend at rank 100). --- gamedata/configs/text/eng/ui_mm_modded_exes.xml | 12 ++++++++++++ gamedata/configs/text/rus/ui_mm_modded_exes.xml | 12 ++++++++++++ .../scripts/options_modded_exes_stalkers.script | 17 +++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/gamedata/configs/text/eng/ui_mm_modded_exes.xml b/gamedata/configs/text/eng/ui_mm_modded_exes.xml index a9f36b699..19faf9ce7 100644 --- a/gamedata/configs/text/eng/ui_mm_modded_exes.xml +++ b/gamedata/configs/text/eng/ui_mm_modded_exes.xml @@ -954,6 +954,18 @@ If enabled, NPCs will run instead of walk when taking cover during combat. This makes firefights more dynamic and prevents NPCs from slowly walking while under fire. + + AI Dispersion Scale at Rank 0 (ai_dispersion_novice_k) + + + Multiplier applied on top of the vanilla rank-dispersion curve at rank 0 (novice).\n \nDefault: 1.0 (no change from vanilla).\n \nLower values reduce low-rank NPC dispersion; higher values increase it. Applies on every NPC's next shot. + + + AI Dispersion Scale at Rank 100 (ai_dispersion_experienced_k) + + + Multiplier applied on top of the vanilla rank-dispersion curve at rank 100 (legend tier; cvar name follows the vanilla LTX naming convention).\n \nDefault: 1.0 (no change from vanilla).\n \nLower values reduce high-rank NPC dispersion; higher values increase it. Applies on every NPC's next shot. + diff --git a/gamedata/configs/text/rus/ui_mm_modded_exes.xml b/gamedata/configs/text/rus/ui_mm_modded_exes.xml index 9ea6705f9..3bd8c700c 100644 --- a/gamedata/configs/text/rus/ui_mm_modded_exes.xml +++ b/gamedata/configs/text/rus/ui_mm_modded_exes.xml @@ -953,6 +953,18 @@ Если включено, NPC будут бежать, а не идти шагом при поиске укрытия во время боя. Это делает перестрелки более динамичными и не дает NPC медленно прогуливаться под огнем. + + Множитель разброса ИИ при ранге 0 (ai_dispersion_novice_k) + + + Множитель, применяемый поверх стандартной кривой разброса по рангу при ранге 0 (новичок).\n \nПо умолчанию: 1.0 (без изменений относительно оригинала).\n \nБолее низкие значения уменьшают разброс у NPC низкого ранга, а более высокие увеличивают его. Применяется при следующем выстреле каждого NPC. + + + Множитель разброса ИИ при ранге 100 (ai_dispersion_experienced_k) + + + Множитель, применяемый поверх стандартной кривой разброса по рангу при ранге 100 (легенда; имя cvar соответствует названию переменной в стандартном LTX).\n \nПо умолчанию: 1.0 (без изменений относительно оригинала).\n \nБолее низкие значения уменьшают разброс у NPC высокого ранга, а более высокие увеличивают его. Применяется при следующем выстреле каждого NPC. + diff --git a/gamedata/scripts/options_modded_exes_stalkers.script b/gamedata/scripts/options_modded_exes_stalkers.script index a337620b5..d96e983ee 100644 --- a/gamedata/scripts/options_modded_exes_stalkers.script +++ b/gamedata/scripts/options_modded_exes_stalkers.script @@ -135,4 +135,21 @@ PAGE = page { def = false, cmd = "ai_move_to_cover_run", }, + line {}, + track { + id = "ai_dispersion_novice_k", + def = 1.0, + min = 0.0, + max = 10.0, + step = 0.1, + cmd = "ai_dispersion_novice_k", + }, + track { + id = "ai_dispersion_experienced_k", + def = 1.0, + min = 0.0, + max = 10.0, + step = 0.1, + cmd = "ai_dispersion_experienced_k", + }, } \ No newline at end of file