Skip to content

Communication Text (Dialogs & Strings)

Myroslava Saveniuk edited this page Sep 24, 2026 · 1 revision

Last verified: 23.09.2026 | Game version: S.T.A.L.K.E.R.: Call of Pripyat (Steam, patch 1.6.02) | OS tested: Debian (Linux)
Status: Active — core workflow verified end-to-end

TL;DR

No visible text lives directly inside dialog/character files — everything is a two-step lookup: id → string_table entry → actual text. To change what a player reads, you usually edit a string_table file. To change dialog structure (branches, conditions, who says what) you edit a separate dialog file. Both are plain XML, in Windows-1251 encoding when they contain Cyrillic.

The three layers

Communication text in CoP is split across three kinds of files that reference each other by id:

character_desc_.xml (who the NPC is, which dialogs they can have)
⭣
dialogs_.xml (dialog structure: phrases, branching, conditions)
⭣
st_dialogs_.xml (the actual text the player reads, in string_table format)

1. Character files — configs/gameplay/character_desc_<location>.xml

Defines each NPC (<specific_character id="...">): name, bio, appearance, inventory, and — importantly — which dialogs they can have:

<specific_character id="zat_a2_stalker_nimble" team_default="1">
    <name>st_zat_a2_stalker_nimble_name</name>
    <bio>Опытный сталкер. Немногословен, добродушен.</bio>
    ...
    <start_dialog>zat_b51_stalker_nimble_start</start_dialog>

    <actor_dialog>zat_b51_stalker_nimble_b52_about_gun_questions</actor_dialog>
    <actor_dialog>zat_b51_stalker_nimble_place_order</actor_dialog>
    <actor_dialog>zat_b51_stalker_nimble_get_order</actor_dialog>
    <actor_dialog>zat_b51_stalker_nimble_about</actor_dialog>
    <actor_dialog>actor_break_dialog</actor_dialog>
</specific_character>
  • <name> and <bio> are ids into a string_table too, not literal text.
  • <start_dialog> — the dialog the NPC opens with automatically when the player talks to them.
  • <actor_dialog> (can repeat) — dialog options available in the conversation menu; the player can pick between these.
  • One file per location (character_desc_zaton.xml, character_desc_jupiter.xml, character_desc_pripyat.xml, character_desc_general.xml for common/shared NPCs).

2. Dialog files — configs/gameplay/dialogs_<location>.xml

Defines the actual branching structure, referenced by the ids from <start_dialog>/<actor_dialog>:

<dialog id="zat_b51_stalker_nimble_get_order">
    <phrase_list>
        <phrase id="0">
            <text>zat_b51_stalker_nimble_get_order_0</text>
            <next>1</next>
            <next>2</next>
        </phrase>
        <phrase id="1111">
            <text>zat_b51_stalker_nimble_get_order_1111</text>
            <precondition>dialogs_zaton.zat_b51_has_item_cost</precondition>
            <action>dialogs_zaton.zat_b51_buy_item</action>
            <disable_info>zat_b51_order_refused</disable_info>
            <give_info>zat_b51_order_in_process</give_info>
            <next>11111</next>
        </phrase>
        ...
    </phrase_list>
</dialog>

Key elements per <phrase>:

Tag Meaning
<text> an id, not literal text — looked up in the matching st_dialogs_*.xml
<next> id of the next phrase(s); multiple <next> = player gets multiple reply options
<precondition> script_file.function_name — a Lua condition; phrase only shows/fires if it returns true
<action> script_file.function_name — Lua code run when this phrase is selected (give item, take money, etc.)
<has_info> / <dont_has_info> phrase only available if a given info_portion is/isn't set
<give_info> / <disable_info> sets/clears an info_portion when this phrase fires
<is_final>1</is_final> ends the dialog after this phrase

Empty <text /> is normal, not a bug. Some phrases exist purely as branching/logic nodes (checking has_info, routing to the next real phrase) with nothing for the player to read. In-game, when an NPC's reply is split across several such nodes, the player sees a "[next…]" option to step through them — that's the empty-text phrases being traversed one by one until a phrase with real text is reached.

Preconditions and actions point to Lua functions in matching .script files (e.g. dialogs_zaton.script), covered in the upcoming Quests page.

3. String tables — configs/text/<lang>/st_dialogs_<location>.xml

The actual player-facing text, keyed by id:

