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 85MaxDialogInteractDistance which is equal to 130struct.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
SIDvalue. Reference operators work forObjPrototypes.cfgbecause both of its base properties (0 and Player) define values for SID.
CoreVariables.cfgandAIGlobals.cfgare 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 = PlayerObjPrototypes.Player.MinDialogInteractDistance = 85But 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].MinDialogInteractDistanceLets 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 ObjPrototypesMyNewConfig.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$