Step 1 - Locating our target files:
The 2 main files that will be involved in adding our flags are "globalvariables.uvar.3" and "tabledefine.user.2".
The first file can be found at: \stm\_Authoring\appsystem\globalvariables (we will only edit this file)
The second file can be found at: \stm\_Chainsaw\leveldesign\scenario\scenarioflag (more on this later)
Step 2 - Opening globalvariables.uvar.3 and adding new flags using REasy Editor:
Upon opening the file, you will get this view:

Expand "Embedded_UVARs", then expand UVAR_File[227]

Expand Header. You will see at its bottom "variable Count: 128". This refers to the total number of flags in this group (or UVAR_File).

Right click UVAR_File[227] and click "Add Variables". You will be prompted to choose a prefix. Do not choose it and leave it blank then click ok. You will then be asked to enter the number of variables to add (aka flags). We will choose 100 as a test. Click OK

We have now added 100 new flags. If we check the Header array of UVAR_File[227], we will find that the number of variables increased from 128 to 228.
Now, you can find the new flags (Guids) by expanding "Data". Thankfully, the indexes of our variables don't change and we will find our new variables right after the last old variable (which is Variable[127]). So the first variable we added would be Variable[128].

Now, let's reveal the new flags. Choose any new variable, and expand it. In our case, we will choose the first new variable that we added, which is Variable[128].
Upon expanding it, we can see the GUID 1d53d89c-79e7-4991-b667-cd47930c9885. Right click it and copy it.

Click "Tools" in the menu bar at the top of the REasy Editor app, and open the GUID converter. Now paste the copied GUID in the first field, then click the button on the left (Memory -> Standard)

The result (Standard GUID) is the flag you can now use in the game files. Congratulations.
Don't forget to save your file!
If you're interested in the details of how this exactly works, read the below paragraphs. If not, you can move on from this page.
About my research / Explaining how the background process works:
After a lot of trial and error as well as trying to understand why data in uvar files is structured the way it is, I found out that there are many conditions that need to be met in order for the game to read your flags (and data in general). There are checks in place coded in the game and you need to make sure they pass.
2 of those conditions are (we are talking exclusively about adding writable flags here):
- The flags should not be in a read-only group of flags.
- The flags should follow the naming rules of the group.
What group am I talking about here? Open up tabledefine.user.2 using your favorite editor (for example REasy) and have a look at its structure. You will find a list of named groups (Mercenaries_Enemy, Chapter, AO_InGameShop, etc). as well as a DigitNum field, a DigitIndex field and an array of Blocks.
What is the significance of each of those things?
The group name (Mercenaries_Enemy for example) is the base name or label for a set of flags.
Let's say the DigitNum is 4 and the DigitIndex is 3. The the flags in this group would all have the name Mercenaries_EnemyXXXX_YYY.
4 X's and 3 Y's. X and Y are numbers. Example: Mercenaries_Enemy0406_000.
Now let's understand what the Blocks field means. Upon expanding one of those Blocks, we will find the attributes "Group", "Num", "ReadOnly" and "ResetInNewGame".
"Group" means what XXXX that subgroup (aka Block) would have.
"Num" means how many total variables that subgroup will (ie. how many total flags).
For example, if a block in Mercenaries_Enemy has Group=201 and Num=96, the first variable would be Mercenaries_Enemy0201_000 and the last variable would be Mercenaries_Enemy0201_095.
"ReadOnly" is important. If it's checked, then those flag can't be set. In that case, we should avoid that block and look for another block that doesn't have Read-Only flags, so that we can add new flags to it.
"ResetInNewGame" is pretty obvious.
It turns out that "Num" (how many flags are in that subgroup) is not important and will be ignored by the game as long as it's not 0.
Now that we understood how flags are organized, let's move on to the next conditions.
- Newly added variables need a properly generated nameHash.
check out https://github.com/TrikzMe/RE-Engine-Hash-tool/
I used it to generate the correct hashes.
- HashData field needs to correctly match Guids<->VarIDs as well as nameHashes<->VarIDs

as you can see in that screenshot, we have a list of GUIDs in the Guids array, and a matching between GUIDs-Variable IDs in the GuidMap array. At first glance, it would seem arbitrary and one would wonder why the GUIDs wouldn't be listed according to the order of appearance of their respective variables. However, it turns out the GUIDs, which are memory representation of the actual flags, are hexadecimally sorted this way (in ascending order):
ffaa4928-ee24-0740-be14-2b22b0fe78ba
b5e76629-fe2a-204a-a185-b97d76554d53
4db5982b-8b19-5d42-9080-de4f3c311775
Therefore, the flags in the Guids array need to be listed in that order. And then they can be matched to their proper variable in the GuidMap. Ignore this sorting, and the game will ignore your flags.
Not only that, but the same principle applies to name hashes! You need to have the name hashes sorted in the "nameHashes" array, and then you need to match them in nameHashMap.
Moving on to the next condition:
- Proper offset recalculation
After adding data to our globalvariables file, it should remain coherent and consistent. This is of course taken care of in my REasy Editor. However, it is important that you backup your savedata before messing with the global variables, because any bug in REasy or mistake from your part can corrupt your save files and the game will keep crashing on startup, even if you delete your edited globalvariables file (flags that shouldn't be set would have been set).
Once those 5 conditions are met and your file doesn't contain errors, your flags will be read by the game. I might have forgotten other minor rules I came across during my research (will edit this in that case).
0 comments