Ltx reading through script
From Mod Wiki
Barin (Talk | contribs)
(New page: 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 ...)
Next diff →
Current revision
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.
Contents |
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 [artefacts] af_blood = 0 af_medusa = 0 af_vyvert = 0 af_dummy_pellicle = 0 af_fuzz_kolobok = 0 af_night_star = 0 [cheap_artefacts]:artefacts af_blood = 3 af_medusa = 5 af_vyvert = 12 af_mincer_meat = 6 af_rusty_thorn = 8 [expensive_artefacts]:artefacts af_fuzz_kolobok = 1 af_night_star = 2 af_electra_moonlight = 3 [spawn_vectors] 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 [blowout] 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 end end end
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 end 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 end end return array end -- 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) end end
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)) end for index = 1, #t do if t[index] == nil then return nil end end return {position = vector():set(t[1], t[2], t[3]), level_vertex = t[4], game_vertex = t[5]} end 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)) end 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) end end