Config files are text files that store settings and parameters used by a program. They provide a means for designers to modify default values outside of compiled code.
In S.T.A.L.K.E.R. 2, many such files are present which can be modified to change the default behavior of the game.
The config files for S.T.A.L.K.E.R. 2 use a unique structural syntax but can be described using universal data structure concepts. These files store properties in a nested data structure similar to JSON, XML, YAML in all but syntax.
When describing these concepts in the following section I will be using YAML which is easier to read and understand when it comes to nested data structures.
Lets look at a snippet from a config file for S.T.A.L.K.E.R. 2 and use it to describe some of these concepts:
// Stalker2\Content\GameLite\GameData\ObjPrototypes.cfg
[0] : struct.begin
...
MinDialogInteractDistance = 85
MaxDialogInteractDistance = 130
...
StaminaPerAction : struct.begin
...
Sprint = 0.1
Climb = 0.5
Jump = 20
...
struct.end
...
struct.end
...
[0]
[#]
is shorthand for defining the nth item of a collection which is refered to as an index.MinDialogInteractDistance
which is equal to 85
MaxDialogInteractDistance
which is equal to 130
struct.begin
is used which means all subsequent properties that are defined -- until it's matching struct.end
keyword is encountered -- will be owned by the [0]
property.MinDialogInteractDistance
is a child property of [0]
and will be refered to in game by first referencing all of its parent nodes followed by its name:ObjProperties[0].MinDialogInteractDistance
NAME | Config | YAML |
---|---|---|
DICTIONARY Collection of properties which are assigned a name and a value for each item |
||
LIST Collection of properties which are assigned a sequential numeric index and value for each item |
||
Dictionaries nested in a List | ||
Lists nested in a Dictionary |
Even though there is no available source code for the game methods that interpret these .cgf
files, we can reasonably infer how some of the available operators work.
operator | description | example |
---|---|---|
refurl |
relative reference to another .cfg file |
[0] : {refurl=../file.cfg} |
refkey |
reference to a previously defined property in the same file or the file pointed to by refurl |
propName : struct.begin {refkey=[0]} |
bskipref |
ignore the original definition for this property | propName struct.begin {bskipref} |
Note: Reference Operators only work for properties that define an
SID
value. Reference operators work forObjPrototypes.cfg
because both of its base properties (0 and Player) define values for SID.
CoreVariables.cfg
andAIGlobals.cfg
are two examples where Reference Operators will not work. Any changes to those two files would have to be made as a complete replacement of the entire file.
Previously we looked at the section of the ObjPrototypes.cgf
which defines the property [0]
. If we look further down in the file (around line 597) we will see another property which is called Player
. This property defines a reference to the [0]
property which means that ObjPrototypes.Player
will be an exact copy of ObjPrototypes[0]
initially, and any properties which are defined below will change any existing property values (only in Player
).
To illustrate this concept consider the following sections of the ObjPrototypes.cfg
file:
[0] : struct.begin
...
SID = empty
...
MinDialogInteractDistance = 85
...
struct.end
...
Player : struct.begin {refkey=[0]}
...
SID = Player
...
struct.end
As a result of this structure, we would see the following values for Player
:
ObjPrototypes.Player.SID = Player
ObjPrototypes.Player.MinDialogInteractDistance = 85
But Why?:
empty
but will be updated to Player
on line 11 in the above exampleMinDialogInteractDistance
but since it started with all of the properties from ObjPrototypes[0]
(curtosy of {refkey=[0]}
) it still ends up with a value for that property which it copied from ObjPrototypes[0].MinDialogInteractDistance
Lets assume we want to modify the Stalker2\Content\GameLite\GameData\ObjPrototypes.cfg
file that was referenced previously.
Player : struct.begin {refkey=[0]}
...
SID = Player
...
CanBeKnockedDown = true
...
struct.end
...
If we wanted to make a change to the CanBeKnockedDown
property and set it to false
. If we did so directly in the ObjPrototypes.cfg
file and published that into a mod, it would work.
However, because we made a change to the original file -- which includes the original values for every other property in ObjPrototypes.cfg
-- our mod would overwrite any other mod that also makes changes to the same file if it was loaded prior to our own.
A better pattern would be to create a new config file and change only the property that we are targetting. In this way it will play nice with any other mod that may edit CanBeKnockedDown
or any other property in the base .cfg
file other than CanBeKnockedDown
.
To do this:
ObjPrototypes.cfg
and call this new folder ObjPrototypes
MyNewConfig.cfg
(call it whatever you want) inside of the ObjPrototypes
folder you just createdMyNewConfig.cfg
(or whatever name you choose) to contain the following:NewPlayer : struct.begin {ref=../ObjPrototypes.cfg; refkey=Player}
CanBeKnockedDown = false
struct.end
.cfg
FilesIt is recommended when datamining with a focus on .cfg
files to extract all game .cfg
and .ini
files using FModel, into a local folder. The advantage of doing this is that you will be able to use text-editors (or file explorer) to search for text within the .cfg
files which is not a feature available to FModel.
^((?!(Dialog|SpawnA|Quest|Contex|OnGame)).)*\.cfg$|ini$