Ltx reading through script

From Mod Wiki

Jump to: navigation, search

Instead of creating more and more variables in scripts, you can use ltx files to store your variables (actually constants to be exact) and then load them in a convenient way. This article is about creating/editing ltx files and reading its contents via script.


Ltx file structure

Ltx files are actually simple text files with an INI file structure. Each file is divided into sections (unique name), sections contains pairs variables (each variable name inside one section must be unique) and values. To read certain value, you need to know which variable holds it and in which section such a variable is defined. Inheritance between sections is allowed which means you can define one base section and then derive from it. Here is a simple example of ltx file we will use in this article:

; config\my_ltx\spawn_data.ltx
af_blood = 0
af_medusa = 0
af_vyvert = 0
af_dummy_pellicle = 0
af_fuzz_kolobok = 0
af_night_star = 0
af_blood = 3
af_medusa = 5
af_vyvert = 12
af_mincer_meat = 6
af_rusty_thorn = 8
af_fuzz_kolobok = 1
af_night_star = 2
af_electra_moonlight = 3
spawn_vector_1 = 334.4873046875, 15.932071685791, -17.644674301147, 582487, 2
spawn_vector_2 = 287.0705871582, 4.5406813621521, 108.36920166016, 556184, 145
spawn_vector_3 = 241.57223510742, 15.355321884155, 125.87966156006, 525993, 149
spawn_vector_4 = 245.78199768066, 8.2552852630615, 186.07391357422, 528854, 148
spawn_vector_5 = 174.6911315918, 10.57382774353, 155.11390686035, 477423, 150
enabled = true
show_blowout_timer = false
show_blowout_warning = true
spawn_artefacts = true
spawn_mutants = false
radiation_strength = 0.65
blowout_type = outdoor

As you can see our ltx file defines 5 sections, 2 of them inherits from section artefacts (trivial example for the sake of clarity). Also values of variables inside sections are using basic data types: numbers, boolean values, strings, however by default values are treated as string variables.

Reading ltx file from script

To read variables and values from ltx file Stalker provides class (exported to lua) called ini_file. Here are the methods of this class:

class ini_file
   -- constructor
   function ini_file(string)
   -- commonly used methods
   function section_exist(string)
   function line_exist(string, string)
   function line_count(string)
   function r_bool(string, string)
   function r_float(string, string)
   function r_string(string, string)
   function r_line(string, number, string&, string&)
   -- rarely used methods
   function r_clsid(string, string)
   function r_s32(string, string)
   function r_token(string, string, const token_list&)
   function r_vector(string, string)
   function r_u32(string, string)
   function r_string_wq(string, string)

Most of methods has two strings arguments. In that case the first argument is a section name, the second - variable name. Constructor of the ini_file class takes only one argument - path to the ltx file. The main folder where Stalker looks for ltx files is gamedata\config\ as it is defined in fsgame.ltx file (variable $game_config$). To read the ltx file, we need to create an object of ini_file class providing the path to our ltx file:

local path = "my_ltx\\spawn_data.ltx" -- gamedata\config\my_ltx\spawn_data.ltx
local ltx = ini_file(path)

Now we can access our variables using methods from ini_file class:

local ltx = ini_file("my_ltx\\spawn_data.ltx")
if ltx then
   -- read value of variable 'enabled' from section 'blowout'
   local is_blowout_enabled = ltx:r_bool("blowout", "enabled") -- true
   -- section 'blowout', variable 'radiation_strength'
   local rad_strength = ltx:r_float("blowout", "radiation_strength") -- 0.65
   -- section 'blowout', variable 'blowout_type'
   local blow_type = ltx:r_string("blowout", "blowout_type") -- outdoor
   -- number of variables in section 'spawn_vectors'
   local num_lines = ltx:line_count("spawn_vectors") -- 5
   -- read the 5th vector: v.x = 174.6911315918, v.y = 10.57382774353, v.z = 155.11390686035
   local v = ltx:r_vector("spawn_vectors", "spawn_vector_5")
   -- safe reading
   if ltx:section_exist("expensive_artefacts") then
      if ltx:line_exist("expensive_artefacts", "af_electra_moonlight") then
         local moonlights = ltx:r_string("expensive_artefacts", "af_electra_moonlight") .. "x moonlights" -- 3x moonlights

Above examples are useful if you only want to read one or two variables. If you want to read all the variables from certain section, you can use loop, for instance:

-- read the whole section, line by line
-- load variables and values to array
function read_section(ltx_path, section_name)
   local ltx = ini_file(ltx_path)
   local array = {}
   if not ltx then
      return array
   if ltx:section_exist(section_name) then
      local variable, value, lines = "", "", ltx:line_count(section_name)
      for current_line = 0, lines - 1 do
         result, variable, value = ltx:r_line(section_name, current_line, "", "")
         array[variable] = value
   return array
-- function call:
local tbl = read_section("my_ltx\\spawn_data.ltx", "cheap_artefacts")
for artefact_name, quantity in pairs(tbl) do
   for counter = 1, quantity do
      alife():create(artefact_name, vector():set(1, 2, 3), 12345, 67890)

Reading more complex data

read_section() function reads the given section line by line, each line is read as a string value. Our ltx file contains section spawn_vectors. As the name implies, this section holds vectors to spawn objects, for example mutants or npcs. For such objects we need the position to spawn (vector) but also level vertex id and game vertex id. We can read the section using method r_vector, but this function will return only spawn position (vector - first 3 values). However we can read the whole section using function read_section() and then parse the values:

function parse_spawn_data(str)
   local t = {}
   str = string.gsub(str, "(%a)", "")
   for value in string.gfind(str, "([%-?%d+%.%d+]+)[%p%s]?") do
      table.insert(t, tonumber(value))
   for index = 1, #t do
      if t[index] == nil then
         return nil
   return {position = vector():set(t[1], t[2], t[3]), level_vertex = t[4], game_vertex = t[5]}
local string_table = read_section("my_ltx\\spawn_data.ltx", "spawn_vectors")
local parsed_data = {}
for k, v in pairs(string_table) do
   table.insert(parsed_data, parse_spawn_data(v))
local artefacts = read_section("my_ltx\\spawn_data.ltx", "cheap_artefacts")
local temp = nil
for artefact_name, quantity in pairs(artefacts) do
   for counter = 1, quantity do
      temp = parsed_data[math.random(1, #parsed_data)]
      alife():create(artefact_name, temp.position, temp.level_vertex, temp.game_vertex)



Personal tools