<string id="zat_b51_stalker_nimble_get_order_0">
    <text>I'm here to collect my order.</text>
</string>

This is the only layer you need to touch if you're just rewording existing dialog without changing its structure/logic.

Other st_*.xml files in the same folder cover different content categories, not just dialogs — worth knowing they exist:

File Contains
st_dialogs_<location>.xml, st_dialogs.xml dialog line text, per location + shared
st_dialog_manager.xml generic dialog manager strings
st_characters.xml NPC names/bios not tied to a specific location
st_quests_<location>.xml, st_quests_general.xml quest journal / PDA text
st_items_*.xml item, weapon, outfit, artifact names & descriptions
st_subtitles.xml subtitles for voiced lines/cutscenes
ui_st_*.xml UI text (menus, inventory, PDA, keybinding screen, etc.) — not dialog-related

Locations / file naming

Dialog and string files are split per location, matching the game's zones: zaton, jupiter, pripyat, plus a shared/general set with no location suffix. When looking for a specific NPC's dialog, check the file matching their location first.

Encoding

Same rule as .script/.ltx files (see Environment & Tools): these XML files are windows-1251-encoded when they contain Cyrillic (Russian text, comments, bios). Reading them with plain cat/grep on Linux shows garbled text — use grep -a to force text mode for searching, and open/save with the correct encoding in your editor (VS Code: bottom-right corner → Reopen/Save with Encoding → Cyrillic Windows 1251).

English text itself is plain ASCII and not affected — encoding only matters when the file contains Cyrillic somewhere (bios, Russian string tables, comments).

File priority reminder

Same rule as Environment & Tools: resources/configs.db → xpatch_02.db → gamedata. Check this per file and per language — the patch doesn't necessarily update every file/language. Example found in this project: xpatch_02.db only contains an updated rus string_table for st_dialogs_zaton.xml; the eng version was never touched by the patch, so the base-archive eng file is still the current source — always check both patch/configs/text/<lang>/ and localization/configs/text/<lang>/ for the specific file/language you're editing before assuming which one is authoritative.

Verified example: changing dialog line text

Changed the reply text NPC "Pilot" (zat_b215_stalker_guide) and Nimble (zat_a2_stalker_nimble) use, both found in st_dialogs_zaton.xml.

1. Find which file contains the target string id

grep -rl "<string_id>" ~/stalker_unpacked/localization/configs/text/eng/

Also check whether the patch has a newer version for your language:

grep -rl "<string_id>" ~/stalker_unpacked/patch/configs/text/eng/ 2>/dev/null

2. Copy the whole file into gamedata, preserving the relative path

mkdir -p "/path/to/Stalker Call of Pripyat/gamedata/configs/text/eng"
cp ~/stalker_unpacked/localization/configs/text/eng/st_dialogs_zaton.xml \
   "/path/to/Stalker Call of Pripyat/gamedata/configs/text/eng/"

The whole file is copied — the engine loads files as a unit, not individual lines inside them. Multiple lines in the same file can be edited in one copy.

3. Edit the copy in gamedata (never the unpacked reference copy)

code "/path/to/Stalker Call of Pripyat/gamedata/configs/text/eng/st_dialogs_zaton.xml"
<string id="zat_b215_stalker_guide_start_31">
    <text>Nice to see you, comrade! What can old Pilot do for you?</text>
</string>

4. Verify in-game

cd "/path/to/Stalker Call of Pripyat"
/path/to/xray-16/bin/x86_64/<config>/xr_3da -cop

Talk to the NPC in question — the edited line appears.

Verified: both edited lines (Nimble and Pilot) show correctly in-game.

Pitfalls

  • <text> inside a dialog file is always an id, never literal text — the real text lives in a separate st_dialogs_*.xml.
  • Empty <text /> phrases are normal branching/logic nodes, not missing content — they surface in-game as the "[Далее…]" step-through option.
  • File priority (patch overriding base archives) must be checked per file and per language, not assumed globally — a patch may only touch one language's string table for a given file.
  • Files containing Cyrillic are windows-1251-encoded; use grep -a on Linux to search them as text, and set the correct encoding in your editor before saving.
  • Copy the entire source file into gamedata, not just the line you're changing — the engine overrides whole files, not individual entries within them.
  • Dialog structure (branching, conditions, actions) lives in a different file (dialogs_<location>.xml) than the text (st_dialogs_<location>.xml) — know which one you actually need to touch before starting.

Links