arrow-left

Only this pageAll pages
gitbookPowered by GitBook
triangle-exclamation
Couldn't generate the PDF for 259 pages, generation stopped at 100.
Extend with 50 more pages.
1 of 100

Wiki

Loading...

Loading...

Guides

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Reference

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Isolating a level

How to take a rundown and reduce it to one level

hashtag
Overview

This step isn't necessary (and in some ways it's better not to do this at all), but for learning purposes it's good to understand exactly what we'll be working with.

For this step we're going to trim the main datablocks that we'll be working with (specifically Rundown and LevelLayout) so that they only contain one level.

This also doubles as an exercise in using VS Code.

hashtag
Isolating blocks

hashtag
Setup

To start, we'll grab a copy of the unedited Rundown, LevelLayout and GameSetup datablocks. You can follow along with how to generate them using MTFO from or grab them from the archived versions at . You can also view the final version of our edited datablocks here: . Put these inside a folder in the GameData directory of BepInEx. You'll have something like this:

circle-info

MTFO can load datablocks directly from the GameData folder, but it is better to keep them organized in a separate folder. MTFO also used to support loading datablocks from the plugins folder instead, which is what you'll see in many mods and other guides (and even in other parts of this wiki!). Placing datablocks in the GameData folder is now preferred.

Open your GameData folder with VS Code.

hashtag
Deleting rundown blocks

Open the Rundown datablock and delete the headers.

circle-info

Headers have no impact on modded datablocks, deleting them is optional. They're used only by the devs in their editor tools.

Now we'll delete all but one rundown from the "Blocks" part of the datablock.

First, find the "Tutorial Holder" rundown's block. This contains the game's tutorial, and its presence is hardcoded so we can't delete it.

Go to the start of the block, collapse it, and copy it. (Or, if using VS Code, you can use Control + Shift + [ to collapse the block your cursor is in).

Paste it at the bottom of the blocks.

Find the rundown that contains whichever level you'd like to use as a foundation. In this case, we'll use Rundown 6.

Collapse it, copy it and paste it at the bottom of the blocks.

Delete all the other blocks, aside from our two at the bottom (it's easiest to do this by collapsing them all). Once we're down to just our two blocks you might need to fix some formatting. There should be a comma between our two blocks, but not one at the end.

hashtag
Deleting all but one level from the rundown

We only have one rundown and we want to keep only one level in it. Let's go with B2.

Collapse all the tier blocks.

Delete everything but B tier.

circle-exclamation

Make sure you don't delete the tiers themselves, just leave them empty. Otherwise the rundown will not load correctly.

Confirm that the 2nd object in B tier is B2 "Contaminant" and collapse the tier blocks

Delete all but the 2nd block.

B2 has now become B1 and is the only level in the rundown.

circle-info

At the bottom of the rundown's block there is the "persistentID". When the rundown's ID is not 1, GTFO API ensures all levels are unlocked, so we don't have to take care of that ourselves. If you want to include level progression, you'll have to set the ID to 1 and then use the "Accessibility", "UnlockedByExpedition", and "CustomProgressionLock" fields to control levels being unlocked.

hashtag
Deleting secondary layer

Contaminant is the only level in our rundown, but it still has a secondary layer. Let's thoroughly remove the secondary layer from the Rundown datablock. We'll have to remove quite a few sections, see the image below for what we have to remove. We need to remove the bulkhead information from the main layer, and also a bunch of stuff from the secondary layer. After we're done, the secondary layer should look the same as the third layer.

hashtag
Deleting level layout blocks

Now we have to do the same to the LevelLayout datablock. We'll find the correct level layout ID and delete the rest.

In the picture above from our rundown block, you can see that LevelLayoutData is set to 162. That's our main layer level layout.

Open the LevelLayout datablock and find the block with this ID.

Repeat the same process as for our rundown blocks: collapse it, copy it, collapse all blocks, delete them, paste the copied block, delete the comma.

Remember VS Code has to process over 200k lines here so don't be too harsh if it lags a bit. Deleting at least a part of the blocks does have practical use here as VS Code and its plugins won't take time to load when editing huge files like this one.

There should only be a few thousand lines left in this file.

hashtag
Modifying game setup datablock

Most of the work is now done, and we only have to do a minor tweak to the GameSetup datablock. Open it up and change the "RundownIdsToLoad" to only contain the rundown ID for your rundown. The rundown's ID is the "PersistentID" number at the bottom of the rundown's block.

hashtag
Regarding changing IDs

We talked briefly about changing the ID of our rundown block earlier. While this is not a necessary step anymore thanks to GTFO API, it was originally agreed with devs to change all custom rundowns' ID to 1. If you did do this, you'll obviously have to change the "RundownIdsToLoad" to match.

You're also allowed to change the LevelLayout block IDs. If you do so, then you'll have to change the "LevelLayoutData" from the rundown's block to match.

hashtag
Verifying

Remember to save everything.

Launch the game. You should now see only B1 in the rundown menu.

Drop into the level. You should now have only the one rundown, and the level itself should load just fine. If you have freecam or some other mods, you can use them to check what the level looks like more easily. See if anything has changed.

You should see some marker (all sorts of objects placed in the level, a whole different topic) placement differences, also the lack of the secondary layer.

Oh and we deleted the bulkhead key, controller, and the bulkhead door (which is now just a security door) from the main layer. If you want to restore that, you can do so by restoring these 3 fields from the original datablock we kept as a backup (you did keep some as a backup, right?):

  • ZonesWithBulkheadEntrance - zones in same layer (main) that have bulkhead entrances.

  • BulkheadDoorControllerPlacements - where to place bulkhead door controllers. If a zone with a bulkhead entrance does not have a door controller, the entrance will not require a bulkhead key.

  • BulkheadKeyPlacements - where to place bulkhead keys in the layer.

Make sure you restore the ones under MainLayerData and not secondary. You can also just copy the whole MainLayerData block.

Later sections of the guide will assume you restored these (or didn't delete them to begin with).

If you did actually restore and verify again, the terminal near the bulkhead might be near the zone door in front of the door controller now.

The Rundown, LevelLayout and GameSetup blocks are now cleaned up and we can move onto the 2nd step in the guide.

The Complete Newbie Guide
OriginalDataBlocksarrow-up-right
Final datablocks version page
GameData folder of BepInEx.
The datablocks inside our GameData folder.
Context menu to open the folder directly in VS Code.
Headers selected to delete
R6 block collapsed and selected to copy
Rundown 6.0 block
The Rundown datablock trimmed to just two rundowns.
R6 tier blocks collapsed
R6 with only B tier
B Tier collapsed
B Tier with only B2 left
Contaminant with secondary layer removed. Pay attention to the red triangles next to line numbers.
R6B2 main layer level layout
R6.5 with only B2 Contaminant, now shown as B1.
Bulkhead zone new terminal location

Home

The one stop shop for all content GTFO modding wiki related! Datablock and guides oh my.

This wiki is connected to the .

circle-info

Current Wiki Status: About as good as it'll get

We certainly don't have everything here, but there is plenty of useful information.

GTFO modding discordarrow-up-right

Contributing

So you've learned the dark secrets of GTFO and now want to spread the madness? Well, this is the page for you!

So you want to contribute to our wiki! Great! Let's get that forbidden knowledge on here with this simple N step program.

Step 1: Follow this linkarrow-up-right to join as an editor of the wiki.

Step 2: Sign into GitBook using whatever account you'd like your edits to be credited to

Step 3: Click the big EDIT button in the top right hand corner of your screen.

The edit button. If you can't find it, you're a lost cause

Step 4: Edit the pages to your heart's content (but do split unrelated changes into multiple requests). If you would like to bring your edits to the next level, consider reading up on the markdown arrow-up-rightformat GitBook uses.

Step 5: Submit your changes for review using the button in the lower right corner.

Step 6: Method 1 (preferred): join the modding discord and send a message in the wiki channel about your change request. Questions and suggestions will be discussed there.

Method 2: (if you don't want to join discord) The change request will be reviewed and you may receive comments with questions, suggestions, and discussion. They will have to be resolved before merging.

Step 7: When all discussion is resolved, the change request is merged.

Thanks for helping the community by spreading your knowledge!

An example of what an edit may look like
The button you have to press to submit your changes for review. You can find it, we believe in you!

Editing rundown and level metadata

Changing fields that have no impact on the game

hashtag
Overview

Not all fields have functional use in-game. Some are used just to display something, like level descriptions for example. Now that we have isolated one level in our rundown, let's change some fields to distinguish it from R6B2.

hashtag
Naming the blocks

First let's change the "name" fields of both rundown and level layout. As we know, this is one of the fields shared by all datablocks and must be unique in the file. It is never visible in-game without mods, but having good names helps with readability and lets us describe the block. This is especially relevant here since JSON has no comments (although there are ways).

The exact names are up to you. I can only try to give a few tips, whether to follow them is up to you:

  • Keep a consistent style of naming.

  • Describe what the block is concisely. A longer name is better than a shorter one that has no meaning.

  • Don't use abbreviations you might not remember.

Here are the names I chose.

This is the only field we're changing that's usually invisible to the players.

hashtag
Changing data displayed to the player

Remember a lot of text fields are of the LocalizedText type, these can be both numbers and strings. If you want localization in your custom rundown you can use the LocalizedText type, in this guide we'll only use strings. You can always check the original text you're changing by looking for the ID in TextDataBlock.

Let's mark the fields we'll focus on:

  • In rundown datablock:

    • "Title" - the displayed title of the rundown;

    • "SurfaceDescription" - displayed when clicking the "intel" button (nobody reads this though);

There are more but this is enough for now.

Since this all has no impact on gameplay (except ZoneAliasStart but that has minimal impact), the values are up to you. Here's what I used:

The results:

There are more fields related to visual data in rundown and level layout but with this we have enough to make unique vanilla-style rundown & level information. We can move on to the 3rd step in the guide.

Use practical names; no jokes.
  • You can mark unfinished blocks by adding TODO (and even what exactly is unfinished) in the name if you need to remind yourself.

  • If you're working on a block that has many entries and you're modifying only a few (e.g. archetype), you can think of a prefix to attach to all names so you know which ones you changed.

  • "Prefix" - Mission prefix, in base game always used to specify tier. In old times the devs asked us to distinguish from base game rundowns (e.g. "act-1") but nowadays it doesn't matter;

  • "PublicName" - the name of the mission;

  • "ExpeditionDepth" - Drop cage target depth in expedition details;

  • "ExpeditionDescription" - text displayed under "://Intel_" in expedition details;

  • "RoleplayedWardenIntel" - text displayed under ":://Interrupted_Communications_" in expedition details and when dropping in.

  • In level layout:

    • "ZoneAliasStart" - used to calculate zone alias unless overriden. By default a zone's alias is this number + localindex offset.

  • R6 rundown and level blocks renamed
    Edited Intel screen
    Edited expedition details
    Changed zone aliases
    "Title": "Newbie guide rundown"
    "SurfaceDescription": "<b>This</b> is a rundown.\nDear God...\nThere's more.\nNo!"
    "Prefix": "F"
    "PublicName": "Pollutant"
    "ExpeditionDepth": 527
    "ExpeditionDescription": "This is an example level created for the newbie guide"
    "RoleplayedWardenIntel": ">.. Have we been here before?\r\n<size=20%>Yes</size>\r\n<color=red>>..No, you must be going insane..</color>"
    "ZoneAliasStart": 100

    The Complete Newbie Guide

    Welcome to hell

    hashtag
    Overview

    circle-exclamation

    Be aware that game updates often break datablocks, especially levels and rundowns, to the point where most rundowns get abandoned.

    This page is for people who want to get started with modding GTFO but don't know anything about it. If you're a programmer and you want to write actual mods, check out the introduction to .

    Always remember that the official discord server is not the place to discuss anything modding related. Talk about it in the instead.

    hashtag
    Prerequisites/Recommendations

    Datablocks are all stored in JSON, you need to get familiar with this text format. Basically it's a way to have data as text stored in a way that can be read by both humans and computers. There's an infinite number of guides and ways to learn JSON. One place to start is .

    The text files can be edited even with notepad, but for your sanity I recommend using something more advanced. The most common option here is . It allows you to easily manage entire folders of files at once, provides syntax checking, highlighting, easy searching, replacing, and lots of other good stuff. You can also add some vscode extensions for yourself such as to further make your life easier. Either way you'll be looking at massive amounts of JSON so best be prepared.

    Knowledge of C# or programming in general can definitely help but is not required for modding using datablocks.

    RegEx is very helpful for quickly finding and replacing data.

    hashtag
    Introduction

    Datablocks (also referred to as blocks or db) are GTFO's way of storing various information about the game. While I'm positive they don't directly edit the files ever, them choosing JSON is a convenient way for modders to read and change that information. What is stored in datablocks is completely in devs' control. Sometimes it may seem arbitrary what is stored there and what isn't, so some modders make plugins that allow even more control over the game.

    Some examples of what we can find in datablocks:

    • The stats of weapons, enemies, and players (HP, speed, damage etc);

    • Terminal logs and passwords;

    • Enemy population in levels;

    Everything that is stored in datablocks can be edited. As previously stated, the developers control what is stored in datablocks, making them limited in some aspects. Some things have set rules that you cannot see in datablocks. Some things may be very hard to get to work as expected. Some things cannot be done using only datablocks. Learning to use them can take a lot of effort, and you will have questions, so don't hesitate to ask in the .

    hashtag
    MTFO Installation/Setup

    For a quick, hassle-free setup it's recommended that you use , a mod manager built to work with Thunderstore.

    hashtag
    Installation with R2Modman/Thunderstore mod manager

    1. Install the latest version of the mod manager

    2. Launch the mod manager and select GTFO

    3. Create a new profile and name it

    Best practice is to create one profile per rundown so you can switch between them easily.

    You can find the profile folder by going through the mod manager to Settings -> All -> Browse Profile Folder

    hashtag
    Manual Installation

    1. Download and , then follow their installation instructions (they should just require you to extract the packages in certain folders)

    2. Run the game normally. To play vanilla again, you'd have to manually delete the mods (or remove/rename some specific files)

    hashtag
    Getting the datablocks

    Now that MTFO is ready, there are still a few things left to do to get datablocks

    1. After installing the mods, launch the game once for MTFO config to generate

    2. Move to BepInEx\config and open MTFO.cfg

    3. Set "Dump GameData" to true, save the file

    A few things to note:

    • You can always regenerate the datablocks by just deleting them from gamedata-dump and launching the game again

    • Disabling the dump setting is optional

    • Only keep one folder of datablocks to load, otherwise you have no control over what's loaded

    hashtag
    Get started

    To get some familiarity with editing datablocks, we're going to do 3 things in this section:

    1. Change a weapon's stats;

    2. Enable a weapon from a previous rundown;

    3. Switch the stats of an enemy to those of another.

    You can test either after every step or all at once. A few tips before we get started:

    • can be used to get a lot of information about blocks.

    • LocalizedText is a special type that can both point to a text block and be read as a plain string.

    • All enums can be passed as numbers or strings. I personally recommend using strings since they often give more information than plain numbers, but both work equally fine.

    Remember, after initial generation, all datablocks should be located in GTFO\BepInEx\plugins\GameData_XXXXX\

    circle-info

    When looking for the blocks you see in the guide, you should try to match either name or persistentID. Other fields can point you to the right blocks, but they don't have to be unique. For example, there are several versions of the pistol.

    hashtag
    Changing a weapon's stats

    Let's keep this one simple. We're going to find the pistol's stats and change its damage to 100 and firemode to automatic. Weapon stats are kept in Archetype datablock. There are multiple ways to determine which block belongs to the pistol, but for now let's "assume" that the correct block is the one with the name "GEAR_Pistol_Semi_v2".

    • Note: lines under 3155 and 3184 are collapsed in vscode editor to reduce clutter. You'll see this used a lot.

    Among the fields we can see the ones named "Damage" and "FireMode" (the latter is an enum and will appear as a number if you're not using enums as strings). Change the damage to 100 and firemode to auto. Additionally, let's change the public name to "Balanced pistol" so we can see the custom blocks were loaded without having to drop into a level.

    After saving, you can launch the game and test, or you can test after all the changes.

    hashtag
    Enabling a weapon from a previous rundown

    All datablocks share some fields. One of these fields is called "internalEnabled" and basically determines whether that block exists for the game or not. To enable a previous weapon, the only thing we need to do (assuming the old blocks have not been broken by game updates) is set this field to true in the correct places. For now we are going to enable the combat shotgun. Open PlayerOfflineGear datablock and find the block named "ShotgunAuto". Set "internalEnabled" to true on that block.

    When you save this and launch the game, the combat shotgun should be available under special weapons.

    hashtag
    Switching the stats of an enemy with those of another

    Aside from "internalEnabled" there are 2 other fields that are shared by all blocks. One of them is "name" which you don't see used in-game, but it does help identify the block you're looking at. The last shared field is "persistentID". This is the field used by blocks to reference other blocks. Note that "persistentID" and "name" cannot repeat in the same file.

    Let's change a striker's stats to those of a big striker's using these references. The main block of an enemy is Enemy datablock and the stats we're looking for are stored in EnemyBalancing datablock. The reference field is named "BalancingDataId".

    To change the stats we just need to find the big striker's balancing data, get its persistentID (in this case it's 16), and set it on the striker data.

    And that's it, wave strikers now have the balancing stats of a big striker. If you want, you can also change the balancing data of "Striker_Hibernate" as well for easier testing and more suffering.

    • If you want to undo all your changes, you can delete the edited files and let them regenerate.

    • If you're wondering what fields do what, you can either interpret the name or check out the .

    • Most fields that hold references to other blocks are of the type "uint" aka "UInt32".

    hashtag
    Introduction to errors

    If you edit datablocks enough, you're bound to run into errors, also called exceptions. There's an infinite number of causes so it's impossible to know all of them, but it's important to know where to start looking for information, at the very least so you can pass on more when looking for help. If you do run into something you can't fix yourself, you can ask in the in the modding discord.

    When launching the game with mods enabled, you'll see the BepInEx console as a separate window. This console is useful for many things, but most importantly for users, it shows errors in red text. All logged messages have the type and source as a prefix. E.g. [Error: MTFO] error message shows that there was an error caused by the mod MTFO. Most of the time errors are caused by the game itself, in which case you will see [Error: Unity] as the prefix. In this case I would always recommend to look for the error in the game logs instead of BepInEx logs. These are located in %userprofile%\AppData\LocalLow\10 Chambers Collective\GTFO If you closed the game already, their name will be of the following format: GTFO.[Date].[Time]_[PlayerNick]_[NetworkStatus]. If the game is still open, it'll instead be GTFO.[Date].[Time]_NICKNAME_NETSTATUS. For the most part you will be looking for the most recent file created. While in bepinex console the error message is one line, the game logs provide the stack trace, which is the full source of the error and often provides much more information than just the error message.

    Let's take a look at an example. BepInEx console shows this error message:

    While the game logs show this:

    NullReferenceException is one of the most common errors that says next to nothing about the cause. All we know from BepInEx console is that an error happened. But the game logs show that the source is from melee weapons. Even if this error doesn't give enough information to you, it will allow other people to find the cause if you ask for help.

    Also note that some errors can cause even more errors. When debugging, check the oldest errors first.

    hashtag
    Remarks

    • GameDataBlockBase, trying to save x without being setup error is most likely caused by errors in your JSON. Check your syntax and if you pass incorrect types, such as string instead of int.

    • You can use git to track changes. This allows you to easily see everything you changed at any time, which is useful for many purposes and especially debugging.

    • If something doesn't work correctly, check if your mods are up to date. Rundown updates often break them.

    hashtag
    Recommended content

    Check out the main page for general information about datablocks. Learn to use datablocks reference to get information about specific datablocks.

    Once you have some experience, you can check out the if you're interested in making levels/rundowns.

    The Newbie Level Guide

    This guide should cover level editing enough to get you started making your own levels

    hashtag
    Overview

    triangle-exclamation

    The Rundown currently out is Rundown 8, revision 34800. If you're reading afterwards, you may have to adjust. If we're lucky any future changes to level generation will be backwards compatible.

    Be aware that game updates can break datablocks, and levels/rundowns usually suffer the most from this. Rundown developers often don't even port their rundowns after some updates.

    circle-check

    There's now a page with finished blocks stored and updates noted located .

    If you get stuck or are unsure if some changes were made as updates passed, check it out.

    As you probably already know, levels in GTFO are generated, and their data is stored in datablocks. In terms of difficulty, editing levels is between intermediate and one of the most advanced things in datablocks. This guide is not meant to teach all thing related to level editing, but it will hopefully give you enough to get you going in creating your own levels.

    This goes without saying, but if you're looking to learn, I highly recommend editing and testing the blocks yourself as you read along.

    Throughout the guide, I'll be posting datablocks or parts of them. If you move along, you won't have to copy-paste them, but you can verify they match using for example.

    hashtag
    Prerequisites

    At this point you should be familiar with JSON, datablocks, and the following:

    Recommended:

    • or some other modding toolkit

    hashtag
    Guide content

    The guide is made of 5 parts:

    1. Isolating a level

    2. Editing rundown and level metadata

    3. Adding and editing zones

    The datablocks we work with in this guide:

    • Main:

      1. RundownDataBlock

      2. LevelLayoutDataBlock

    hashtag
    Useful links

    • (OriginalDataBlocks)

    • (but actually just level layout editor)

    VS Code editor (technically not required but guide assumes you use it)
    Editing warden objective
  • Adding a secondary sector

  • WardenObjectiveDataBlock
  • Edited:

    1. ExpeditionBalanceDataBlock

    2. EnemyGroupDataBlock

    3. EnemyPopulationDataBlock

    4. FogSettingsDataBlock

    5. SurvivalWaveSettingsDataBlock

    6. ChainedPuzzleDataBlock

  • Touched:

    1. LightSettingsDataBlock

    2. ConsumableDistributionDataBlock

    3. StaticSpawnDataBlock

    4. BigPickupDistributionDataBlock

    5. ComplexResourceSetDataBlock

    6. ChainedPuzzleTypeDataBlock

  • Diffcheckerarrow-up-right

    here
    Diffcheckerarrow-up-right
    The Complete Newbie Guide
    Datablocks reference
    Enum types
    VS Code tips
    Enable MTFO hot reloading
    CConsolearrow-up-right
    TypeListarrow-up-right
    Datablock Editorarrow-up-right
    Geomorph sheetarrow-up-right
    The objectives of levels;
  • Level layouts themselves;

  • Entire rundowns.

  • Select "Online" and install MTFO
  • Open Settings -> Locations -> Change GTFO directory. Locate and select the install location of GTFO. By default this is C:\Program Files (x86)\Steam\steamapps\common\GTFO

  • Hit the "Play Modded" button

  • Launch and close the game
  • You should now see a folder like BepInEx\GameData-Dump\31829 (version might be changed), this is your datablocks folder

  • Copy the folder to BepInEx\plugins so you'll for example have BepInEx\plugins\31829 (folder name doesn't matter)

  • You can now edit the blocks in plugins and they'll be loaded by MTFO

  • You don't need to keep all datablocks to have them load. In fact, it's recommended to only keep the ones you're going to edit

  • Game logs are useful for more than just finding exceptions, they provide information about what's going on in the game. You can make a desktop shortcut to the logs folder to access them faster.

  • Remember, game updates can break existing datablocks, so be careful when using old blocks as reference (and especially careful when enabling disabled blocks).

  • plugins
    modding discordarrow-up-right
    w3schoolsarrow-up-right
    vscodearrow-up-right
    indent-rainbowarrow-up-right
    datablock development channelarrow-up-right
    R2Modmanarrow-up-right
    Bepinexarrow-up-right
    MTFOarrow-up-right
    Datablock reference
    datablock reference
    tech support channelarrow-up-right
    Datablocks reference
    Newbie Level Guide
    Dump gamedata set to true
    Pistol archetype block
    Edited pistol archetype block
    Balanced pistol in weapon selection
    Combat shotgun block
    Enemy to EnemyBalancing reference
    Edited striker data

    Editing warden objective

    If you're looking for a guide that explains events, you've come to the wrong place

    hashtag
    Overview

    Warden objectives are a core part of any level and they're quite convoluted complex just by themselves, especially with the new event system (that we won't look at). Our level is quite a nightmare by now but we're still not done torturing it for science. It's time to change the warden objective.

    But seeing how in the next part we're adding a secondary sector, here we're going for 3 objectives:

    1. Uplink terminal for main;

    2. Empty (unsolvable) objective for secondary;

    3. Reactor objective for secondary.

    hashtag
    Uplink terminal

    Alright, so, as you might guess, the zone we'll be adding this to is the zone we created, and we're looking for it to land in the 2nd terminal (further down the zone).

    Funny enough we just yeeted an uplink objective with the original level's secondary layer, so let's steal that and also steal the text info from an uplink made before localized text became a thing (because we're not looking to deal with localization right now).

    circle-info

    Remember, using existing blocks is often better than starting from 0, but be careful about which blocks you pick - some might become outdated with game updates. If you can, try to go for the current rundown.

    We'll open up the WardenObjective datablock, and start by copying objective 274 (the original secondary objective) and the Header - GoToWinCondition_ToMainLayer fields from 19 (an uplink objective without localized text). After changing also changing the ID and name we get this:

    chevron-rightOur new warden objective blockhashtag

    Let's go through a bit of analysis before we change it. Know that not all fields are relevant and not all fields behave the same on different objectives.

    • Type is . Here it's 8, terminal uplink.

    • The info fields are straight-forward and can be easily checked in-game. Pay attention to strings in capitals in [] clauses, these are special values that get converted in code.

    • Waves during uplinks are set to settings 44, population 1. Population is standard, settings are set to standard and special only, single wave (10000 points), 5 enemies per group and 8 seconds between groups.

    The terminal picking and exit condition (elevator or exit geo) are set elsewhere, we'll look at that later.

    Pretty much all of these settings are fair enough, we just need to change the uplink count to 1 and increase the exit scan speed.

    Now let's configure the objective in rundown db.

    Only 2 things to change here - the datablock id and the local index, the rest are already correct (make sure you edit the ObjectiveData inside MainLayerData).

    Note that ZonePlacementDatas is a list of lists. If I recall correctly, the outer list is for different uplinks (if we had kept 2 uplinks for example), the inner list is for different locations for the same uplink (rng between runs).

    The only other thing to note is WinCondition. 1 means exit geo. This field only affects info fields to my understanding, and only for the main layer. The actual exit location is always the exit geo if there is one.

    circle-info

    You can have exit geos in layers, but that means you'll always have to do that layer.

    You cannot alternate between several exit geos and/or elevator in the same level.

    A quick test shows that all went according to plan, just one thing was forgotten - a door towards exit was previously locked until the objective was completed. We can copy that for our uplink objective and edit the text or we can disable the lock. I'll go with the latter and set PuzzleType to 0 on zone 9.

    hashtag
    Empty objective

    This is used for times when you don't want to deal with creating an objective but still need one (i.e. while you're still making a level) or when you have other means of completing the objective.

    We're looking to make an objective as simple and universal as possible and in my experience the easiest way is a gather small items objective that spawns no items. The only thing you need to do once you have this block is set the objective ID in rundown db and you're done.

    The block in question:

    We'll try this out once we get to making the secondary sector.

    hashtag
    Reactor

    Reminder that you shouldn't make objectives before you have the level.

    Before we get into any specifics, remember that reactor is an objective heavily relying on waves. If you've read the heat explanation in the mod , you'll know there's a heat bug in base game and reactors will definitely mess with that, so you not only have to build your waves around the bug, it'll also affect the rest of the level and all other attempts until the game is restarted.

    Let's steal R6D1 objective and text info from elsewhere. Reactor blocks are pretty huge thanks to each reactor wave defined separately, and this one also has a bunch of events. We'll have to analyze it in parts. Here's the whole block before editing:

    chevron-rightOur empty warden objectivehashtag

    Reactor objective type is 1; text fields are self-explanatory so we'll skip them.

    Immediately on landing (EventsOnElevatorLand) we have 2 events, the first turns the lights off and the second adds a subobjective. We don't need either so we'll remove those events.

    Then we have EventsOnActivate, I believe run upon completing the scan after inputting the startup command. Weirdly enough only one event seems relevant here - turning the lights on. The others don't seem like they would do anything - the 2nd event is type 0 (none) and the last is type 10 (StopEnemyWaves) but there are no waves to stop as far as I know. Maybe I misremember, or maybe there have been some changes to the level during development and they didn't get cleaned up properly. Either way we need none of these so we'll remove them as well.

    Since we're on events, let's check the last remaining event in this block as well - "Events" under the 4th reactor wave. Usually the zone-unlock events for verification would be here, but R6D1 doesn't do that. Here we have one event - type 5 with trigger 1 - sound on start, with a timed delay. Looks like this is the tank spawn roar. We're removing it.

    One last thing before we look at reactor waves - DoNotSolveObjectiveOnReactorComplete. This is used to make R6D1 seem like it's a terminal command objective when it's actually a reactor. Set this to false so the objective is completed after reactor.

    Alright, reactor waves it is. Here's the first block:

    The first settings are all about time. Time for warmup, wave, and verify phases, as well as for repeat phases marked as "fail".

    VerifyInOtherZone determines if you get the code on HUD or if you have to find it on a terminal. ZoneForVerification is the local index of the zone to place the code in. No placement data here, which means we don't get to choose weights.

    There's 4 waves total here - settings, population, and spawn type are all familiar at this point. The only thing new is "SpawnTimeRel" - when to start spawning the wave. Say, 0.55 would result in 80 * 0.55 = at 44 seconds into the wave. Remember that settings can delay spawn, groups don't all spawn instantly, spawn cap exists etc. so you have to be careful about not overdoing the waves, otherwise people will have to fight through the verify time.

    I won't dive deep into the settings and population. I can guess that they'll mostly be very specific in spawn timing, enemies, and especially population points.

    The other 3 blocks are the exact same thing, just different numbers, so there's no need to analyze them for me. This is all up to level design and balancing, and we don't do that here. I'll delete the 4th wave and leave everything as-is.

    Here's the final block:

    chevron-rightOur secondary's warden objectivehashtag

    Time to finish this.

    Adding a secondary sector

    If we were in R4, this would be a guide on "optional" error alarms

    hashtag
    Overview

    Finally, the last part of the guide. level guide using as many mods as possible when?

    We have already settled on the objective, but we have to make the sector before we apply it. We're not going to generate a third sector because it's the exact same process.

    hashtag
    Setup

    Start with making a new level layout. For a placeholder let's copy the block we have, delete all zones but 0, and clean up all the nightmares we added. Change the alias start to 200, and remember to rename and change ID.

    Here's our placeholder layout:

    chevron-rightOur secondary's placeholder level layouthashtag

    We already have a placeholder objective, so let's move straight to rundown db.

    Enable the secondary layer, set layout, set to build from zone 4 in main layer, set datablock ID to the unsolvable objective.

    If you want to lock it with a bulkhead key, all you have to do is add an entry to main layer bulkhead door controller placements and set it to spawn in the same zone as the bulkhead. Remember to also take care of keys in that case. I'll go with secondary always unlocked.

    Quick test to see if secondary did spawn and it did. Time to generate the proper layout.

    hashtag
    Layout

    Let's keep this small, to reactor basics. The first zone is fine. We're adding a bridge and a reactor geo for a total of 3 zones.

    First thing to do here is find the custom geos. Remember you can only spawn something as custom geo if it is in that complex resource set's custom geos. In rundown db we can see we're using ComplexResourceData 1. Open ComplexResourceSetDataBlock, find ID 1. To make it easier to find what geos we have, I'm going to use breadcrumbs to find the custom geos:

    For the most part we care about the Objective block. I'll copy that to a new file to make search easier.

    I can see reactor gives 3 results and bridge 0, and I'm not sure the 3 reactor results are actual reactors anyway. Time to consult the (although the search in google docs doesn't seem to be the best search ever).

    As suspected, the 3rd result was not an actual reactor geo. I'll take the first reactor (geo_64x64_mining_reactor_open_HA_01) and the classic reactor bridge (geo_64x64_mining_refinery_I_HA_05). I can see that both of these are in complex resource set 1 so I don't have to modify it.

    circle-info

    If you're wondering whether you could spawn geomorphs from other complexes by messing with complex resource set, the answer is no. Only certain geos are loaded based on the level. The only way to mix complexes is to use mods.

    Right, so, copy the first zone 2 more times, fix local indexes, add custom geos, and test.

    Now this took me a few times with LG being finicky, but I got both geos to spawn in the correct directions. If you want to try for yourself with just pointers, check out how the map generates and adjust start positions and coverage. As I understand (I don't), LG will quit trying if it can't generate what it wants, and it can also skip generating the custom geos if it fills up the coverage size too early (normally when custom geo is set, that's the only thing that generates in the zone, but parts of random-generated geos can carry over from previous zones, filling up the size).

    LG is rocket science that deserves its own guide if any poor fool ever bothered to make one, and on top of that it's still changing, so we won't dive too deep into why things happened here.

    Anyway here's the level layout I got:

    chevron-rightOur secondary's final level layouthashtag

    Some results:

    If you have your own working layout, you don't have to copy mine. Note that there are some questionable terminal placements in there.

    hashtag
    Objective

    We've already made the objective, so we just need to apply it in rundown db and test it out. If it works, we don't have to do anything here.

    Future me says it works fine. Excellent. The secondary layer is complete.

    hashtag
    Final test

    With the nightmare fully assembled, it's time for the last test. Go beat the whole level.

    I'd love to insert a full video of me clearing it with Calle QA recording in the background, game muted (except for the combat music mod playing looming dread), cheats enabled, but I'm not gonna do that.

    hashtag
    Afterword

    Finally done, feels like this took forever to write. Hopefully it wasn't so bad to get through as a reader. I hope you learned something, especially something about how to learn from existing examples and debug. Remember, you're not even limited to base game blocks. If you ask nicely, I'm sure most modders will let you use their blocks as examples.

    I also highly recommend checking out the various different mods that expand datablock limitations.

    Now if you'll excuse me, I need to go cast this abomination of a level into oblivion and then turn myself in. Good luck on your future endeavors.

    The Newbie Git Guide

    I just changed something and now the level's not working AND I CAN'T FIX IT FOR 2 HOURS AAAAAHHHHHHHHHHH

    hashtag
    Overview

    circle-info

    This guide only introduces the very fundamentals of Git in a simplified fashion.

    circle-info

    This guide assumes you're using VS Code but Git is fully usable without it.

    Git is a version control system. That basically means you get to see all the changes you (or someone else if you're collaborating) have made to files in a repository. Git is commonly used for storing files online and even publicly for anyone to see, such as on GitHub, but it's fully functional for offline use as well. For now, we're only covering offline use.

    In VS Code, the main view for Git is the source control view, seen at the top left side of the window:

    The changes are shown on the files themselves:

    ...and their contents, marked as red for deletions and green for additions:

    How useful this is depends on how you use it, for example:

    • You can easily return to a version of your content that you know for sure is working.

    • You can undo one little change at a time to see where exactly things went wrong.

    • You can keep it as a form of documentation for the changes made over time or the changes required for certain things to work.

    Using Git is completely optional but (speaking from experience) it can save hours wasted debugging and even dropped/restarted levels (for rundown developers) when no fix for problems is found.

    hashtag
    Installation

    If you haven't installed git yet, the source control view will show something like this:

    Download and launch git installer from there. Most users should use 64-bit standalone installer.

    When going through the installation, most default options should be fine. Just one change you might want to make:

    Either way, for basic git use none of these options should matter much.

    Now that git is installed, reload VS Code and open the folder you want to start working with, such as a fresh MTFO dump (moved to a folder where mod managers won't mess with it), or your own rundown if you have one. The guide will use .

    First step when working with a project offline is to initialize the repository. If you open the source control view now, you should see something like this:

    We're almost ready to start using git, but first there's 2 commands to run. We have to set a user name and email for commits author tracking. For offline repositories this shouldn't matter much and can be changed later, but remember that you can't change author information on existing commits. To run the commands, open a new terminal in VS Code:

    In the terminal, input the commands with your own values:

    git config --global user.name "somename"

    git config --global user.email "somename@gmail.com"

    Now you're ready to start using Git.

    hashtag
    GitLens extension

    VS Code has extensions that bring additional functionality to the editor. GitLens is one such extension for Git:

    It will not be covered here, but if you see some functionality in the guide that you don't see in your own VS Code, it likely comes from this extension.

    hashtag
    Basic Git use in VS Code

    Now that we're ready, let's initialize the repository. Once it's done, the source control view should list all your files as new since we haven't started tracking them yet:

    Let's stage and commit all of them as the initial commit:

    1. Press the + icon to stage all the changes (make sure you press it to the right of the "Changes" text instead of a specific file) - you're selecting the files to include in the commit

    2. Write the commit message - "initial commit"

    3. Press the commit button to finalize the commit.

    Now the source control window should only show the "Publish Branch" button. This is an offline project so we're not going to do that.

    There may have been a lot of unfamiliar terms used just now. The git glossary is (google is also an option), but let's look at some fundamentals:

    • Stage (verb) - to stage a change is to prepare it for a commit, i.e. include in the commit. Git allows you to select just the changes you want instead of everything that's been edited (including selecting only specific parts of files).

    • Commit - a snapshot of the hierarchy and the contents of the files in a Git repository; a single point in the Git history. A commit is like a specific version of your project.

    • Commit message - a description of the changes made in a specific commit.

    hashtag
    Practical use

    So now we kind of know how to work with Git and it does track the changes in our project correctly, but how do we make use of it? For starters, when do we commit? And what commit messages do we use?

    That's completely up to you. If you are developing a rundown on thunderstore, one thunderstore version can be one commit, with commits like "V 1.0.1", "added C1" etc. You can make it more detailed, for example "adjusted ammo balancing for C1", "added shadow baby charger", "added hel hammer launcher". There's probably just 2 things I could mention:

    • Generally, smaller commits are better than large commits - keep them more focused, easier to define and less progress lost when reverting;

    • Make sure your changes work before you commit. A commit with a broken project version is the last thing you want.

    Now let's say that we did indeed break something (but didn't commit) and want to use Git to help fix it. The first straightforward way is to see the specific changes you made and change them back. We don't want to revert the entire commit or entire files, just some one line that's probably broken. We have 2 easy ways to do that.

    For the first, go to source control view and select a file with changes, then find some specific change:

    Click the arrow in the middle to revert the change:

    The change should be reverted, just remember to save the file.

    circle-exclamation

    You can't always easily undo reverted changes.

    For the second method, go directly to the changed file and line. You should see a blue line near line numbers:

    Click it. You should now see the changes inline. At the top right there should be a revert icon:

    Click it to revert the change.

    In 2 other common cases where you want to revert a whole file or all the changes since the last commit, it's easily done through source control view. All you need to do is click the revert icon on a file or next to changes:

    Reverting that specific change would restore the deleted file.

    Now if you break your project and don't remember what was different when it worked, you can simply look and see. Hopefully this prevents some painful debugging for you.

    Git keeps the entire history of the project since the repository was initialized, so you could go back to a version of your project from years back if you wanted to. You can also look into storing a project privately or publicly online as well and even working with other people.

    Final datablocks version

    Shows where you can see the finished datablocks and the changes made since then

    Since R6 is gone now and so are the source blocks, some things have changed and the guide may be hard to follow. You may want to see what blocks were used when originally developing the guide, or perhaps you just want to check/copy a specific block. Either way, the guide blocks are now stored on git:

    You can also check out the commits to see any changes made since initial release. I will also cover some changes here as well.

    hashtag
    R7 update

    Since MTFO now supports loading only specific blocks (also to fix some crap broken by R7 like players' shoes, shooters with pouncer stance and so on), the blocks have been minimized.

    Your First Plugin

    This guide goes over setting up a development environment using Visual Studio and compiling your first plugin

    hashtag
    Preface

    circle-info

    A Plugin is a compiled C# assembly file that is loaded by BepInEx to allow for custom code to be executed, such as patches or custom behaviour

    Adding and editing zones

    Don't be fooled by the fact that this guide is 5 parts, this right here is half of it

    hashtag
    Overview

    This is the meat of the guide. We're going to add a zone, add sleepers, alarms, blood doors, spitters, respawns, resources, a generator puzzle, a pitch black zone, fog.. there's tons of stuff we can do here.

    However, as always, we can't explore everything or we'll be here all week (and this part is already really long). I'll try not to go into too much detail on the meaning of fields this time either, since you can check the relevant blocks' reference to see what all the fields do.

    NullReferenceException: Object reference not set to an instance of an object.
    18:17:44.732 - NullReferenceException: Object reference not set to an instance of an object.
    Gear.MeleeWeaponFirstPerson.UpdateInput () (at <00000000000000000000000000000000>:0)
    Gear.MeleeWeaponFirstPerson.UpdateLocal () (at <00000000000000000000000000000000>:0)
    triangle-exclamation

    This guide assumes you are running windows 10 or 11, own GTFO on steam, and have r2modman installed

    circle-exclamation

    Is this missing something you want help with? Try asking in our Discord server.

    Branch, "master" branch - a "branch" is a line of development. Essentially, it allows you to isolate your changes and commits from others based on people working on them or their purpose. Branching is a more advanced topic that you likely won't run into when working alone. The master branch is the default, the main branch in a project.

    GTFO-APIarrow-up-right
    OriginalDataBlocksarrow-up-right
    herearrow-up-right
    Source Control view icon
    Git changes in VS Code explorer: U (Untracked - new) file and M (Modified) file
    Git changes in VS Code source control view - also showing a D (deleted) file
    Modified line in ArchetypeDataBlock.json, showing "Bullpup" -> "Bullpups" change (opened through source control view)
    Source control view showing git is not installed
    Git install - use VS Code as default editor
    Source control view on a folder without git
    VS Code new terminal button
    git config commands settings name and email
    GitLens extension in VS Code
    Source control view after initializing repository
    Initial commit
    Source control view with no changes
    ArchetypeDataBlock with changes
    Arrow showing revert
    Blue line to the right of line numbers
    Inline change with revert icon
    Discard changes icon in source control view

    WaveOnGotoWinTrigger trigger is 0 (when objective is completed) but WavesOnGotoWin is empty, so there's no extraction alarm.

  • ChainedPuzzleToActive is 10 so a team scan is required before uplink starts.

  • ChainedPuzzleAtExit is 11 (always is) and speed multiplier is 0.2 (at 1.0 speed I believe it takes around 20 seconds to scan).

  • Rounds per uplink is 4 and there's 2 terminals.

  • Wave spawn type is 1 (InSuppliedCourseNodeZone), meaning they'll spawn in uplink zone.

  • {
      "Type": 8,
      "Header": "Terminal Uplink",
      "MainObjective": "Find the <u>Uplink Terminals</u> [ALL_ITEMS] and establish an external uplink from each terminal",
      "WardenObjectiveSpecialUpdateType": 0,
      "GenericItemFromStart": 0,
      "FindLocationInfo": "Gather information about the location of [ALL_ITEMS]",
      "FindLocationInfoHelp": "Access more data in the terminal maintenance system",
      "GoToZone": 0,
      "GoToZoneHelp": 0,
      "InZoneFindItem": 0,
      "InZoneFindItemHelp": 0,
      "SolveItem": "Use [ITEM_SERIAL] to create an uplink to [UPLINK_ADDRESS]",
      "SolveItemHelp": "Use the UPLINK_CONNECT command to establish the connection",
      "GoToWinCondition_Elevator": "Neural Imprinting Protocols retrieved. Return to the point of entrance in [EXTRACTION_ZONE]",
      "GoToWinConditionHelp_Elevator": "Use the navigational beacon and the floor map ([KEY_MAP]) to find the way back",
      "GoToWinCondition_CustomGeo": "Go to the forward exit point in [EXTRACTION_ZONE]",
      "GoToWinConditionHelp_CustomGeo": "Use the navigational beacon and the information in the surroundings to find the exit point",
      "GoToWinCondition_ToMainLayer": "Go back to the main objective and complete the expedition.",
      "GoToWinConditionHelp_ToMainLayer": 0,
      "ShowHelpDelay": 180.0,
      "WavesOnElevatorLand": [],
      "EventsOnElevatorLand": [],
      "WaveOnElevatorWardenIntel": 0,
      "FogTransitionDataOnElevatorLand": 0,
      "FogTransitionDurationOnElevatorLand": 0.0,
      "OnActivateOnSolveItem": false,
      "WavesOnActivate": [
        {
          "WaveSettings": 44,
          "WavePopulation": 1,
          "SpawnDelay": 0.0,
          "TriggerAlarm": true,
          "IntelMessage": 0
        }
      ],
      "EventsOnActivate": [],
      "StopAllWavesBeforeGotoWin": false,
      "WavesOnGotoWin": [],
      "WaveOnGotoWinTrigger": 0,
      "EventsOnGotoWin": [],
      "EventsOnGotoWinTrigger": 0,
      "FogTransitionDataOnGotoWin": 0,
      "FogTransitionDurationOnGotoWin": 0.0,
      "ChainedPuzzleToActive": 10,
      "ChainedPuzzleMidObjective": 0,
      "ChainedPuzzleAtExit": 11,
      "ChainedPuzzleAtExitScanSpeedMultiplier": 0.2,
      "Gather_RequiredCount": -1,
      "Gather_ItemId": 0,
      "Gather_SpawnCount": 0,
      "Gather_MaxPerZone": 0,
      "Retrieve_Items": [],
      "ReactorWaves": [],
      "LightsOnFromBeginning": false,
      "LightsOnDuringIntro": false,
      "LightsOnWhenStartupComplete": false,
      "DoNotSolveObjectiveOnReactorComplete": false,
      "SpecialTerminalCommand": "",
      "SpecialTerminalCommandDesc": "",
      "PostCommandOutput": [],
      "SpecialCommandRule": 0,
      "PowerCellsToDistribute": 0,
      "Uplink_NumberOfVerificationRounds": 4,
      "Uplink_NumberOfTerminals": 2,
      "Uplink_WaveSpawnType": 1,
      "CentralPowerGenClustser_NumberOfGenerators": 0,
      "CentralPowerGenClustser_NumberOfPowerCells": 4,
      "CentralPowerGenClustser_FogDataSteps": [],
      "ActivateHSU_ItemFromStart": 0,
      "ActivateHSU_ItemAfterActivation": 0,
      "ActivateHSU_StopEnemyWavesOnActivation": false,
      "ActivateHSU_ObjectiveCompleteAfterInsertion": false,
      "ActivateHSU_RequireItemAfterActivationInExitScan": false,
      "ActivateHSU_Events": [],
      "Survival_TimeToActivate": 0.0,
      "Survival_TimeToSurvive": 0.0,
      "Survival_TimerTitle": 0,
      "Survival_TimerToActivateTitle": 0,
      "GatherTerminal_SpawnCount": 0,
      "GatherTerminal_RequiredCount": 0,
      "GatherTerminal_Command": "",
      "GatherTerminal_CommandHelp": "",
      "GatherTerminal_DownloadingText": "",
      "GatherTerminal_DownloadCompleteText": "",
      "GatherTerminal_DownloadTime": -1.0,
      "name": "F1 Pollution main - uplink",
      "internalEnabled": true,
      "persistentID": 400
    }
    eWardenObjectiveType
    ConfigurableGlobalWaveSettings
    Warden objective edited
      "ZoneAliasStart": 200,
      "Zones": [
        {
          "LocalIndex": 0,
          "AliasOverride": -1,
          "OverrideAliasPrefix": false,
          "SubSeed": 2,
          "MarkerSubSeed": 0,
          "LightsSubSeed": 0,
          "BulkheadDCScanSeed": 0,
          "SubComplex": 2,
          "CustomGeomorph": "",
          "CoverageMinMax": {
            "x": 40.0,
            "y": 45.0
          },
          "BuildFromLocalIndex": 0,
          "StartPosition": 1,
          "StartPosition_IndexWeight": 0.0,
          "StartExpansion": 1,
          "ZoneExpansion": 3,
          "LightSettings": 56,
          "AltitudeData": {
            "AllowedZoneAltitude": 3,
            "ChanceToChange": 0.5
          },
          "EventsOnEnter": [],
          "EventsOnPortalWarp": [],
          "EventsOnApproachDoor": [],
          "EventsOnUnlockDoor": [],
          "EventsOnOpenDoor": [],
          "EventsOnDoorScanStart": [],
          "EventsOnDoorScanDone": [],
          "ProgressionPuzzleToEnter": {
            "PuzzleType": 0,
            "CustomText": 972,
            "PlacementCount": 1,
            "ZonePlacementData": []
          },
          "ChainedPuzzleToEnter": 0,
          "IsCheckpointDoor": false,
          "PlayScannerVoiceAudio": true,
          "SecurityGateToEnter": 0,
          "UseStaticBioscanPointsInZone": false,
          "TurnOffAlarmOnTerminal": false,
          "TerminalPuzzleZone": {
            "LocalIndex": 0,
            "SeedType": 1,
            "TerminalIndex": 0,
            "StaticSeed": 0
          },
          "EventsOnTerminalDeactivateAlarm": [],
          "ActiveEnemyWave": {
            "HasActiveEnemyWave": false,
            "EnemyGroupInfrontOfDoor": 0,
            "EnemyGroupInArea": 0,
            "EnemyGroupsInArea": 0
          },
          "EnemySpawningInZone": [
          ],
          "EnemyRespawning": false,
          "EnemyRespawnRequireOtherZone": true,
          "EnemyRespawnRoomDistance": 2,
          "EnemyRespawnTimeInterval": 10.0,
          "EnemyRespawnCountMultiplier": 1.0,
          "HSUClustersInZone": 0,
          "CorpseClustersInZone": 0,
          "ResourceContainerClustersInZone": 0,
          "GeneratorClustersInZone": 0,
          "CorpsesInZone": 0,
          "GroundSpawnersInZone": 3,
          "HSUsInZone": 0,
          "DeconUnitsInZone": 0,
          "AllowSmallPickupsAllocation": true,
          "AllowResourceContainerAllocation": true,
          "ForceBigPickupsAllocation": true,
          "ConsumableDistributionInZone": 20,
          "BigPickupDistributionInZone": 0,
          "TerminalPlacements": [
            {
              "PlacementWeights": {
                "Start": 1000.0,
                "Middle": 0.0,
                "End": 0.0
              },
              "AreaSeedOffset": 123,
              "MarkerSeedOffset": 123,
              "LocalLogFiles": [
              ],
              "UniqueCommands": [],
              "StartingStateData": {
                "StartingState": 0,
                "AudioEventEnter": 0,
                "AudioEventExit": 0,
                "PasswordProtected": false,
                "PasswordHintText": "Password Required.",
                "GeneratePassword": false,
                "PasswordPartCount": 1,
                "ShowPasswordLength": true,
                "ShowPasswordPartPositions": false,
                "TerminalZoneSelectionDatas": []
              }
            }
          ],
          "ForbidTerminalsInZone": false,
          "PowerGeneratorPlacements": [],
          "DisinfectionStationPlacements": [],
          "HealthMulti": 0.0,
          "HealthPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "WeaponAmmoMulti": 0.0,
          "WeaponAmmoPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "ToolAmmoMulti": 0.0,
          "ToolAmmoPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "DisinfectionMulti": 0.0,
          "DisinfectionPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "StaticSpawnDataContainers": [
          ]
        }
      ],
      "name": "Newbie guide B1 secondary",
      "internalEnabled": true,
      "persistentID": 163
    }
    Geomorph sheetarrow-up-right
    Bulkhead dc for secondary layer
    Breadcrumbs showing custom geos
    Map with bridge and reactor
    View from bridge zone to initial zone of secondary layer
    {
      "Type": 3,
      "Header": "Don't escape",
      "MainObjective": "Don't escape",
      "WardenObjectiveSpecialUpdateType": 0,
      "GenericItemFromStart": 0,
      "FindLocationInfo": "",
      "FindLocationInfoHelp": "",
      "GoToZone": 0,
      "GoToZoneHelp": 0,
      "InZoneFindItem": 0,
      "InZoneFindItemHelp": 0,
      "SolveItem": 0,
      "SolveItemHelp": 0,
      "GoToWinCondition_Elevator": "",
      "GoToWinConditionHelp_Elevator": 0,
      "GoToWinCondition_CustomGeo": "",
      "GoToWinConditionHelp_CustomGeo": 0,
      "GoToWinCondition_ToMainLayer": "",
      "GoToWinConditionHelp_ToMainLayer": 0,
      "ShowHelpDelay": 180.0,
      "WavesOnElevatorLand": [],
      "EventsOnElevatorLand": [],
      "WaveOnElevatorWardenIntel": 0,
      "FogTransitionDataOnElevatorLand": 0,
      "FogTransitionDurationOnElevatorLand": 0.0,
      "OnActivateOnSolveItem": false,
      "WavesOnActivate": [],
      "EventsOnActivate": [],
      "StopAllWavesBeforeGotoWin": false,
      "WavesOnGotoWin": [
      ],
      "WaveOnGotoWinTrigger": 1,
      "EventsOnGotoWin": [],
      "EventsOnGotoWinTrigger": 0,
      "FogTransitionDataOnGotoWin": 0,
      "FogTransitionDurationOnGotoWin": 0.0,
      "ChainedPuzzleToActive": 0,
      "ChainedPuzzleMidObjective": 0,
      "ChainedPuzzleAtExit": 11,
      "ChainedPuzzleAtExitScanSpeedMultiplier": 0.5,
      "Gather_RequiredCount": 1,
      "Gather_ItemId": 149,
      "Gather_SpawnCount": 0,
      "Gather_MaxPerZone": 1,
      "Retrieve_Items": [],
      "ReactorWaves": [],
      "LightsOnFromBeginning": false,
      "LightsOnDuringIntro": false,
      "LightsOnWhenStartupComplete": false,
      "DoNotSolveObjectiveOnReactorComplete": false,
      "SpecialTerminalCommand": "",
      "SpecialTerminalCommandDesc": "",
      "PostCommandOutput": [],
      "SpecialCommandRule": 0,
      "PowerCellsToDistribute": 0,
      "Uplink_NumberOfVerificationRounds": 0,
      "Uplink_NumberOfTerminals": 1,
      "Uplink_WaveSpawnType": 1,
      "CentralPowerGenClustser_NumberOfGenerators": 0,
      "CentralPowerGenClustser_NumberOfPowerCells": 4,
      "CentralPowerGenClustser_FogDataSteps": [],
      "ActivateHSU_ItemFromStart": 0,
      "ActivateHSU_ItemAfterActivation": 0,
      "ActivateHSU_StopEnemyWavesOnActivation": false,
      "ActivateHSU_ObjectiveCompleteAfterInsertion": false,
      "ActivateHSU_RequireItemAfterActivationInExitScan": false,
      "ActivateHSU_Events": [],
      "Survival_TimeToActivate": 0.0,
      "Survival_TimeToSurvive": 0.0,
      "Survival_TimerTitle": 0,
      "Survival_TimerToActivateTitle": 0,
      "GatherTerminal_SpawnCount": 0,
      "GatherTerminal_RequiredCount": 0,
      "GatherTerminal_Command": "",
      "GatherTerminal_CommandHelp": "",
      "GatherTerminal_DownloadingText": "",
      "GatherTerminal_DownloadCompleteText": "",
      "GatherTerminal_DownloadTime": -1.0,
      "name": "Unsolvable objective",
      "internalEnabled": true,
      "persistentID": 401
    }
    {
      "Type": 1,
      "Header": "Reactor Startup",
      "MainObjective": "Find the main reactor for the floor and make sure it is back online.",
      "WardenObjectiveSpecialUpdateType": 0,
      "GenericItemFromStart": 0,
      "FindLocationInfo": "Gather information about the location of the Reactor",
      "FindLocationInfoHelp": 0,
      "GoToZone": "Navigate to [ITEM_ZONE] and start the Reactor",
      "GoToZoneHelp": 0,
      "InZoneFindItem": "Find the reactor control panel and initiate the startup",
      "InZoneFindItemHelp": 0,
      "SolveItem": "Make sure the Reactor is fully started before leaving",
      "SolveItemHelp": 0,
      "GoToWinCondition_Elevator": "Return to the point of entrance in [EXTRACTION_ZONE]",
      "GoToWinConditionHelp_Elevator": 0,
      "GoToWinCondition_CustomGeo": 0,
      "GoToWinConditionHelp_CustomGeo": 0,
      "GoToWinCondition_ToMainLayer": "Go back to the main objective and complete the expedition.",
      "GoToWinConditionHelp_ToMainLayer": 0,
      "ShowHelpDelay": 180.0,
      "WavesOnElevatorLand": [],
      "EventsOnElevatorLand": [
        {
          "Type": 3,
          "Trigger": 0,
          "ChainPuzzle": 0,
          "UseStaticBioscanPoints": false,
          "Layer": 0,
          "DimensionIndex": 0,
          "LocalIndex": 0,
          "Delay": 0.0,
          "Duration": 0.0,
          "ClearDimension": false,
          "WardenIntel": 0,
          "CustomSubObjectiveHeader": 0,
          "CustomSubObjective": 0,
          "SoundID": 0,
          "DialogueID": 0,
          "FogSetting": 0,
          "FogTransitionDuration": 0.0,
          "EnemyWaveData": {
            "WaveSettings": 0,
            "WavePopulation": 0,
            "SpawnDelay": 0.0,
            "TriggerAlarm": false,
            "IntelMessage": 0
          },
          "Position": {
            "x": 0.0,
            "y": 0.0,
            "z": 0.0,
            "magnitude": 0.0,
            "sqrMagnitude": 0.0
          },
          "Count": 0,
          "Enabled": false
        },
        {
          "Type": 11,
          "Trigger": 0,
          "ChainPuzzle": 0,
          "UseStaticBioscanPoints": false,
          "Layer": 0,
          "DimensionIndex": 0,
          "LocalIndex": 0,
          "Delay": 0.0,
          "Duration": 0.0,
          "ClearDimension": false,
          "WardenIntel": 1450,
          "CustomSubObjectiveHeader": 0,
          "CustomSubObjective": 1542,
          "SoundID": 0,
          "DialogueID": 0,
          "FogSetting": 0,
          "FogTransitionDuration": 0.0,
          "EnemyWaveData": {
            "WaveSettings": 0,
            "WavePopulation": 0,
            "SpawnDelay": 0.0,
            "TriggerAlarm": false,
            "IntelMessage": 0
          },
          "Position": {
            "x": 0.0,
            "y": 0.0,
            "z": 0.0,
            "magnitude": 0.0,
            "sqrMagnitude": 0.0
          },
          "Count": 0,
          "Enabled": false
        }
      ],
      "WaveOnElevatorWardenIntel": 0,
      "FogTransitionDataOnElevatorLand": 0,
      "FogTransitionDurationOnElevatorLand": 0.0,
      "OnActivateOnSolveItem": true,
      "WavesOnActivate": [],
      "EventsOnActivate": [
        {
          "Type": 2,
          "Trigger": 0,
          "ChainPuzzle": 0,
          "UseStaticBioscanPoints": false,
          "Layer": 0,
          "DimensionIndex": 0,
          "LocalIndex": 7,
          "Delay": 0.0,
          "Duration": 0.0,
          "ClearDimension": false,
          "WardenIntel": 1166,
          "CustomSubObjectiveHeader": 0,
          "CustomSubObjective": 0,
          "SoundID": 0,
          "DialogueID": 0,
          "FogSetting": 0,
          "FogTransitionDuration": 0.0,
          "EnemyWaveData": {
            "WaveSettings": 0,
            "WavePopulation": 0,
            "SpawnDelay": 0.0,
            "TriggerAlarm": false,
            "IntelMessage": 0
          },
          "Position": {
            "x": 0.0,
            "y": 0.0,
            "z": 0.0,
            "magnitude": 0.0,
            "sqrMagnitude": 0.0
          },
          "Count": 0,
          "Enabled": false
        },
        {
          "Type": 0,
          "Trigger": 0,
          "ChainPuzzle": 0,
          "UseStaticBioscanPoints": false,
          "Layer": 0,
          "DimensionIndex": 0,
          "LocalIndex": 0,
          "Delay": 0.0,
          "Duration": 0.0,
          "ClearDimension": false,
          "WardenIntel": 0,
          "CustomSubObjectiveHeader": 0,
          "CustomSubObjective": 1444,
          "SoundID": 0,
          "DialogueID": 0,
          "FogSetting": 0,
          "FogTransitionDuration": 0.0,
          "EnemyWaveData": {
            "WaveSettings": 0,
            "WavePopulation": 0,
            "SpawnDelay": 0.0,
            "TriggerAlarm": false,
            "IntelMessage": 0
          },
          "Position": {
            "x": 0.0,
            "y": 0.0,
            "z": 0.0,
            "magnitude": 0.0,
            "sqrMagnitude": 0.0
          },
          "Count": 0,
          "Enabled": false
        },
        {
          "Type": 10,
          "Trigger": 0,
          "ChainPuzzle": 0,
          "UseStaticBioscanPoints": false,
          "Layer": 0,
          "DimensionIndex": 0,
          "LocalIndex": 0,
          "Delay": 0.0,
          "Duration": 0.0,
          "ClearDimension": false,
          "WardenIntel": 0,
          "CustomSubObjectiveHeader": 0,
          "CustomSubObjective": 0,
          "SoundID": 0,
          "DialogueID": 0,
          "FogSetting": 0,
          "FogTransitionDuration": 0.0,
          "EnemyWaveData": {
            "WaveSettings": 0,
            "WavePopulation": 0,
            "SpawnDelay": 0.0,
            "TriggerAlarm": false,
            "IntelMessage": 0
          },
          "Position": {
            "x": 0.0,
            "y": 0.0,
            "z": 0.0,
            "magnitude": 0.0,
            "sqrMagnitude": 0.0
          },
          "Count": 0,
          "Enabled": false
        }
      ],
      "StopAllWavesBeforeGotoWin": false,
      "WavesOnGotoWin": [],
      "WaveOnGotoWinTrigger": 0,
      "EventsOnGotoWin": [],
      "EventsOnGotoWinTrigger": 0,
      "FogTransitionDataOnGotoWin": 0,
      "FogTransitionDurationOnGotoWin": 0.0,
      "ChainedPuzzleToActive": 10,
      "ChainedPuzzleMidObjective": 0,
      "ChainedPuzzleAtExit": 11,
      "ChainedPuzzleAtExitScanSpeedMultiplier": 2.0,
      "Gather_RequiredCount": -1,
      "Gather_ItemId": 0,
      "Gather_SpawnCount": 0,
      "Gather_MaxPerZone": 0,
      "Retrieve_Items": [],
      "ReactorWaves": [
        {
          "Warmup": 40.0,
          "WarmupFail": 20.0,
          "Wave": 80.0,
          "Verify": 60.0,
          "VerifyFail": 60.0,
          "VerifyInOtherZone": false,
          "ZoneForVerification": 0,
          "EnemyWaves": [
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.0,
              "SpawnType": 0
            },
            {
              "WaveSettings": 22,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.25,
              "SpawnType": 0
            },
            {
              "WaveSettings": 7,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.45,
              "SpawnType": 0
            },
            {
              "WaveSettings": 9,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.55,
              "SpawnType": 0
            }
          ],
          "Events": []
        },
        {
          "Warmup": 55.0,
          "WarmupFail": 20.0,
          "Wave": 90.0,
          "Verify": 60.0,
          "VerifyFail": 60.0,
          "VerifyInOtherZone": false,
          "ZoneForVerification": 0,
          "EnemyWaves": [
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.0,
              "SpawnType": 0
            },
            {
              "WaveSettings": 129,
              "WavePopulation": 35,
              "SpawnTimeRel": 0.2,
              "SpawnType": 0
            },
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.35,
              "SpawnType": 0
            },
            {
              "WaveSettings": 9,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.45,
              "SpawnType": 0
            },
            {
              "WaveSettings": 23,
              "WavePopulation": 10,
              "SpawnTimeRel": 0.65,
              "SpawnType": 0
            }
          ],
          "Events": []
        },
        {
          "Warmup": 60.0,
          "WarmupFail": 20.0,
          "Wave": 110.0,
          "Verify": 60.0,
          "VerifyFail": 60.0,
          "VerifyInOtherZone": false,
          "ZoneForVerification": 0,
          "EnemyWaves": [
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.0,
              "SpawnType": 0
            },
            {
              "WaveSettings": 22,
              "WavePopulation": 10,
              "SpawnTimeRel": 0.15,
              "SpawnType": 0
            },
            {
              "WaveSettings": 129,
              "WavePopulation": 35,
              "SpawnTimeRel": 0.25,
              "SpawnType": 0
            },
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.35,
              "SpawnType": 0
            },
            {
              "WaveSettings": 9,
              "WavePopulation": 10,
              "SpawnTimeRel": 0.5,
              "SpawnType": 0
            },
            {
              "WaveSettings": 128,
              "WavePopulation": 35,
              "SpawnTimeRel": 0.7,
              "SpawnType": 0
            }
          ],
          "Events": []
        },
        {
          "Warmup": 60.0,
          "WarmupFail": 20.0,
          "Wave": 120.0,
          "Verify": 60.0,
          "VerifyFail": 60.0,
          "VerifyInOtherZone": false,
          "ZoneForVerification": 0,
          "EnemyWaves": [
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.0,
              "SpawnType": 0
            },
            {
              "WaveSettings": 22,
              "WavePopulation": 10,
              "SpawnTimeRel": 0.1,
              "SpawnType": 0
            },
            {
              "WaveSettings": 129,
              "WavePopulation": 35,
              "SpawnTimeRel": 0.35,
              "SpawnType": 0
            },
            {
              "WaveSettings": 23,
              "WavePopulation": 10,
              "SpawnTimeRel": 0.4,
              "SpawnType": 0
            },
            {
              "WaveSettings": 128,
              "WavePopulation": 35,
              "SpawnTimeRel": 0.75,
              "SpawnType": 0
            },
            {
              "WaveSettings": 30,
              "WavePopulation": 16,
              "SpawnTimeRel": 0.95,
              "SpawnType": 0
            }
          ],
          "Events": [
            {
              "Type": 5,
              "Trigger": 1,
              "ChainPuzzle": 0,
              "UseStaticBioscanPoints": false,
              "Layer": 0,
              "DimensionIndex": 0,
              "LocalIndex": 6,
              "Delay": 171.0,
              "Duration": 0.0,
              "ClearDimension": false,
              "WardenIntel": 0,
              "CustomSubObjectiveHeader": 0,
              "CustomSubObjective": 0,
              "SoundID": 2134610730,
              "DialogueID": 0,
              "FogSetting": 0,
              "FogTransitionDuration": 0.0,
              "EnemyWaveData": {
                "WaveSettings": 0,
                "WavePopulation": 0,
                "SpawnDelay": 0.0,
                "TriggerAlarm": false,
                "IntelMessage": 0
              },
              "Position": {
                "x": 0.0,
                "y": 0.0,
                "z": 0.0,
                "magnitude": 0.0,
                "sqrMagnitude": 0.0
              },
              "Count": 0,
              "Enabled": false
            }
          ]
        }
      ],
      "LightsOnFromBeginning": false,
      "LightsOnDuringIntro": false,
      "LightsOnWhenStartupComplete": true,
      "DoNotSolveObjectiveOnReactorComplete": true,
      "SpecialTerminalCommand": "",
      "SpecialTerminalCommandDesc": "",
      "PostCommandOutput": [],
      "SpecialCommandRule": 0,
      "PowerCellsToDistribute": 0,
      "Uplink_NumberOfVerificationRounds": 0,
      "Uplink_NumberOfTerminals": 1,
      "Uplink_WaveSpawnType": 1,
      "CentralPowerGenClustser_NumberOfGenerators": 0,
      "CentralPowerGenClustser_NumberOfPowerCells": 4,
      "CentralPowerGenClustser_FogDataSteps": [],
      "ActivateHSU_ItemFromStart": 0,
      "ActivateHSU_ItemAfterActivation": 0,
      "ActivateHSU_StopEnemyWavesOnActivation": false,
      "ActivateHSU_ObjectiveCompleteAfterInsertion": false,
      "ActivateHSU_RequireItemAfterActivationInExitScan": false,
      "ActivateHSU_Events": [],
      "Survival_TimeToActivate": 0.0,
      "Survival_TimeToSurvive": 0.0,
      "Survival_TimerTitle": 0,
      "Survival_TimerToActivateTitle": 0,
      "GatherTerminal_SpawnCount": 0,
      "GatherTerminal_RequiredCount": 0,
      "GatherTerminal_Command": "",
      "GatherTerminal_CommandHelp": "",
      "GatherTerminal_DownloadingText": "",
      "GatherTerminal_DownloadCompleteText": "",
      "GatherTerminal_DownloadTime": -1.0,
      "name": "F1 Pollution secondary - reactor",
      "internalEnabled": true,
      "persistentID": 402
    }
        {
          "Warmup": 40.0,
          "WarmupFail": 20.0,
          "Wave": 80.0,
          "Verify": 60.0,
          "VerifyFail": 60.0,
          "VerifyInOtherZone": false,
          "ZoneForVerification": 0,
          "EnemyWaves": [
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.0,
              "SpawnType": 0
            },
            {
              "WaveSettings": 22,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.25,
              "SpawnType": 0
            },
            {
              "WaveSettings": 7,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.45,
              "SpawnType": 0
            },
            {
              "WaveSettings": 9,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.55,
              "SpawnType": 0
            }
          ],
          "Events": []
        },
    {
      "Type": 1,
      "Header": "Reactor Startup",
      "MainObjective": "Find the main reactor for the floor and make sure it is back online.",
      "WardenObjectiveSpecialUpdateType": 0,
      "GenericItemFromStart": 0,
      "FindLocationInfo": "Gather information about the location of the Reactor",
      "FindLocationInfoHelp": 0,
      "GoToZone": "Navigate to [ITEM_ZONE] and start the Reactor",
      "GoToZoneHelp": 0,
      "InZoneFindItem": "Find the reactor control panel and initiate the startup",
      "InZoneFindItemHelp": 0,
      "SolveItem": "Make sure the Reactor is fully started before leaving",
      "SolveItemHelp": 0,
      "GoToWinCondition_Elevator": "Return to the point of entrance in [EXTRACTION_ZONE]",
      "GoToWinConditionHelp_Elevator": 0,
      "GoToWinCondition_CustomGeo": 0,
      "GoToWinConditionHelp_CustomGeo": 0,
      "GoToWinCondition_ToMainLayer": "Go back to the main objective and complete the expedition.",
      "GoToWinConditionHelp_ToMainLayer": 0,
      "ShowHelpDelay": 180.0,
      "WavesOnElevatorLand": [],
      "EventsOnElevatorLand": [
      ],
      "WaveOnElevatorWardenIntel": 0,
      "FogTransitionDataOnElevatorLand": 0,
      "FogTransitionDurationOnElevatorLand": 0.0,
      "OnActivateOnSolveItem": true,
      "WavesOnActivate": [],
      "EventsOnActivate": [
      ],
      "StopAllWavesBeforeGotoWin": false,
      "WavesOnGotoWin": [],
      "WaveOnGotoWinTrigger": 0,
      "EventsOnGotoWin": [],
      "EventsOnGotoWinTrigger": 0,
      "FogTransitionDataOnGotoWin": 0,
      "FogTransitionDurationOnGotoWin": 0.0,
      "ChainedPuzzleToActive": 10,
      "ChainedPuzzleMidObjective": 0,
      "ChainedPuzzleAtExit": 11,
      "ChainedPuzzleAtExitScanSpeedMultiplier": 2.0,
      "Gather_RequiredCount": -1,
      "Gather_ItemId": 0,
      "Gather_SpawnCount": 0,
      "Gather_MaxPerZone": 0,
      "Retrieve_Items": [],
      "ReactorWaves": [
        {
          "Warmup": 40.0,
          "WarmupFail": 20.0,
          "Wave": 80.0,
          "Verify": 60.0,
          "VerifyFail": 60.0,
          "VerifyInOtherZone": false,
          "ZoneForVerification": 0,
          "EnemyWaves": [
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.0,
              "SpawnType": 0
            },
            {
              "WaveSettings": 22,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.25,
              "SpawnType": 0
            },
            {
              "WaveSettings": 7,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.45,
              "SpawnType": 0
            },
            {
              "WaveSettings": 9,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.55,
              "SpawnType": 0
            }
          ],
          "Events": []
        },
        {
          "Warmup": 55.0,
          "WarmupFail": 20.0,
          "Wave": 90.0,
          "Verify": 60.0,
          "VerifyFail": 60.0,
          "VerifyInOtherZone": false,
          "ZoneForVerification": 0,
          "EnemyWaves": [
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.0,
              "SpawnType": 0
            },
            {
              "WaveSettings": 129,
              "WavePopulation": 35,
              "SpawnTimeRel": 0.2,
              "SpawnType": 0
            },
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.35,
              "SpawnType": 0
            },
            {
              "WaveSettings": 9,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.45,
              "SpawnType": 0
            },
            {
              "WaveSettings": 23,
              "WavePopulation": 10,
              "SpawnTimeRel": 0.65,
              "SpawnType": 0
            }
          ],
          "Events": []
        },
        {
          "Warmup": 60.0,
          "WarmupFail": 20.0,
          "Wave": 110.0,
          "Verify": 60.0,
          "VerifyFail": 60.0,
          "VerifyInOtherZone": false,
          "ZoneForVerification": 0,
          "EnemyWaves": [
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.0,
              "SpawnType": 0
            },
            {
              "WaveSettings": 22,
              "WavePopulation": 10,
              "SpawnTimeRel": 0.15,
              "SpawnType": 0
            },
            {
              "WaveSettings": 129,
              "WavePopulation": 35,
              "SpawnTimeRel": 0.25,
              "SpawnType": 0
            },
            {
              "WaveSettings": 23,
              "WavePopulation": 6,
              "SpawnTimeRel": 0.35,
              "SpawnType": 0
            },
            {
              "WaveSettings": 9,
              "WavePopulation": 10,
              "SpawnTimeRel": 0.5,
              "SpawnType": 0
            },
            {
              "WaveSettings": 128,
              "WavePopulation": 35,
              "SpawnTimeRel": 0.7,
              "SpawnType": 0
            }
          ],
          "Events": []
        }
      ],
      "LightsOnFromBeginning": false,
      "LightsOnDuringIntro": false,
      "LightsOnWhenStartupComplete": true,
      "DoNotSolveObjectiveOnReactorComplete": false,
      "SpecialTerminalCommand": "",
      "SpecialTerminalCommandDesc": "",
      "PostCommandOutput": [],
      "SpecialCommandRule": 0,
      "PowerCellsToDistribute": 0,
      "Uplink_NumberOfVerificationRounds": 0,
      "Uplink_NumberOfTerminals": 1,
      "Uplink_WaveSpawnType": 1,
      "CentralPowerGenClustser_NumberOfGenerators": 0,
      "CentralPowerGenClustser_NumberOfPowerCells": 4,
      "CentralPowerGenClustser_FogDataSteps": [],
      "ActivateHSU_ItemFromStart": 0,
      "ActivateHSU_ItemAfterActivation": 0,
      "ActivateHSU_StopEnemyWavesOnActivation": false,
      "ActivateHSU_ObjectiveCompleteAfterInsertion": false,
      "ActivateHSU_RequireItemAfterActivationInExitScan": false,
      "ActivateHSU_Events": [],
      "Survival_TimeToActivate": 0.0,
      "Survival_TimeToSurvive": 0.0,
      "Survival_TimerTitle": 0,
      "Survival_TimerToActivateTitle": 0,
      "GatherTerminal_SpawnCount": 0,
      "GatherTerminal_RequiredCount": 0,
      "GatherTerminal_Command": "",
      "GatherTerminal_CommandHelp": "",
      "GatherTerminal_DownloadingText": "",
      "GatherTerminal_DownloadCompleteText": "",
      "GatherTerminal_DownloadTime": -1.0,
      "name": "F1 Pollution secondary - reactor",
      "internalEnabled": true,
      "persistentID": 402
    }
          "SecondaryLayerEnabled": true,
          "SecondaryLayout": 163,
          "BuildSecondaryFrom": {
            "LayerType": 0,
            "Zone": 4
          },
          "SecondaryLayerData": {
            "ZonesWithBulkheadEntrance": [
            ],
            "BulkheadDoorControllerPlacements": [],
            "BulkheadKeyPlacements": [
            ],
            "ObjectiveData": {
              "DataBlockId": 401,
              "WinCondition": 1,
              "ZonePlacementDatas": [
              ]
            },
            "ArtifactData": {
              "ArtifactAmountMulti": 1.0,
              "ArtifactLayerDistributionDataID": 0,
              "ArtifactZoneDistributions": []
            }
          },
    {
      "ZoneAliasStart": 200,
      "Zones": [
        {
          "LocalIndex": 0,
          "AliasOverride": -1,
          "OverrideAliasPrefix": false,
          "SubSeed": 2,
          "MarkerSubSeed": 0,
          "LightsSubSeed": 0,
          "BulkheadDCScanSeed": 0,
          "SubComplex": 2,
          "CustomGeomorph": "",
          "IgnoreRandomGeomorphRotation": true,
          "CoverageMinMax": {
            "x": 10.0,
            "y": 15.0
          },
          "BuildFromLocalIndex": 0,
          "StartPosition": 1,
          "StartPosition_IndexWeight": 0.0,
          "StartExpansion": 1,
          "ZoneExpansion": 3,
          "LightSettings": 56,
          "AltitudeData": {
            "AllowedZoneAltitude": 3,
            "ChanceToChange": 0.5
          },
          "EventsOnEnter": [],
          "EventsOnPortalWarp": [],
          "EventsOnApproachDoor": [],
          "EventsOnUnlockDoor": [],
          "EventsOnOpenDoor": [],
          "EventsOnDoorScanStart": [],
          "EventsOnDoorScanDone": [],
          "ProgressionPuzzleToEnter": {
            "PuzzleType": 0,
            "CustomText": 972,
            "PlacementCount": 1,
            "ZonePlacementData": []
          },
          "ChainedPuzzleToEnter": 0,
          "IsCheckpointDoor": false,
          "PlayScannerVoiceAudio": false,
          "SecurityGateToEnter": 0,
          "UseStaticBioscanPointsInZone": false,
          "TurnOffAlarmOnTerminal": false,
          "TerminalPuzzleZone": {
            "LocalIndex": 0,
            "SeedType": 1,
            "TerminalIndex": 0,
            "StaticSeed": 0
          },
          "EventsOnTerminalDeactivateAlarm": [],
          "ActiveEnemyWave": {
            "HasActiveEnemyWave": false,
            "EnemyGroupInfrontOfDoor": 0,
            "EnemyGroupInArea": 0,
            "EnemyGroupsInArea": 0
          },
          "EnemySpawningInZone": [
          ],
          "EnemyRespawning": false,
          "EnemyRespawnRequireOtherZone": true,
          "EnemyRespawnRoomDistance": 2,
          "EnemyRespawnTimeInterval": 10.0,
          "EnemyRespawnCountMultiplier": 1.0,
          "HSUClustersInZone": 0,
          "CorpseClustersInZone": 0,
          "ResourceContainerClustersInZone": 0,
          "GeneratorClustersInZone": 0,
          "CorpsesInZone": 0,
          "GroundSpawnersInZone": 3,
          "HSUsInZone": 0,
          "DeconUnitsInZone": 0,
          "AllowSmallPickupsAllocation": true,
          "AllowResourceContainerAllocation": true,
          "ForceBigPickupsAllocation": true,
          "ConsumableDistributionInZone": 20,
          "BigPickupDistributionInZone": 0,
          "TerminalPlacements": [
            {
              "PlacementWeights": {
                "Start": 1000.0,
                "Middle": 0.0,
                "End": 0.0
              },
              "AreaSeedOffset": 123,
              "MarkerSeedOffset": 123,
              "LocalLogFiles": [
              ],
              "UniqueCommands": [],
              "StartingStateData": {
                "StartingState": 0,
                "AudioEventEnter": 0,
                "AudioEventExit": 0,
                "PasswordProtected": false,
                "PasswordHintText": "Password Required.",
                "GeneratePassword": false,
                "PasswordPartCount": 1,
                "ShowPasswordLength": true,
                "ShowPasswordPartPositions": false,
                "TerminalZoneSelectionDatas": []
              }
            }
          ],
          "ForbidTerminalsInZone": false,
          "PowerGeneratorPlacements": [],
          "DisinfectionStationPlacements": [],
          "DumbwaiterPlacements": [],
          "HealthMulti": 0.0,
          "HealthPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "WeaponAmmoMulti": 0.0,
          "WeaponAmmoPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "ToolAmmoMulti": 0.0,
          "ToolAmmoPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "DisinfectionMulti": 0.0,
          "DisinfectionPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "StaticSpawnDataContainers": [
          ]
        },
        {
          "LocalIndex": 1,
          "AliasOverride": -1,
          "OverrideAliasPrefix": false,
          "SubSeed": 2,
          "MarkerSubSeed": 0,
          "LightsSubSeed": 0,
          "BulkheadDCScanSeed": 0,
          "SubComplex": 2,
          "CustomGeomorph": "Assets/AssetPrefabs/Complex/Mining/Geomorphs/Refinery/geo_64x64_mining_refinery_I_HA_05.prefab",
          "IgnoreRandomGeomorphRotation": true,
          "CoverageMinMax": {
            "x": 30.0,
            "y": 30.0
          },
          "BuildFromLocalIndex": 0,
          "StartPosition": 3,
          "StartPosition_IndexWeight": 0.0,
          "StartExpansion": 1,
          "ZoneExpansion": 3,
          "LightSettings": 56,
          "AltitudeData": {
            "AllowedZoneAltitude": 3,
            "ChanceToChange": 0.5
          },
          "EventsOnEnter": [],
          "EventsOnPortalWarp": [],
          "EventsOnApproachDoor": [],
          "EventsOnUnlockDoor": [],
          "EventsOnOpenDoor": [],
          "EventsOnDoorScanStart": [],
          "EventsOnDoorScanDone": [],
          "ProgressionPuzzleToEnter": {
            "PuzzleType": 0,
            "CustomText": 972,
            "PlacementCount": 1,
            "ZonePlacementData": []
          },
          "ChainedPuzzleToEnter": 0,
          "IsCheckpointDoor": false,
          "PlayScannerVoiceAudio": false,
          "SecurityGateToEnter": 0,
          "UseStaticBioscanPointsInZone": false,
          "TurnOffAlarmOnTerminal": false,
          "TerminalPuzzleZone": {
            "LocalIndex": 0,
            "SeedType": 1,
            "TerminalIndex": 0,
            "StaticSeed": 0
          },
          "EventsOnTerminalDeactivateAlarm": [],
          "ActiveEnemyWave": {
            "HasActiveEnemyWave": false,
            "EnemyGroupInfrontOfDoor": 0,
            "EnemyGroupInArea": 0,
            "EnemyGroupsInArea": 0
          },
          "EnemySpawningInZone": [
          ],
          "EnemyRespawning": false,
          "EnemyRespawnRequireOtherZone": true,
          "EnemyRespawnRoomDistance": 2,
          "EnemyRespawnTimeInterval": 10.0,
          "EnemyRespawnCountMultiplier": 1.0,
          "HSUClustersInZone": 0,
          "CorpseClustersInZone": 0,
          "ResourceContainerClustersInZone": 0,
          "GeneratorClustersInZone": 0,
          "CorpsesInZone": 0,
          "GroundSpawnersInZone": 3,
          "HSUsInZone": 0,
          "DeconUnitsInZone": 0,
          "AllowSmallPickupsAllocation": true,
          "AllowResourceContainerAllocation": true,
          "ForceBigPickupsAllocation": true,
          "ConsumableDistributionInZone": 20,
          "BigPickupDistributionInZone": 0,
          "TerminalPlacements": [
            {
              "PlacementWeights": {
                "Start": 1000.0,
                "Middle": 0.0,
                "End": 0.0
              },
              "AreaSeedOffset": 123,
              "MarkerSeedOffset": 123,
              "LocalLogFiles": [
              ],
              "UniqueCommands": [],
              "StartingStateData": {
                "StartingState": 0,
                "AudioEventEnter": 0,
                "AudioEventExit": 0,
                "PasswordProtected": false,
                "PasswordHintText": "Password Required.",
                "GeneratePassword": false,
                "PasswordPartCount": 1,
                "ShowPasswordLength": true,
                "ShowPasswordPartPositions": false,
                "TerminalZoneSelectionDatas": []
              }
            }
          ],
          "ForbidTerminalsInZone": false,
          "PowerGeneratorPlacements": [],
          "DisinfectionStationPlacements": [],
          "DumbwaiterPlacements": [],
          "HealthMulti": 0.0,
          "HealthPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "WeaponAmmoMulti": 0.0,
          "WeaponAmmoPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "ToolAmmoMulti": 0.0,
          "ToolAmmoPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "DisinfectionMulti": 0.0,
          "DisinfectionPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "StaticSpawnDataContainers": [
          ]
        },
        {
          "LocalIndex": 2,
          "AliasOverride": -1,
          "OverrideAliasPrefix": false,
          "SubSeed": 2,
          "MarkerSubSeed": 0,
          "LightsSubSeed": 0,
          "BulkheadDCScanSeed": 0,
          "SubComplex": 2,
          "CustomGeomorph": "Assets/AssetPrefabs/Complex/Mining/Geomorphs/geo_64x64_mining_reactor_open_HA_01.prefab",
          "IgnoreRandomGeomorphRotation": true,
          "CoverageMinMax": {
            "x": 40.0,
            "y": 45.0
          },
          "BuildFromLocalIndex": 1,
          "StartPosition": 1,
          "StartPosition_IndexWeight": 0.0,
          "StartExpansion": 1,
          "ZoneExpansion": 3,
          "LightSettings": 56,
          "AltitudeData": {
            "AllowedZoneAltitude": 3,
            "ChanceToChange": 0.5
          },
          "EventsOnEnter": [],
          "EventsOnPortalWarp": [],
          "EventsOnApproachDoor": [],
          "EventsOnUnlockDoor": [],
          "EventsOnOpenDoor": [],
          "EventsOnDoorScanStart": [],
          "EventsOnDoorScanDone": [],
          "ProgressionPuzzleToEnter": {
            "PuzzleType": 0,
            "CustomText": 972,
            "PlacementCount": 1,
            "ZonePlacementData": []
          },
          "ChainedPuzzleToEnter": 0,
          "IsCheckpointDoor": false,
          "PlayScannerVoiceAudio": false,
          "SecurityGateToEnter": 0,
          "UseStaticBioscanPointsInZone": false,
          "TurnOffAlarmOnTerminal": false,
          "TerminalPuzzleZone": {
            "LocalIndex": 0,
            "SeedType": 1,
            "TerminalIndex": 0,
            "StaticSeed": 0
          },
          "EventsOnTerminalDeactivateAlarm": [],
          "ActiveEnemyWave": {
            "HasActiveEnemyWave": false,
            "EnemyGroupInfrontOfDoor": 0,
            "EnemyGroupInArea": 0,
            "EnemyGroupsInArea": 0
          },
          "EnemySpawningInZone": [
          ],
          "EnemyRespawning": false,
          "EnemyRespawnRequireOtherZone": true,
          "EnemyRespawnRoomDistance": 2,
          "EnemyRespawnTimeInterval": 10.0,
          "EnemyRespawnCountMultiplier": 1.0,
          "HSUClustersInZone": 0,
          "CorpseClustersInZone": 0,
          "ResourceContainerClustersInZone": 0,
          "GeneratorClustersInZone": 0,
          "CorpsesInZone": 0,
          "GroundSpawnersInZone": 3,
          "HSUsInZone": 0,
          "DeconUnitsInZone": 0,
          "AllowSmallPickupsAllocation": true,
          "AllowResourceContainerAllocation": true,
          "ForceBigPickupsAllocation": true,
          "ConsumableDistributionInZone": 20,
          "BigPickupDistributionInZone": 0,
          "TerminalPlacements": [
            {
              "PlacementWeights": {
                "Start": 1000.0,
                "Middle": 0.0,
                "End": 0.0
              },
              "AreaSeedOffset": 123,
              "MarkerSeedOffset": 123,
              "LocalLogFiles": [
              ],
              "UniqueCommands": [],
              "StartingStateData": {
                "StartingState": 0,
                "AudioEventEnter": 0,
                "AudioEventExit": 0,
                "PasswordProtected": false,
                "PasswordHintText": "Password Required.",
                "GeneratePassword": false,
                "PasswordPartCount": 1,
                "ShowPasswordLength": true,
                "ShowPasswordPartPositions": false,
                "TerminalZoneSelectionDatas": []
              }
            }
          ],
          "ForbidTerminalsInZone": false,
          "PowerGeneratorPlacements": [],
          "DisinfectionStationPlacements": [],
          "DumbwaiterPlacements": [],
          "HealthMulti": 0.0,
          "HealthPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "WeaponAmmoMulti": 0.0,
          "WeaponAmmoPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "ToolAmmoMulti": 0.0,
          "ToolAmmoPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "DisinfectionMulti": 0.0,
          "DisinfectionPlacement": {
            "Start": 0.0,
            "Middle": 0.0,
            "End": 0.0
          },
          "StaticSpawnDataContainers": [
          ]
        }
      ],
      "name": "Newbie guide B1 secondary",
      "internalEnabled": true,
      "persistentID": 163
    }

    Additionally, the exit zone size has been changed so the max size isn't reached before exit geomorph is generated.

    Here's the new map:

    Updated map in R7

    hashtag
    R1 ALT update

    Now that devs have confirmed they're officially killing the game (and keeping old rundowns), code-wise it shouldn't change much, which means less maintenance work for rundown developers.

    With this update, there's only 2 things to do to get old levels to work:

    1. Change GameSetup rundown ids to load into a list

    2. Add the tutorial rundown (its reference is hardcoded so we can't get rid of it)

    That's it. The layout doesn't even reroll. Unless you were using some mods that are now broken (this guide only uses MTFO), the level should be fully functional.

    hashtag
    R2 ALT update

    It seems no changes are required.

    Since this is likely to continue, the notes will only be updated if there are relevant changes.

    hashtag
    R8 update

    The start of the guide has been reworked to include the R1 ALT update required changes. Additionally some ID numbers have been changed to avoid collisions.

    In practice I would just use the more readable blocks from the typelistarrow-up-right (or some people opt to make levels using the datablockeditorarrow-up-right), but we started with MTFO generated blocks so let's continue with them.

    hashtag
    Before we start

    There's a block we can change once for the whole rundown to make level editing life a bit easier in the long run.

    The datablock in question is ExpeditionBalance. We won't cover all of it, only the relevant parts.

    circle-info

    In the Rundown datablock, ExpeditionBalance is always usually set to 1. If you want to make changes specific to levels, you can make a new expedition balance block and set the ID just for the level.

    Yes, we're about to screw up the balance of the current level, but when making your own levels you shouldn't start with preset resources and sleeper spawns.

    hashtag
    Resources

    The fields in question:

    These are the base multipliers for resources. Say, with Health being 1.0, setting "HealthMulti" in a zone to 0.8 will result in 4 uses of health, or 80% health for a player. This basically requires no calculation.

    The values we don't like - the ones that complicate the math - are weapon and tool ammo.

    Set both of those fields to 1 so you don't have to think about how many uses of ammo/tool you'll spawn.

    hashtag
    Artifacts

    Artifact progress is not saved when using mods, so unless you have special mods that make use of it, it's just an annoyance. What's more, they can even cause your layout to reroll if there's not enough space to place all of them, affecting not only one zone, but the rest of the layout generated afterwards.

    Set these 2 fields to 0 to avoid artifact spawns:

    hashtag
    Sleeper spawns

    Sleeper spawning system is convoluted, you can read about it here. The relevant part here is that when we're going with relative value, the points assigned are calculated like this: EnemyPopulationPerZone * DistributionValue (from expedition balance and level layout).

    So with a distribution value of 1, we'll have 25 points. But if we want to have exactly 12 points for example, we have to do some math.

    Since we don't like math, let's set EnemyPopulationPerZone to 10. Now all we have to do to get 12 points is assign 1.2 in DistributionValue. Why not just go with 1? Because devs decided to automatically fail if it's set to less than 5 regardless of DistributionValue.

    Reminder that we have just screwed up the resources and especially sleepers in our level, but in reality we wouldn't start with resources and sleepers already set anyway.

    hashtag
    Adding a new zone

    Now that that's taken care of, we can start messing with the level layout itself.

    Let's add a new zone to the existing level. We're going to do this in the following order:

    1. Copy the first zone and paste it at the end;

    2. Change the local index;

    3. Setup build parameters - where it's built from, the direction, size, altitude, subcomplex;

    4. Adjust terminals;

    5. Adjust lighting;

    6. Set sleepers;

    7. Set resources and consumables.

    There's more we can do, but these 7 are plenty to get a full zone. And this is already too much to do at once without testing.

    hashtag
    Steps 1 and 2

    Go to level layout, copy the first zone, and paste it after the last zone. If you collapse all the zones now, you should see 12 in total:

    11 zones collapsed + the pasted one in the end

    An easier way to see is by using Breadcrumbsarrow-up-right:

    Zones list with 12 elements in Breadcrumbs

    Anyway, the last zone had localindex 10, so this one should have 11. You can verify by searching for localIndex 11:

    Search for localindex 11 shows no results
    circle-info

    Remember, if you don't know what a field does, check the datablocks reference to see if it's documented.

    hashtag
    Step 3

    SubComplex is 2, so this would be a Storage zone. Let's change it to DigSite (0) instead.

    BuildFromLocalIndex is 0, so the source zone here will be the elevator zone. This is fine.

    StartPosition is 1 (From_Start). The elevator zone is pretty small so this might not have impact, but let's change it to 2 (From_AverageCenter).

    StartExpansion is 1. Let's change it to 3, hoping it will generate a security door to the right.

    ZoneExpansion is 3. Let's also change this to go right, setting it to 5.

    AltitudeData is 3. I would normally allow all here, but this level has infection fog, so let's go with 5. Medium-high should generate mostly above infection fog (of course that depends on fog settings but we already have existing medium zones and we know those are above fog).

    CoverageMinMax is 40-45. That should result in a zone around medium-ish size. Let's set it to 65-65. We'll hopefully get a huge room and around 2 larges or a mix.

    This is all guesswork. If we wanted precision, we'd have to try mods or keep rerolling the layout until we get what we want. But for now let's roll with what we get, even if it turns out completely different from my expectations.

    hashtag
    Step 4

    The generated zone should be decently big now, so let's have 2 terminals.

    Find TerminalPlacements, we'll set the placement weights to 0, leaving the terminal placement up to rng. Then copy-paste that block.

    The results:

    2 terminal placements in the added zone

    hashtag
    Step 5

    Lights are decided by "LightSettings" field. If this is set to 0, the light settings in rundown db will be chosen instead.

    Right now it's set to 56. If we have a look at the LightSettings datablock and find that entry, we'll see it's named "AlmostWhite_1". Let's try 71 "RustyRedToBrown_1" instead. If you want, you can pick something different or even make your own light settings.

    hashtag
    Step 6

    The sleeper spawning system is convoluted, you can read about it here. Yes I already said it before in this page.

    We'll need the EnemyPopulation and EnemyGroup datablocks, and we'll also still need to make use of LevelLayout. Since we'll have to alternate between several files here, you might want to use split editor.

    We're going to create 1 randomized group of either strikers, shooters, or big strikers, and 1 group with forced scout. We can reuse existing groups and populations but let's make our own for practice. A bottom-up approach is more appropriate here, so let's start with the EnemyPopulation datablock.

    Deleting all existing blocks and remaking from scratch would introduce a few problems with hardcoded ID uses and the current level spawns so let's not do that (but when making full custom rundowns that might be better in the long run). Instead we'll be using numbers that are guaranteed not to mix up with base game blocks.

    I'll follow the "rules" set in enemy spawning system. Considering the special enum values, limitations, and the total size of the enums in base game (ensuring scout entry doesn't step on one), here are the 4 new "RoleDatas" for our population entry:

    chevron-rightOur new population entryhashtag

    These will go inside the "RoleDatas" of the population block that our expedition is using (you can see which population your expedition is using in the Rundown datablock). In our case, our expedition is using an "EnemyPopulation" of 1 (pretty much every level does). So we'll place these new "RoleDatas" at the end of this population, like so:

    circle-info

    Population entries don't have a "Comment" field. But you can add any fields to JSON and as long as there are no syntax errors the game will ignore them. Comment fields have been added for clarity.

    As we can see the role-difficulty pairs are unique so these entries won't be randomized at population-level, only at group-level.

    Now to add enemy groups, these will just go below all the existing enemy groups in the EnemyGroup datablock:

    chevron-rightOur new enemy groupshashtag

    1 forced scout group, and 4 mixed groups of the 3 enemies. Considering the relative weights, this should be a striker-dominant zone. MaxScores are the same all around so these will be a bit more predictable sizes. If we wanted more randomized sizes we could go with a range of 2-6 for example. It's just best not to give really big sizes to groups since a whole group always spawns in the same room, possibly resulting in high concentration in one area and rest zone empty.

    Note I included an update to the LastPersistentID value. That's just so the logs don't clutter saying blocks with IDs above last were found.

    Also remember MaxScore has that obnoxious hardcoded random multiplier on it, screwing with our spawns for no good reason.

    Finally, we can set the spawns in level layout:

    Comments again for clarity.

    30 score spawns + 1 forced scout sounds fair for this zone size, but that of course depends on balancing.

    Also normally you would take a look at the generated layout and settle on it before starting to spawn sleepers.

    hashtag
    Step 7

    All that's left before we finally drop in is resources and consumables.

    Before setting any spawns, always make sure these 2 are set to true in our LevelLayout block:

    Resources are fairly straight-forward and purely dependent on balance so let's just use them to verify ExpeditionBalance values, setting all to 2 - should be 10 uses of each resource.

    Resources set to 2.0 each

    Consumables are set by just one field - "ConsumableDistributionInZone". If we tried to make something specific we'd have to constantly look at ItemDataBlock. Let's do the same as we did with lights and judge by names here instead. We'll have a peek at the names in the ConsumableDistribution datablock.

    It's currently set to 45, "OnlyFogReps_Alt". Fog repeller balancing is important for an infection level, but our zone specifically is set to medium-high altitude data. While it can still generate something under infection fog, it should mostly stick to above that. Our options are combatting darkness, fog, giving foam/tripmines which are very powerful, or just generic consumable distribution that doesn't focus on anything in particular. Let's go with the generic one, setting it to 1.

    hashtag
    Testing the new zone

    A more proper level-making process could be something like this for example:

    1. The entire layout;

    2. Objective;

    3. Resources;

    4. Consumables and other spawns;

    5. Sleepers;

    6. Alarms.

    But since we're just learning we simply focused on a single zone and finally made it to testing.

    hashtag
    Before drop

    In lobby, remember to select the biotracker if you don't have mods that'll let you count and avoid enemies easier (you really should be using some though).

    Before we drop in, we need to be ready for errors. We have 2 options here.

    hashtag
    Option 1: Using bepinex console/UnityLogListening set to true

    If bepinex console is enabled and unity log listening is enabled in bepinex config.

    While dropping in, look at the console to check if you don't see tons of errors (red text) looping, meaning we've entered an infinite cage drop.

    hashtag
    Option 2: No bepinex console/UnityLogListening set to false

    This is if we can't see game logs in bepinex console.

    Open the game logs folder %userprofile%\AppData\LocalLow\10 Chambers Collective\GTFO and locate the current log. Monitor it while dropping in. If the level generation fails, the latest log can start rapidly rising in size, meaning we entered an infinite error loop and will never finish cage drop.

    hashtag
    Either way

    If infinite cage drop happens, exit the game and relaunch after debugging and coming up with a fix. Exiting just the level can work but we can't guarantee no after-effects will carry over to the next drop.

    Even if we drop in successfully we'll check for exceptions to see if anything failed without causing infinite cage drop. During the whole testing process and after exiting the level you should still look at the logs to verify no errors appeared.

    hashtag
    After drop

    Immediately upon dropping in and revealing the map I can something new at the right side of the map generated. Let's compare before/after.

    The level before adding the new zone
    The level after adding the new zone

    We can see the map is the same apart from something new generated at the top right, which would be our zone. However, even without going in to test, it's clearly visible that the zone is not generated from the elevator zone. Verifying this we can see it generated from the zone to the right of elevator, and the source entry is to the north (forward):

    Why did this happen?

    There's no errors in the bepinex console and no particular errors in the game logs, but let's look closer.

    The "BlockAndCleanFailedAreasFromZone" part is ok, it happens. I'm not an LG expert, but if I had to guess I'd say it either collided with other zones or ran out of plugs to connect areas.

    Line 6 explains the cause. Zone 0 has nowhere to generate a security door so it moved on to another zone.

    I'd say LG handled this well but we still need to fix it. A few options here:

    • Expand the elevator zone - screw up the whole existing layout.

    • Move source to zone 103 (right-most zone) - that is a fog zone and there are other balance shenanigans.

    • Move source to zone 102 - this is what LG did.

    Let's go with option 3. We should also change the entrance to north like LG generated because there's likely no entrance to generate on the right side, but we can still try that and see what happens. Spoilers - it still generated from the north. Let's go ahead and change both fields now:

    Here's our map now:

    Map after changing source zone

    We can see it still generated in the same spot, as expected, and this time the layout of the zone is different. This is the exact same map as before changing entrance direction to north.

    Time to explore.

    hashtag
    Exploring the zone

    hashtag
    The layout

    The zone is heading right indeed, it's above fog everywhere except in parts of the last room, which is the huge one so that's expected. The lighting is also as expected. Here's a view of the last room from its entrance:

    Zone 111 area F (the huge area - last room)

    If it seems relatively dark, it's because I'm using the lights adjustment mod.

    Two terminals generated, one near the middle, another at the very end.

    Overall, I would say the layout is a great success.

    hashtag
    The sleepers

    24 total sleepers spawned - 2 big strikers, 1 scout, 11 strikers and 10 shooters. The spread is fair, only one area got 3 groups which is still very manageable. The spawns are very easy in this zone. I would say we can easily double the distribution here unless there's some special reason not to (like an error alarm), but we're not trying to balance the level. The spawns are all there, the count and spread is as expected. The sleepers part is successful.

    hashtag
    The resources

    10 uses of each spawned in various pack sizes. Right on target. If you get a bit more it might still be fine, because there's a base game bug where a resource pack spawns bigger than it should be.

    With consumables we weren't going for anything special, so there's not much to verify apart from the fact that the usual stuff spawned.

    We've seen everything and after leaving the level there are still no errors to see. We've successfully added a new zone.

    hashtag
    Editing existing zones

    Unfortunately, we're still not done here. Out of the things we said we would do in the overview, we still have these to do: alarms, blood doors, spitters, respawns, a generator puzzle, a pitch black zone, and fog.

    Might as well go for some sort of world record in page length.

    Or speedrun the rest of these topics.

    hashtag
    Adding an alarm

    Ah yes, the best difficulty filler in the game, abused on every single level. Even the error shenanigans in R4 are technically all alarms.

    We'll eventually add our alarm by changing our "ChainedPuzzleToEnter" for our new zone in the LevelLayout block, but we'll do things from the ground up again.

    Chained puzzles use 3 other datablocks (in addition to the ChainedPuzzle datablock itself):

    • SurvivalWaveSettings - the wave settings. Defines what, when, how many, and where;

    • SurvivalWavePopulation - wave settings specify what roles can spawn, this block maps roles to enemies, making settings more reusable;

    • ChainedPuzzleType - the types of scans, like full team, big, small, cluster etc. Mostly you just see the names and decide what scan to pick. I don't know any reason to edit this datablock.

    In this example we'll only be editing ChainedPuzzle and SurvivalWaveSettings, though we'll reference things in the other blocks.

    Survival wave population ID 1 will give us striker in standard, shooter in special, and big striker in miniboss. As basic an alarm setup as it gets.

    For survival wave settings let's make something new. Something the base game doesn't do for alarms.

    A little bit of analysis:

    • Updating LastPersistentID to match our new highest PersistentID.

    • Wave pause settings set to basically enforce 30-ish seconds between waves. The little variation is because something bugs if min-max are equal.

    • Population filter (with some help from base game boss bug) will allow only the 3 roles to spawn.

    • The most notable thing here is the limited population. Combined with points per wave, we get exactly 2 waves, with group spawns being more intense on the 2nd wave.

    This alarm should keep the players occupied for at least a minute and depending on their clearing power, not much longer than that.

    circle-info

    Tip: Whenever adding your own custom blocks, always check that the "persistentID"s that you choose aren't already in use.

    Moving on to chained puzzle:

    We're using the blocks we settled on - 400 for our new survival wave setting, and 1 for the basic survival wave population. For scans, one type 33 - the geo scan (introduced in R6.5) (highly likely not to function well in a random geo, but let's try it) - should be enough and we're not disabling the waves when the scan is completed, so the players will have to kill the 2 full waves.

    Now they could just cheese it by running away and mining wherever until the population runs out, but from my experience they don't do that:

    1. Barely anybody even notices something out of the ordinary with spawns when they're made well. If they do, they don't realize the specifics.

    2. People hate wasting time. Even with cheese they'd have to sit in a sustain full-team scan for a while doing absolutely nothing.

    All that's left is to set "ChainedPuzzleToEnter": 300 in our level layout and test.

    Unsurprisingly the geo scan is screwed up but it's mostly functional so it's fine. Moving on.

    hashtag
    Adding a blood door

    circle-exclamation

    As noted here, only hunter groups work properly for blood doors.

    The new zone has suffered enough so let's leave it alone for now. Let's add a blood door to the zone left from the elevator - localIndex 1.

    Setting up a blood door is fairly easy as long as you know your enemy groups. It's controlled by "ActiveEnemyWave" in level layout. Let's skip making hunter groups this time and just see what's in stock. I see "Hunter Easy Bullrush" in groups with ID 32. MaxScore 8 makes me guess it should be about 8 spawns, but it seems the cost is 2 in population so it's actually 4. Let's spawn one group on the door and 2 in the area for a total of 12 chargers:

    A quick test here shows the predictions were spot on. On to the next topic.

    hashtag
    The rest

    Spitters, respawns, a generator puzzle, a pitch black zone, fog - we've got 5 things left to do, and at this point I feel like we've had enough practice to tackle them without too many details.

    hashtag
    Spitters

    Spitters are static spawn enemies, controlled by "StaticSpawnDataContainers". This references StaticSpawnDataBlock, but it's rare to edit that directly in my experience. We can tackle just the level layout datablock after seeing that spitters are ID 1 in static spawns. Here's our block, placed in the first zone:

    We're spawning just a few because I hate spitters. Most fields besides the ID and Count are for location randomization.

    hashtag
    Respawns

    Respawner sacks are also a static spawn I believe, but they seem to be a special one, you only set up enemy respawning and they'll spawn automatically. So let's do that, again placing them in the first zone because we hate everyone who plays our levels:

    The fields are all straight-forward here, but as always you can check the datablock reference for explanations. We don't need any respawn exclusions here so we don't even need to have that field.

    Now when we messed with expedition balancing we reduced the first zone's population to barely anything, and there will be few respawn sacks as well because of that. Still enough to verify it's there and respawn works though.

    hashtag
    Generator puzzle

    I was going to make a keycard puzzle but we already have that example in the early zones. And generators have a little optional trick - we can spawn cells using big pickups distribution instead of ZonePlacementData. Scientific research suggests that thanks to how markers are set up, we'll get more possible placements inside our zone using big pickups instead of zone placement.

    In zone 0, set ForceBigPickupsAllocation to true and BigPickupDistributionInZone to 5. In zone 1, set PuzzleType to 2 and PlacementCount to 0.

    Now the zone to the left of spawn should require a generator to be activated which spawns in its entrance zone, and in elevator zone we spawned a cell using big pickups.

    hashtag
    Pitch black zone

    This one's just a matter of light settings, and there already seem to be 2 settings for darkness. Let's set LightSettings to 73 in zone 1.

    hashtag
    Editing fog

    This can't be set per zone, we can either edit the level's fog settings or setup some warden objective stuff. From rundown db we can see the level uses FogSettings with an ID of 90. We should copy that to a new persistent ID and set it, then edit the settings. But let's just edit ID 90 directly in the FogSettings datablock.

    If we don't want to flip the balance of the level, we can only do something boring, which means we're flipping the balance of the level. Here are the new settings:

    Fog density has been increased, altitude moved way up to 5, range and max boost changed to 0. Now the fog is upside-down and cancer is in the high zones instead of low. Flip successful.

    If you didn't test these 5 parts yet, now's the time. We're all done with the changes. Here's a picture where you can see the fog, generator, spitters, and respawners:

    Zone 0 showing the changes made

    Bonus points if you get hit by a spitter as soon as you drop in.

    hashtag
    Afterword

    I would like to thank all my fans, my mother, and everyone that supported me. I finally got to finish this damn page.

    Jokes aside, we can finally move on to warden objective. That topic's not simple either but fortunately I just have to settle on one thing and I get to choose a simple objective.

    hashtag
    Extra

    I mentioned typelist blocks before so I thought I'd throw in a few examples of how our blocks would look like then:

    Added zone build parameters
    Added zone sleeper spawns
    Added enemy groups
    Added survival settings

    Creating a Patch class

    The following Patch class will use HarmonyX to allow us to modify how GTFO behaves

    First, in Visual Studio, click Project > Add Class and change Class1.cs to Patch.cs

    Next replace the pre-generated code with the following

    After that go back to our Plugin class and add the following line to your Load method

    new Harmony("NewbiePluginAuthor.MyFirstPlugin").PatchAll();

    You can now compile the plugin and when you click the About Rundown button in-game you will unlock a new rundown

    hashtag
    Explaining how this works

    The line we added to our load method means that when the plugin loads it will create a Harmony instance and apply all the patches it can find (note we supply Harmony with the same GUID we saw earlier). The [HarmonyPatch] attribute we gave our Patch class helps Harmony find it (though it isn't always required depending on how you go about patching).

    When Harmony finds our Patch class it'll then look for any patching methods. The attributes we gave to the MyPatch method label it as such a patching method. The [HarmonyPostfix] attribute tells Harmony a little about how we want to do our patch while the [HarmonyPatch(...)] attribute tells Harmony what we want to patch. In this case it specifies that we want to patch the Setup method in the CM_PageRundown_New class. Our patch replaces the action of the about rundown button with our own code.

    triangle-exclamation

    If multiple patch classes are desired first create a harmony instance and then use the types

    circle-info

    To find more information on how to use HarmonyX please reference their

    Creating a C# class library project

    How to set up your project for editing and compiling

    circle-info

    We will be creating a Library project written in C# targeting all platforms

    First create a new project and choose "Class Library" - "A project for creating a classlibrary that targets .NET or .NET Standard"

    Then write a name into the Project name field, such as "MyFirstPlugin" and click "Next"

    Next ensure you have ".NET 6.0 (Long-term support)" selected as your Framework and click "Create"

    circle-info

    When the project is finished creating you should see "Class1.cs" open

    Click Project > Edit Project File and replace it with the following

    circle-exclamation

    The following project settings assume you have r2modman installed in the Default location with BepInEx installed and run at least once

    circle-info

    You can change which r2modman profile is used by editing the Profile property Additionally, you can also change the BepInEx path to your preferred location by editing the BepInEx property

    Finally save the changes to the csproj file

    circle-check

    You should now be ready to create your Plugin class

    Setting up Visual Studio Community

    Visual Studio Community allows you to navigate, edit and compile code.

    1. Download Visual Studio by click "Free Download" underneath the Community section

    2. Run "VisualStudioSetup.exe" from your download folder

    3. Continue through the process until you get to the "Installing" window with the "Workloads" tab

    Compiling for release

    We will be compiling our plugin for release, meaning that there will be no debugging options set up

    First Click Build > Configuration Manager in Visual Studio

    Then in the Configuration Manager window, change Active solution configuration from "Debug" to "Release", then click close

    Next Click Build > Build Solution

    circle-info

    If you used the earlier project settings your plugin should now be created inside your r2modman profile

    Patching in slightly more detail

    This is a very basic summary of patching. See the for more details.

    hashtag
    Why patching

    Typically, when making a plugin, developers will want to change how something in the base game behaves. Of course, in order to change the normal behavior we need to know what piece(s) of code in the base game determine that behavior so that we can target them with a patch. This means that part of the challenge of making a plugin is determining which method(s) to patch in the first place! If you're unsure how to go about determining which methods to target consider asking in our .

    Writing a Plugin class

    The following Plugin class will allow BepInEx to load and handle your compiled assembly as a plugin

    In Visual studio right click "Class1.cs" in the solution explorer and rename it to "Plugin.cs". Choose "Yes" to rename all references

    circle-info

    If you do not have a Class1.cs you can create Plugin.cs instead by choosing Project > Add Class...

    Copy and paste the following code into "Plugin.cs" replacing the entire contents of the file

            {
              "Role": 5,
              "Difficulty": 20,
              "Enemy": 20,
              "Cost": 5.0,
              "Weight": 1.0,
              "Comment": "Scout"
            },
            {
              "Role": 100,
              "Difficulty": 100,
              "Enemy": 24,
              "Cost": 1.0,
              "Weight": 1.0,
              "Comment": "Diff 100 - group-randomized Striker_Hibernate"
            },
            {
              "Role": 101,
              "Difficulty": 100,
              "Enemy": 26,
              "Cost": 1.0,
              "Weight": 1.0,
              "Comment": "Diff 100 - group-randomized Shooter_Hibernate"
            },
            {
              "Role": 102,
              "Difficulty": 100,
              "Enemy": 28,
              "Cost": 4.0,
              "Weight": 1.0,
              "Comment": "Diff 100 - group-randomized Striker_Big_Hibernate"
            }
        {
          "Type": 1,
          "Difficulty": 20,
          "SpawnPlacementType": 0,
          "MaxScore": 5.0,
          "ScoreInAreaPaddingMulti": 1.0,
          "RelativeWeight": 1.0,
          "Roles": [
            {
              "Role": 5,
              "Distribution": 1
            }
          ],
          "name": "Forced Scout",
          "internalEnabled": true,
          "persistentID": 100
        },
        {
          "Type": 0,
          "Difficulty": 100,
          "SpawnPlacementType": 0,
          "MaxScore": 4.0,
          "ScoreInAreaPaddingMulti": 1.0,
          "RelativeWeight": 1.0,
          "Roles": [
            {
              "Role": 24,
              "Distribution": 4
            },
            {
              "Role": 26,
              "Distribution": 2
            }
          ],
          "name": "Diff 100 3 strikers 1 shooter",
          "internalEnabled": true,
          "persistentID": 101
        },
        {
          "Type": 0,
          "Difficulty": 100,
          "SpawnPlacementType": 0,
          "MaxScore": 4.0,
          "ScoreInAreaPaddingMulti": 1.0,
          "RelativeWeight": 0.5,
          "Roles": [
            {
              "Role": 24,
              "Distribution": 3
            },
            {
              "Role": 26,
              "Distribution": 3
            }
          ],
          "name": "Diff 100 2 strikers 2 shooters",
          "internalEnabled": true,
          "persistentID": 102
        },
        {
          "Type": 0,
          "Difficulty": 100,
          "SpawnPlacementType": 0,
          "MaxScore": 4.0,
          "ScoreInAreaPaddingMulti": 1.0,
          "RelativeWeight": 0.1,
          "Roles": [
            {
              "Role": 26,
              "Distribution": 5
            }
          ],
          "name": "Diff 100 4 shooters",
          "internalEnabled": true,
          "persistentID": 103
        },
        {
          "Type": 0,
          "Difficulty": 100,
          "SpawnPlacementType": 0,
          "MaxScore": 4.0,
          "ScoreInAreaPaddingMulti": 1.0,
          "RelativeWeight": 0.2,
          "Roles": [
            {
              "Role": 28,
              "Distribution": 5
            }
          ],
          "name": "Diff 100 1 big striker",
          "internalEnabled": true,
          "persistentID": 104
        }
      ],
      "LastPersistentID": 9999
          "HealthPerZone": 1.0,
          "DisinfectionPerZone": 1.0,
          "WeaponAmmoPerZone": 0.8,
          "ToolAmmoPerZone": 0.7,
          "ArtifactsPerSegment": 1,
          "ArtifactsPerLayer": 30,
          "EnemyPopulationPerZone": 25.0
              "EnemySpawningInZone": [
                {
                  "GroupType": 1,
                  "Difficulty": 20,
                  "Distribution": 1,
                  "DistributionValue": 1,
                  "Comment": "1 forced scout"
                },
                {
                  "GroupType": 0,
                  "Difficulty": 100,
                  "Distribution": 2,
                  "DistributionValue": 3,
                  "Comment": "diff 100 30 score randomized groups"
                }
              ],
              "AllowSmallPickupsAllocation": true,
              "AllowResourceContainerAllocation": true,
    Next Batch: GenerateZones - Count: 12
    
    14:39:39.745 - <color=#C84800> ---- MainLayer ---- Picked build from area : Area_A</color>
    14:39:39.808 - BlockAndCleanFailedAreasFromZone >  ZoneAlias: 102 dim:Reality  AreaCount: 1  ZoneCoverageOnFail:10  ZoneMinCoverage:40  CoverageStatus:NotEnough
    14:39:40.490 - BlockAndCleanFailedAreasFromZone >  ZoneAlias: 111 dim:Reality  AreaCount: 1  ZoneCoverageOnFail:10  ZoneMinCoverage:65  CoverageStatus:NotEnough
    14:39:40.491 - WARNING : Zone11 (Zone_11 - 111): Failed to find any good StartAreas in zone 0 (100) expansionType:Towards_Right m_buildFromZone.m_areas: 5 scoredCount:0 dim: Reality
    14:39:40.491 - BlockAndCleanFailedAreasFromZone >  ZoneAlias: 111 dim:Reality  AreaCount: 5  ZoneCoverageOnFail:39  ZoneMinCoverage:65  CoverageStatus:NotEnough
    14:39:40.491 - BlockAndCleanFailedAreasFromZone >  ZoneAlias: 111 dim:Reality  AreaCount: 1  ZoneCoverageOnFail:3  ZoneMinCoverage:65  CoverageStatus:NotEnough
    14:39:40.552 - Last Batch: GenerateZones
              "BuildFromLocalIndex": 2,
              "StartExpansion": 1,
        {
          "m_pauseBeforeStart": 0.0,
          "m_pauseBetweenGroups": 5.0,
          "m_wavePauseMin_atCost": 49.0,
          "m_wavePauseMax_atCost": 50.0,
          "m_wavePauseMin": 29.0,
          "m_wavePauseMax": 30.0,
          "m_populationFilter": [
            0
          ],
          "m_filterType": 1,
          "m_chanceToRandomizeSpawnDirectionPerWave": 1.0,
          "m_chanceToRandomizeSpawnDirectionPerGroup": 0.1,
          "m_overrideWaveSpawnType": false,
          "m_survivalWaveSpawnType": 0,
          "m_populationPointsTotal": 60.0,
          "m_populationPointsPerWaveStart": 30.0,
          "m_populationPointsPerWaveEnd": 30.0,
          "m_populationPointsMinPerGroup": 5.0,
          "m_populationPointsPerGroupStart": 5.0,
          "m_populationPointsPerGroupEnd": 10.0,
          "m_populationRampOverTime": 60.0,
          "name": "2 intense waves",
          "internalEnabled": true,
          "persistentID": 400
        }
      ],
      "LastPersistentID": 400
        {
          "PublicAlarmName": "Geo Alarm",
          "TriggerAlarmOnActivate": true,
          "SurvivalWaveSettings": 400,
          "SurvivalWavePopulation": 1,
          "DisableSurvivalWaveOnComplete": false,
          "UseRandomPositions": true,
          "WantedDistanceFromStartPos": 0.0,
          "WantedDistanceBetweenPuzzleComponents": 1.0,
          "ChainedPuzzle": [
            {
              "PuzzleType": 33
            }
          ],
          "OnlyShowHUDWhenPlayerIsClose": false,
          "AlarmSoundStart": 3339129407,
          "AlarmSoundStop": 42633153,
          "name": "Geo alarm 2 waves",
          "internalEnabled": true,
          "persistentID": 300
        }
          "ActiveEnemyWave": {
            "HasActiveEnemyWave": true,
            "EnemyGroupInfrontOfDoor": 32,
            "EnemyGroupInArea": 32,
            "EnemyGroupsInArea": 2
          },
          "StaticSpawnDataContainers": [
            {
              "Count": 10,
              "DistributionWeightType": 1,
              "DistributionWeight": 1.0,
              "DistributionRandomBlend": 0.5,
              "DistributionResultPow": 2.0,
              "StaticSpawnDataId": 1,
              "FixedSeed": 0
            }
          "EnemyRespawning": true,
          "EnemyRespawnRequireOtherZone": true,
          "EnemyRespawnRoomDistance": 2,
          "EnemyRespawnTimeInterval": 10.0,
          "EnemyRespawnCountMultiplier": 1.0,
    {
      "Enabled": true,
      "FogColor": {
        "a": 0.03137255,
        "r": 0.4392157,
        "g": 0.7529412,
        "b": 0.5176471
      },
      "FogDensity": 0.005,
      "FogAmbience": 0.0,
      "DensityNoiseDirection": {
        "x": 0.0,
        "y": -1.0,
        "z": 0.0,
        "magnitude": 1.0,
        "sqrMagnitude": 1.0
      },
      "DensityNoiseSpeed": 0.034,
      "DensityNoiseScale": 0.1,
      "DensityHeightAltitude": 5.05,
      "DensityHeightRange": 0.0,
      "DensityHeightMaxBoost": 0.0,
      "Infection": 0.03,
      "name": "Fog_lightest_White_low1_INFECTION_R6_B2",
      "internalEnabled": true,
      "persistentID": 90
    },
    using CellMenu;
    using HarmonyLib;
    using UnityEngine;
    using UnityEngine.Diagnostics;
    
    namespace MyFirstPlugin;
    
    [HarmonyPatch]
    internal static class Patch
    {
        [HarmonyPatch(typeof(CM_PageRundown_New), nameof(CM_PageRundown_New.Setup))]
        [HarmonyPostfix]
        public static void MyPatch(CM_PageRundown_New __instance)
        {
            __instance.m_aboutTheRundownButton.OnBtnPressCallback = (Action<int>)((_) => { Application.ForceCrash((int)ForcedCrashCategory.Abort); });
        }
    }
    
    circle-check

    You should now be able to launch your modded game and see in the BepInEx log our logged message

  • Under the "Desktop & Mobile" section select ".NET desktop development"

  • Under the "Gaming" section select "Game development with Unity"

  • Once you have your preferred components selected click "Install" on the bottom right

  • Wait for the heat death of the universe until your IDE is installed

  • Continue through the rest of the set up until a "Get started" window appears

  • circle-info

    Signing in to Visual Studio is optional

    circle-check

    You should now be ready to create your C# class library project

    herearrow-up-right
    hashtag
    Patching

    The two basic kinds of patches are Prefix and Postfix patches. Both of these target some original method in the game's code in the same way through the [HarmonyPatch(...)] attribute (though there are also more complicated ways to determine which method they target).

    hashtag
    Postfix Patches

    Postfix patches use the [HarmonyPostFix] attribute. Postfix patches run after the original method. As with any patch this allows you to run any code you want at this point, but also importantly, this can let you alter the normal return value of that method.

    hashtag
    Prefix Patches

    Prefix patches use the [HarmonyPreFix] attribute. Prefix patches run before the original method. They can alter the arguments of the original method before that method runs. They can also control whether or not to skip the original method completely.

    Unfortunately, a more complicated kind of patch (Transpiler patches) which offers some unique benefits doesn't quite work with how GTFO is compiled.

    harmony documentationarrow-up-right
    Discord Serverarrow-up-right
    var harmony = new Harmony("NewbiePluginAuthor.MyFirstPlugin");
    harmony.PatchAll(typeof(RundownPatch));
    harmony.PatchAll(typeof(PlayerPatch));
    harmony.PatchAll(typeof(EnemyPatch));
    Github Wikiarrow-up-right
    <Project Sdk="Microsoft.NET.Sdk">
    	<PropertyGroup>
    
    		<!--
    		Use the following property to set your preferred r2modman profile
    		-->
    		<Profile>Default</Profile>
    
    		<TargetFramework>net6.0</TargetFramework>
    		<ImplicitUsings>enable</ImplicitUsings>
    		<Nullable>enable</Nullable>
    		<DebugType>None</DebugType>
    		<AssemblyName>$(SolutionName)</AssemblyName>
    		<RootNamespace>$(SolutionName)</RootNamespace>
    		<BepInEx>$(AppData)\r2modmanPlus-local\GTFO\profiles\$(Profile)\BepInEx</BepInEx>
    		<BuildDirectory>$(BepInEx)\plugins\$(SolutionName)\</BuildDirectory>
    		<OutputPath>$(BuildDirectory)</OutputPath>	
    		<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
    	</PropertyGroup>
    	<Target Name="PostBuild" BeforeTargets="PostBuildEvent">
    		<Delete Files="$(OutputPath)$(AssemblyName).deps.json" />
    	</Target>
    	<ItemGroup>
    		<Reference Include="$(BepInEx)\core\0Harmony.dll" Private="false" />
    		<Reference Include="$(BepInEx)\core\BepInEx.Core.dll" Private="false" />
    		<Reference Include="$(BepInEx)\core\BepInEx.Unity.IL2CPP.dll" Private="false" />
    		<Reference Include="$(BepInEx)\core\Il2CppInterop.Common.dll" Private="false" />
    		<Reference Include="$(BepInEx)\core\Il2CppInterop.Runtime.dll" Private="false" />
    		<Reference Include="$(BepInEx)\interop\*.dll" Private="false" />
    		<Reference Remove="$(BepInEx)\interop\netstandard.dll" />
    	</ItemGroup>
    </Project>
    circle-info

    If you do not see where to paste the code into, double click the Plugin.cs file in the solution explorer

    Save your changes by selecting File > Save Plugin.cs

    circle-check

    You should now be ready to compile your first plugin

    hashtag
    Explaining how this work

    We create a new class that inherits from the BepInEx BasePlugin class. We give this new class a special attribute (the BepInPlugin thing above the class) which BepInEx uses to make this class into a full-fledged plugin. The arguments we supply to the attribute include:

    • The GUID: "NewbiePluginAuthor.MyFirstPlugin" This is an identifier which should uniquely identify the plugin. Typically just author.pluginname should suffice.

    • The plugin name: "MyFirstPlugin"

    • The plugin version: "1.0.0" This uses .

    Adding Custom Audio

    Mr Bro will teach you how to create soundbanks to add custom sounds

    hashtag
    What is Wwise?

    Audiokinetic Wwise is a software development kit (SDK) for audio content creation and integration in games and other interactive media, the tool used by 10CC to integrate audio into GTFO. Wwise also includes a soundbank system, which allows developers to organize and access their audio content, using sound events. To add custom sounds to GTFO, we will have to use Wwise and create SoundBanks within the application.

    hashtag
    What is a SoundBank?

    A SoundBank is a container of sound events, and the objects and audio data required to play them. GTFO uses SoundBanks created by Wwise to play all of its audio in-game, ranging from its dynamic music system to enemy sound effects.

    Who is Mr Bro?

    Hi there, my name is Mr. Bro and I'm a big fan of the video game GTFO. Everyone has been asking for ways to add custom sound and here is a guide on how to do so! Looking into it I have found a way how to use Wwise to create custom soundbanks and have created a plugin to put these soundbanks into GTFO. Personally it was very difficult at first, but I look forward to hearing feedback from other players and continuing to improve my creations!

    Project Setup

    Step 1: Download the Wwise launcher from the link below. From inside the launcher, download Wwise version 2017.1.9.6501.

    You also probably want to use audacity to convert audio files to the .wav file format, because that's what Wwise requires. The download link is below.

    Step 2: Using Wwise version 2017.1.9.6501 create a new project, and uncheck all of the asset groups, none are required for our SoundBanks.

    Adding Sounds into Wwise

    Step 1: In the project explorer, right-click on the Default Work Unit in the Actor-Mixer Hierarchy, and in "New Child", select "Actor-Mixer". Name this Actor-Mixer "SFXmixer"

    Step 2: Right-click SFXmixer and create a new folder, and name it whatever you want. We will be putting all our sounds into this folder.

    Step 3: Drag your .wav files directly into this folder in the hierarchy inside Wwise. It should prompt you with import settings, click import.

    Step 4: Click on your sound, and in the Sound Property Editor, click on the "Positioning" tab. Check the "Override parent" box.

    Step 6: Change the positioning to "3D". (Note: You can change the volume of your sound, or make your sound loop continuously in the "General Settings" tab)

    Audio files

    How to setup foobar2000 with the vgmstream component to play and extract the audio files from GTFO

    hashtag
    Setup and playback

    1. Download and install foobar2000arrow-up-right

    2. Download and open

    3. Open foobar2000 and choose File > Add Folder

    4. Find and add the following folder: ~\Steam\steamapps\common\GTFO\GTFO_Data\StreamingAssets\GeneratedSoundBanks\Windows

    5. Open the SoundbanksInfo.xml in a text editor to see what audio files the game uses

    6. In foobar2000 search for the file id with Ctrl + F

    7. Double click the audio to listen to it

    hashtag
    Converting files

    1. In foobar2000 right click a track

    2. Choose Convert > Quick Convert

    3. Choose an output setting and click Convert

    Creating a Sound Event

    Step 1: In the "Events tab", click on the "Default Work Unit" in the "Events" folder, and create a new "Play" sound event. Click on the "Play" sound event you created.

    Step 2: Click back onto the "Audio" tab, and drag your sound from the hierarchy into the "Target" box in the Event Editor. (Note: This Event Editor will only display given you clicked on the "Play" event in the Events tab)

    Using SoundBanks in GTFO

    Step 1: Add BepInExPack_GTFO, MTFO (if you don't have them already) as a dependency to your profile/mod.

    Step 2: In your profile, add the .bnk and .txt file to the path:

    (Profile)/
    └──BepInEx/
        └──Assets/
            └──SoundBank/
               └──(your soundbanks)

    (Create the "Assets" and "SoundBank" folder if they don't exist)

    Step 3: Use the sound event ID inside the .txt file to put into MTFO datablocks to use your sound ingame. Make sure to use the sound event ID (highlighted below) which is located on the upper half of the file, not the audio ID which is located on the lower half of the file.

    This sound event ID can be used in in-game events, as well as:

    GameData_EnemySFXDataBlock_bin

    GameData_ChainedPuzzleDataBlock_bin

    GameData_MeleeSFXDataBlock_bin

    There's also a DataBlock for weapon sound effects, but ¯\_(ツ)_/¯

    Mr Bro out

    using BepInEx;
    using BepInEx.Unity.IL2CPP;
    
    namespace MyFirstPlugin;
    
    [BepInPlugin("NewbiePluginAuthor.MyFirstPlugin", "MyFirstPlugin", "1.0.0")]
    public class Plugin : BasePlugin
    {
        public override void Load()
        {
            // Plugin startup logic
            Log.LogInfo("MyFirstPlugin is loaded!");
        }
    }
    semantic versioningarrow-up-right
    Select an output path and save
    vgmstream foobar componentarrow-up-right

    Fixing Unity errors after importing

    How to fix the numerous errors when importing asset files from GTFO

    triangle-exclamation

    Please for the love of god expand this section

    Export asset files from GTFO

    Export unity asset files from GTFO

    1. Download the latest AssetRipper_win_x64.ziparrow-up-right

    2. Extract the AssetRipper files and run AssetRipper.exe

    3. Change the following settings

      • Check Skip StreamingAssets Folder

    4. Choose File > Open Folder

    5. Navigate to and select the following folder ~\Steam\steamapps\common\GTFO

    6. After it loads the game content choose Export > Export all Files and select an output folder

    circle-check

    You are now ready to import the asset files into a unity project

    Import asset files to Unity

    Import GTFO asset files into Unity

    circle-exclamation

    Unity version 2019.4.21f1arrow-up-right is required to create a project for GTFO

    1. Open Unity Hub and in the Projects tab click the drop-down button next to Open

    2. Select Add project from disk and navigate to your exported assets folder

    3. Choose the "ExportedProject" folder and ensure the editor version is correct

    4. Open the project in Unity Hub and wait for Half-Life 3

    5. Enjoy the numerous errors

    Creating a SoundBank

    Step 1: Click on the "SoundBanks" tab, right-click the "Default Work Unit", and create a new Soundbank. After doing this, press F7 to open the SoundBank workstation, or press the "Layouts" tab in the window menu, and selected "SoundBanks". You can press F5 to close the Manager, or use the aforementioned tab.

    Step 2: Click on the "Events" tab, and drag your "Play" sound event into the SoundBank Editor.

    If you want to create more sound events, you can drag them into the same SoundBank. This includes "Stop" events, which will stop a sound playing, which is necessary for stopping looping sounds. (e.g. Door alarms)

    Step 3: To export the SoundBank, right-click the SoundBank in the SoundBank Manager, and "Generate SoundBank(s) for current platform", or press Shift-F7.

    Step 4: To view your SoundBank file, right-click the SoundBank in the SoundBank Manager, and select the last option in the drop down menu, "Open Containing Folder", for the SoundBank. (Make sure not to select the second last option that opens the folder for the Work Unit.)

    You should end up with two files, the .bnk file (the SoundBank itself), and a .txt file, containing your Event IDs. This .txt file is necessary for using your SoundBank.

    Modded GTFO on Linux

    basically like it's done on windows

    hashtag
    Steam, GTFO, R2modman

    • make sure your gfx drivers are good (other games, glxgears work etc)

    • install linux-native steam

    • login to steam

    • install GTFO

    • launch GTFO, make sure it launches and works okay

    • if "not responding" after trying to start a level, try x11 instead of wayland (on ubuntu you log out, select user, on password screen you go bottom right of screen gears -> ubuntu on xorg)

    • download r2modman for your distro from

    • launch r2modman, select GTFO, should detect your GTFO directory, can be set from settings if not

    • create a profile, install the mods you want in it

    • click on launch modded, modded launches, enjoy

    • Tested to work with r2modman 3.1.34, earlier versions needed some extra steps to launch modded properly (like creating a bat-file to launch modded and a doorstop_config.ini file with a full path to the BepInEx.Unity.IL2CPP.dll file etc)

    Introduction to Errors

    You will run into some if you play enough modded. You might have already run into some without even knowing it. You have already run into some you don't even know about.

    hashtag
    Overview

    Originally covered in The Complete Newbie Guide, but it deserves its own page. Besides, it's useful for all users.

    Errors and exceptions often mean something went wrong either with the game or a mod. There's an infinite number of causes so it's impossible to know all of them, but it's important to know where to start looking for information. At the very least you can pass on more when looking for help. If you do run into something you can't fix yourself, you can ask in the tech support channelarrow-up-right in the modding discord.

    hashtag
    Important distinctions

    • Error/Exception - while in a way they mean the same thing to a user, the distinct difference is that if you see "error", it is printed by programmers, whereas "exception" shows that it came straight from code.

    • BepInEx logs/game logs - BepinEx logs are shown in the console window and LogOutput.log, meanwhile game logs are stored in %userprofile%\AppData\LocalLow\10 Chambers Collective\GTFO. While some information overlaps, game logs show more useful base game error information, and show a good amount of non-error information as well.

    hashtag
    Viewing errors

    When launching the game with mods enabled, you'll see the BepInEx console as a separate window.

    This console is useful for many things, but most importantly for users, it shows most errors in red text. If it's not a red text error, it can be relevant to rundown developers specifically, so it's not covered here.

    circle-info

    Not all red text means you have to do something about it. Some mods post meaningless errors on purpose (although they really shouldn't), and some base game errors are meaningless as well.

    In the case of mods, the message is probably something intentionally stupid.

    In the case of game errors, check the game logs to see if they contain that error. If they don't, you can probably ignore it.

    All logged messages have the type and source as a prefix. E.g. [Error: MTFO] error message shows that there was an error caused by the mod MTFO. Most of the time errors are thrown by the game itself (but the underlying cause can still be a mod), in which case you will see [Error: Unity] as the prefix. In this case it is recommended to look for the error in the game logs instead of BepInEx logs. These are located in %userprofile%\AppData\LocalLow\10 Chambers Collective\GTFO If you closed the game already, their name will be of the following format: GTFO.[Date].[Time]_[PlayerNick]_[NetworkStatus]. If the game is still open (or crashed), it'll instead be GTFO.[Date].[Time]_NICKNAME_NETSTATUS. For the most part you will be looking for the most recent file created.

    circle-info

    It is also possible to see an error coming from something that doesn't match any mod names nor base game (such as Preloader or Detour). Treat it as an error coming from mods in that case.

    While in BepInEx console the error message is one line, the game logs provide the stack trace, which is the full source of the error and often provides much more information than just the error message.

    Let's take a look at an example. BepInEx console shows this error message:

    While the game logs show this:

    NullReferenceException is one of the most common errors that says next to nothing about the cause. All we know from BepInEx console is that an error happened, but the game logs show that the source is from melee weapons. Even if this error doesn't give enough information to you, it will allow other people to find the cause faster if you ask for help.

    Also note that some errors can cause even more errors. When debugging, check the oldest errors first.

    https://github.com/ebkr/r2modmanPlus/releasesarrow-up-right

    Datamining

    How to retrieve sounds, assets, models, etc. from the game files

    circle-info

    This section is still in development

    BepInEx console window
    NullReferenceException: Object reference not set to an instance of an object.
    18:17:44.732 - NullReferenceException: Object reference not set to an instance of an object.
    Gear.MeleeWeaponFirstPerson.UpdateInput () (at <00000000000000000000000000000000>:0)
    Gear.MeleeWeaponFirstPerson.UpdateLocal () (at <00000000000000000000000000000000>:0)

    Creating Custom Weapons

    Most information below this point has been reproduced from Mccad00's "How to make custom weapons for GTFO" guidearrow-up-right, with updates, additions, and clarifications.

    In most, if not all cases, information from the actual DataBlock pages on this wiki is marginally more up-to-date than whatever is reproduced in this guide - please refer to the DataBlock pages if there are discrepancies.

    In GTFO, weapons are composed of a large number of DataBlocks which provide stats, determine behavior, recoil data, and configure their appearance.

    Fortunately, you only really have to understand the green-highlighted entries in this chart.

    Before going any further, it’s important that you understand what main DataBlocks contain weapon data, and what data are in each.

    • : Creates an inventory object that players can select in the lobby and then use in-game by defining a collection of 3d objects (weapon parts) and associating them with data from a entry, as well as some other DataBlock entries.

    • : Groups together 4 entries and 1 entry.

    • : Defines weapon statistics and associates a entry with them, in addition to referencing other metadata.

    • : Defines what inventory slot a piece of equipment uses, controls its HUD elements, and defines what type of Item it is.

    Note: There will be some DataBlock information reproduced in this guide. For clarity, inline comments have been added. Again, please refer to the actual datablock pages for more detail.

    hashtag
    Archetype

    At the heart of every weapon in GTFO is the , which determines a gun’s statistics and metadata. Like most DataBlocks, there are many fields and not all of them are always relevant.

    This is a very terse guide to this DataBlock - please see the actual page for more details.

    Note: Any new weapon Archetype you create needs a unique PersistentID for its data. Keep track of this ID as you’ll be using it in the GearCategory DataBlock.

    hashtag
    GearCategory

    Perhaps the most baffling DataBlock involved in custom weapons and gear is the GearCategory DataBlock. The GearCategory system is designed to group together 4 archetype DataBlock entries into one category and assigns them an entry in the Item Datablock, which is used to assign the weapons behavior on the HUD and a slot in the inventory to fit into. Let’s take a look at an example.

    Note: Any new GearCategory you create needs a unique PersistentID for its data. Keep track of this PersistentID so you can reference it in the PlayerOfflineGearDataBlock.

    hashtag
    GearCategoryDataBlock: PartAlignPriority

    Sometimes, multiple parts in a GearJSON will share the same aligns as each other, which will result in one of the parts defaulting to have that align. In order to control which parts get the align in cases like this, we need to edit the PartAlignPriority in the GearCategoryDataBlock. The GearCategory which is linked to your weapon via the ‘Category’ component type will determine which GearCategory you need to modify for this. Let’s look at the Magnum’s part align priority to see how it works:

    "AlignType": This corresponds to the Enum that is used by Aligns in the GearDataBlocks.

    "PartPrio": A list of gear component types, ordered by priority. This determines which part to assign this align to.

    So, this set of align priorities means that align types 7 and 8 (LeftHand and RightHand) are both going to prioritize part 12. From this setup, we can guess that this is probably necessary so that both hands align on the grip.

    hashtag
    PlayerOfflineGear

    In GTFO, almost every piece of equipment is assembled programmatically to get more mileage out of the limited assets the game shipped with.

    Weapons, tools, and even some consumables are put together using this system. For the sake of simplicity, we will refer to these assembled items as ‘Gear’. Every assembled Gear item in GTFO is set up in the PlayerOfflineGearDataBlock via a string called GearJSON.

    hashtag
    GearJSON formatting

    To start, let’s break down the GearJSON string for the Pistol:

    Note: Line breaks have been added into this string for the explanation, but in your DataBlock the entire string must be on a single line with no linebreaks.

    "{\"Ver\":1,\"Name\":\"Shelling S49\", This line assigns the GearJSON a ‘descriptive name’, which is displayed in your inventory and in the lobby screen.

    \"Packet\":{\"Comps\":{\"Length\":16, This line tells the game how many gear components your part contains. If this number doesn’t match the actual number of gear components, the game won’t read the GearJSON string correctly.

    \"a\":{\"c\":2,\"v\":8}, This line defines a gear component to add to our GearJSON, which is broken up into 3 values:

    1. \"a\" The index, in alphabetical order, of this gear component. Notice in our example that every component starts with a unique letter identifier.

    2. \"c\":2 The component type, such as FrontPart, ReceiverPart, or StockPart. In this component, type is ‘2’ which corresponds to GearCategory. If you attempt to use the same component type on multiple components, only one of them will load.

    3. "V\":8

    The ending section of the GearJSON string, starting with \"MatTrans\", is not used by the game.

    You can have as many gear components as you want in a GearJSON, provided you use correct syntax to define them. Because of the complexity and obscurity of GearJSON strings, writing one from scratch is discouraged. Instead, duplicating and modifying an existing GearJSON from the base game is a simpler method that will save you time (and sanity).

    hashtag
    Gear Component Types

    Note: Unused/Unusable component types are omitted.

    ID
    Component Type
    Description

    Note: Even though the developers typically only used appropriate parts, you can actually use any of these parts on any piece of gear.

    hashtag
    Gear Datablocks: General

    The gear DataBlocks are used to assign behavior, animations, models, and aligns to gear parts, for use in GearJSON. The most simple, and arguably the most important part of these DataBlocks is ‘General’, which tells the game what model and children to load, and what hand animations to use.

    "Model": The path of the part prefab to load

    "Children": A list of child prefabs to load

    "GearCategoryFilter": 0, Unused.

    "LeftHandGripAnim": The animation clip to play for the player’s arms on layer 5

    "RightHandGripAnim": The animation clip to play for the player’s arms on layer 6

    "AssetBundle": 20, The asset bundle to load the prefabs from.

    "BundleShard": 3 The asset shard to load the prefabs from.

    Generally, when copying prefabs into this DataBlock, it’s important to make sure you use the same AssetBundle and BundleShard as the prefab you copied.

    hashtag
    Gear Datablocks: Aligns

    Gear parts are attached to each other using aligns, which are empty Game Objects placed onto gear parts which aligned parts are parented to. In order to change the usage of these aligns, you need to edit, or make a copy of the gear DataBlock entry for the desired part. Let’s look at the aligns of Front_UZI_1:

    "AlignType": 0, The Type of the align, which determines which part attaches to this

    "AlignName": "Receiver_M" The name of the game object which this align attaches parts to. Unfortunately, we can’t add or modify these game objects in this DataBlock, but we can tell the game what parts to place onto these aligns.

    hashtag
    Gear Datablocks: Align Types

    ID
    Align Type
    Description

    hashtag
    Gear Datablocks: FireSequence and ReloadSequence

    To handle animations, the many Gear DataBlocks contain lists of WeaponAnimSequenceItems, which provide timing, behavior, and a string to reference the animation. Let’s look at the Short Shotgun reload sequence:

    "TriggerTime": 0.0, The delay, from the start of the sequence, to play the clip.

    "Type": 5, The type, which determines the behavior of the animation.

    "StringData": "shotgun_reload_1_shell_in" The string of the animation clip.

    Note: This formatting and behavior is consistent between reload and firing sequence.

    hashtag
    Gear Datablocks: Animation Types

    ID
    Animation Type
    Description

    hashtag
    GearPartCustomization: Modifying gear part transforms

    By default, it is possible to use whatever weapon or tool parts you want on any gun, and to choose what aligns those parts snap to. However, it is not possible to adjust the position, scale, or rotation of parts. To get around this limitation, you can use the , which allows you to modify the location, rotation, and scale of parts and get far more mileage out of them. Once the GearPartCustomization plugin is installed, it'll create a new file in your custom folder titled GearPartTransform.json.

    Let’s take a look at the composition of this file.

    Each entry in the Parts list is an object with the following properties:

    Each entry in the Children list is an object with the following properties:

    This might seem daunting - you'll potentially be editing a very large amount of data, but thanks to , this process is heavily simplified and relatively easy.

    When you first boot up the game with , you’ll see something like this.

    For now, press F7 to close the Unity Explorer menu. Pick a level, pick the gear you'd like to customize, and start the game. Once you've loaded into the level and are in control, open the Unity Explorer menu by pressing F7. Go to the Object Explorer window and and select Object Search. Set the scope of the search to UnityObject, the class filter to Gear.GearPartHolder, and click Search.

    In our search results, you’ll find the GearPartHolder objects for everything in your character's current inventory. To continue, click on the GearPartHolder of the gear you want to customize. In this example, let's modify the Hanaway PSB.

    With the GearPartHolder open, you’ll be able to see all of the properties and fields of the GearPartHolder. You can also click Inspect GameObject to view the GameObject itself, where you can move, rotate, and scale the gun to make it easier to view your change while editing - for example, you can move it to the center of the screen so you can see it better. While there are many of fields here, very few of them are useful. Let’s inspect GearPartHolder.FrontPart.

    You can now see the FrontPart’s global position, local position, rotation, and scale, as well as its attached child objects. Don't use the sliders to adjust these values - at the scale of this game, even minute adjustments to the sliders can move parts a tremendous distance.

    Note: To change where the gun is, don't change the global position, change the local position.

    When you change the values for this weapon part, you can see that the weapon part is changed in-game as well. Once you’re happy with how it looks, you can input these values into your entry in the GearPartTransform.json.

    hashtag
    ItemFPSSettings - First person weapon positioning

    To modify the position of weapons in the first person camera, you need to either assign an existing ItemFPSSetting entry (There are plenty of good ones in the base game) or write a custom one. Let’s look at an entry in the :

    hashtag
    Best Practices and Notes

    PersistentIDs: Before you make a new weapon, it's wise to come up with an unused PersistentID and use that for everything associated with your weapon. You can reference the TextDataBlock for ideas on how large PersistentIDs can get, and be sure to search through all existing files to make sure you don't have any collisions.

    External Guides

    If there's something useful for modding but not stored on the wiki, we'll reference it here.

    hashtag
    Geomorph sheetarrow-up-right

    Partly an explanation on how level generation works, mostly a list of all geomorphs and what they look like.

    hashtag

    Explains most things about how weapons work and how to make them - for archival purposes.

    This has been transcribed and updated, as the guide.

    hashtag

    A way to make level layout blocks online instead of working with JSON.

    hashtag

    Mostly focused on how to setup unity for making geomorphs, but works for datamining unity assets and making other things in unity as well.

    Major update soon.

    hashtag

    Stores all datablocks and their type information as well as enums. Can be used to view all changes to datablocks starting from mid-R4.

    VS Code Tips

    Editor features that make working with datablocks easier

    hashtag
    Saving files

    This may seem very basic but it can come up more often than expected. There's 2 quick ways to save files and you should save often.

    • Ctrl + s - save the current file

    • Ctrl + k, s - save all opened files (press ctrl and k together, release both, and press s)

    hashtag
    Opening folders from context menu

    This is a neat function to have, it allows you to easily open any folder from file explorer with VS Code. You can enable this when installing. If you didn't, you can reinstall VS Code without deleting it and select the option (or you can go mess with registry files but I wouldn't recommend it).

    hashtag
    Syntax errors

    If VS Code detects an error in your file, it'll mark that file red.

    It might not be obvious what causes this or what the exact error is, so you can open the problems view to see it by pressing ctrl + shift + m:

    From here, you can click on the problem and you'll be taken straight to it. And if you're lucky, the error message will accurately explain the problem.

    hashtag
    Split editor

    This allows you to see several files at once. To use it, simply drag a file in the top view to the side of the screen.

    hashtag
    Collapse blocks

    You can collapse blocks by clicking the arrow next to them at the left side of the screen. This can be useful to hide unnecessary information or quickly select entire blocks.

    hashtag
    Navigating files

    hashtag
    Go to start/end of block

    Useful when navigating big lists, such as levels in a tier. Pressing ctrl + shift + \ anywhere inside a block will take you to the end of it, and pressing it again while at the end of a block will take you back to the start.

    hashtag
    Breadcrumbs

    Breadcrumbs tell you where you are inside a file in terms of blocks:

    You can click the breadcrumbs to navigate and even find out what block you're in.

    hashtag
    Go to line

    Sometimes it's possible that you know the line you need but scrolling would take some effort. To quickly go to the line you want, press ctrl + g. This will open an input field at the top of the screen. Input the line number you need and press enter.

    hashtag
    Go to file

    When working with datablocks, it's common to open and close a lot of files. The explorer view at the left side of the screen is a good way to see all the files but it can take a bit of effort to get the one you want. A better way is to use the top menu to go to the file you want, similarly to going between lines. Open the menu with ctrl + p and start typing the name of the file you want, then press enter to open the file. This works for any file in the folder you have open and its subfolders.

    hashtag
    Search

    This one might seem obvious but there can be features you're not aware of.

    hashtag
    Searching in selection

    The basic shortcut for search is ctrl + f but afterwards you can press alt + l or manually click the icon to limit the search to selected text.

    For example, if i want to search for tier D in rundowndatablock, i get this:

    But if i want to find tier d in a specific rundown, i could use breadcrumbs to get to the start/end of the block, collapse it, select it and then find in selection instead, showing 2 matches:

    This may seem trivial but imagine you're trying to find a specific chained puzzle use in a certain level and have to go through hundreds of matches instead. Then it ends up saving tons of time.

    hashtag
    Searching across files

    Available either with ctrl + shift + f or with 2nd menu at the left side of the screen, this function allows search/replace to work across all files in the opened folder. You can also search in a subset of files.

    hashtag
    RegEx search

    RegEx is a powerful search & replace tool, not limited to VS Code, and is quite a complex topic. For now let's just say that it allows you to find text based on patterns.

    Let's say I want to find enemy with persistent id 13, but I'm lazy to enter the whole text in the search. Using RegEx, i can search for pattern pers.+13 and find what I want.

    Here "pers" and "13" are taken as literal text to search for, but ".+" is a pattern saying "match any character at least once" (except line breaks), and this ends up matching the rest of the missing text in-between "pers" and "13".

    I recommend you check out guides to RegEx and test online for mistakes and explanations, for example in .

    hashtag
    RegEx replace

    RegEx (as well as search without regex) can be used not only to find, but to replace text, performing massive amounts of editing in no time at all.

    Let's say we want to take ALL the enemy groups in base game and rename them to mark as such.

    • The search pattern is "name": "(.+)". All of these characters are matched literally, except for "(.+)". The ".+" pattern is the same as before, but "()" marks a capturing group. That means we're going to reuse it later.

    • The replace pattern is "name": "OBSOLETE_$1". Here almost everything is literal, except for $1. That means the first capturing group should be inserted here.

    The result:

    Depending on creativity and circumstances, this can be used to great effect. In fact, RegEx was used to generate a big part of this wiki.

    hashtag
    Creating temporary files

    A simple but neat feature, this allows you to create a new file simply by double-clicking next to the list of existing files. You can use this to store a block for editing temporarily, back up certain information, mark notes and so on. VS Code will keep the file even if you close and reopen the app.

    hashtag
    Comments

    Comments are created purely to give additional context/information for the reader. JSON technically does not have comments, but there are workarounds for this.

    One way is to make a new JSON field. The game ignores whatever fields it doesn't know, so it won't break anything.

    But this can get annoying, and there is a way to use comments normally with //. If you do it in a plain JSON file, VS Code will likely complain about it.

    But the game ignores comments so it can be left as-is. However, the red text triggers our OCD and we want it gone. Well, there is a way. JSONC (json with comments) exists, and while mods do not usually use it, we can configure VS Code to take any JSON file as JSONC.

    To do this, open the command menu with ctrl + shift + p and start typing "language". "Change language mode" should pop up. Select it, then select "Configure file association", then type in "jsonc" and press enter.

    Now VS Code will assume JSONC for all JSON files and you won't see it complaining about comments.

    hashtag
    Git

    Git is a powerful versioning tool not limited to VS Code. It is covered in its own guide .

    Enabling MTFO Hot Reload

    Hot reloading can let you test your changes without having to restart your game, it's great!

    hashtag
    Enabling MTFO Hot Reload

    circle-exclamation

    Hot reloading may not work for every datablock. If you make a change and nothing happens, you may need to restart the game instead. Additionally, hot reloading isn't quite the same as restarting your game, and may cause bugs. If in doubt, restart your game.

    Hot reloading is a MTFO feature that allows you to reload datablocks without restarting the game. It can speed up your ability to test your changes quite considerably, and is definitely something you should strongly consider before trying to make your own datablock mods.

    If you're using r2modman to manage your mods, then after creating a profile with MTFO (and launching the modded profile at least once to generate the config files) you can go to Config Editor in the r2modman profile, and then edit MTFO's config file.

    Then simply set EnableHotReload to true and save.

    You can also edit the config file with any text editor as well.

    circle-info

    Don't mind the description stating it only works for a few datablocks, it's outdated.

    Now when you're in the game's level selection menus, a button will appear on the left that will reload your datablocks without having to restart the game.

    Weapon guidearrow-up-right
    Creating Custom Weapons
    Datablock (level layout) editorarrow-up-right
    Unity setuparrow-up-right
    OriginalDataBlocks (TypeList)arrow-up-right
    regex101arrow-up-right
    here
    Open with code in context menu
    Open with code checkboxes during installation
    File with syntax errors
    Problems view
    Split editor view with 2 files open
    A rundown block collapsed
    Breadcrumbs showing the cursor is in CustomGeomorphs
    Breadcrumbs showing that the cursor is in CustomGeomorphs in Complex_Tech block
    Line number menu
    Top menu with enemybalancing file selected
    tierd with 7 matches
    tierd with find in selection
    Searching for "hunter" in the enums folder
    RegEx search pers.+13
    RegEx search & replace for all names
    Group names with OBSOLETE_ prefix added
    New file created by double-clicking
    Comment field in enemy population
    big striker comment
    VS Code saying comments are not allowed in JSON
    Change language mode in command menu
    Configure file association option
    Json with comments selection
    Accessing MTFO's config.
    The EnableHotReload setting in MTFO's config.
    The Reload Game Data button.

    Main

    List of most commonly used datablocks

    The component value. This tells the game which component to load for a given type. In this component, since the type was GearCategory, this will load the GearCategory with persistentID 8.

    5

    AudioSetting

    PersistentID of the WeaponAudio entry to load

    6

    MuzzleFlash

    PersistentID of the WeaponMuzzleFlash entry to load

    7

    ShellCasing

    PersistentID of the WeaponShellCasing entry to load

    12

    FrontPart

    The front, barrel portion of a weapon

    16

    ReceiverPart

    The receiver of a weapon

    19

    StockPart

    The grip or stock of a weapon

    21

    SightPart

    The sight of a weapon; some front parts have this function built in

    23

    MagPart

    The magazine of a weapon. Not all parts support this

    25

    FlashlightPart

    The flashlight of a weapon

    27

    ToolMainPart

    The base part which the rest of the tool parts align to

    30

    ToolGripPart

    The grip or stock of a tool; this is interchangeable with StockPart

    33

    ToolDeliveryPart

    Typically the business end of a tool

    37

    ToolPayloadPart

    Varies widely between tools

    40

    ToolTargetingPart

    The ‘targeting module’ placed on some tools

    42

    ToolScreenPart

    The display screen, only functional if the gear uses the correct BaseItem

    44

    MeleeHeadPart

    The head of a melee weapon

    46

    MeleeNeckPart

    The part that connects the head to the handle of a melee weapon

    48

    MeleeHandlePart

    The handle of a a melee weapon

    50

    MeleePommelPart

    The base of the handle of a melee weapon

    5

    Flashlight

    Corresponds to the FlashlightPart gear component

    6

    SightLook

    The aim camera if no sight part is present

    7

    LeftHand

    The player’s left hand

    8

    RightHand

    The player’s right hand

    9

    Receiver

    Corresponds to the ReceiverPart gear component

    10

    Front

    Corresponds to the FrontPart gear component

    12

    ToolGrip

    Corresponds to the ToolGripPart gear component

    13

    ToolDelivery

    Corresponds to the ToolDeliveryPart gear component

    14

    ToolPayload

    Corresponds to the ToolPayloadPart gear component

    15

    ToolTargeting

    Corresponds to the ToolTargetingPart gear component

    16

    ToolScreen

    Corresponds to the ToolScreenPart gear component

    17

    ToolDetection

    Unknown

    18

    ToolScanning

    Unknown

    20

    MeleeHead

    Corresponds to the MeleeHeadPart gear component

    40

    RotationPivot

    Presumably used by sentry guns to position the contained weapon parts

    41

    GroundPlacement

    Presumably used to position the base of a sentry gun

    4

    ReceiverAnim

    Animate the weapon’s receiver part

    5

    Sound

    Play a sound event using the animation string as a sound event ID

    6

    DoUpdateAmmo

    Refill the weapon’s magazine. (No animation clip input required)

    7

    Empty

    Do nothing. Typically used at the end of a sequence. (No animation clip input required)

    8

    StockAnim

    Animate the weapon’s stock part

    9

    RightHandAnim

    Animate the FPS arms (animation layer 6)

    1

    FireMode

    0-3, determines which FireMode PersistentID to use from the GearCategory

    2

    Category

    PersistentID of the GearCategoryDataBlock to load

    3

    BaseItem

    PersistentID of the ItemDataBlock entry to load.

    4

    ItemFPSSettings

    0

    Muzzle

    Weapon’s muzzle flash

    1

    ShellEject

    Weapon’s ejection port

    2

    Magazine

    Corresponds to the MagPart gear component

    4

    Sight

    Corresponds to the SightPart gear component

    0

    WeaponMovementAnim

    Animate the first person weapon holder

    1

    FrontPartAnim

    Animate the weapon’s front part

    2

    LeftHandAnim

    Animate the FPS arms (animation layer 5)

    3

    LeftHandMagAnim

    PlayerOfflineGearDataBlock
    GearCategoryDataBlock
    GearCategoryDataBlock
    ArchetypeDataBlock
    ItemDataBlock
    ArchetypeDataBlock
    RecoilDataBlock
    ItemDataBlock
    ArchetypeDataBlock
    ArchetypeDataBlock
    GearPartCustomization pluginarrow-up-right
    Unity Explorerarrow-up-right
    Unity Explorerarrow-up-right
    ItemFPSSettingsDataBlock
    An exploded view of a gun, illustrating the various parts used to create it
    The R5-era Rundown screen, with Unity Explorer open
    Searching for GearPartHolder objects
    Inspecting the Hanaway PSB's parts
    Inspecting the Front_Rifle_2 GameObject

    PersistentID of the ItemFPSSettings entry to load.

    Animate the FPS arms using the magazine’s animation. (No animation clip input required)

    "PublicName": //Weapon inventory name, PersistentID or String
    "Description": //Weapon lobby description, PersistentID or String
    "FireMode": //How the weapon shoots:
                //0 - Semiauto (one shot per trigger pull)
                //1 - Burst (multiple sequential shots per trigger pull)
                //2 - Auto (continuous fire as long as trigger is held)
                //3 - SemiBurst (unused but functional, see ArchtypeDataBlock for details)
    "RecoilDataID": //Weapon recoil settings, references a PersistentID in RecoilDatablock
    "DamageBoosterEffect": //Determines what boosters affect this weapon.
                           //See "Effect" field in BoosterImplantEffectDataBlock
    "Damage": //Weapon base damage
    "DamageFalloff": { // see ArchetypeDataBlock for more details
        "x": //Falloff begins
        "y": //Falloff ends
    },
    "StaggerDamageMulti": //Multiplier to get weapon's stagger damage
    "PrecisionDamageMulti": //Multiplier for shots that hit an enemy's weakpoint
    "DefaultClipSize": //Number of shots in a magazine
    "DefaultReloadTime": //Time in seconds to reload
    "CostOfBullet": //Total ammo capacity, see ArchetypeDataBlock for more details
    "ShotDelay": //Time in seconds between each shot
    "PiercingBullets": //Whether this weapon's projectiles pierce though enemies
    "PiercingDamageCountLimit": //See ArchetypeDataBlock for more details 
    "HipFireSpread": //Size of the accuracy cone when hipfiring, not degrees
    "AimSpread": //Size of the accuracy cone when aiming, not degrees
    "EquipTransitionTime": //Time in seconds to equip the weapon
    "EquipSequence": //Animation sequence to play when equipping the weapon
                     //(see later section on AnimationSequences for more details) 
    "AimTransitionTime": //Time in seconds to aim down sights
    "AimSequence": //Animation sequence to play when aiming the weapon
                   //(see later section on AnimationSequences for more details)
    "BurstDelay": //Delay in seconds between bursts
    "BurstShotCount": //Number of shots to fire in a burst
    "ShotgunBulletCount": //Number of pellets to fire if the weapon is a shotgun
    "ShotgunConeSize": //Radius of the shotgun’s cone (Integer)
    "ShotgunBulletSpread": //Spread between each pellet (Integer)
    "SpecialChargetupTime": //Time it takes to charge up before firing this weapon
    "SpecialCooldownTime": //Time it takes to cool down after firing this weapon
    "SpecialSemiBurstCountTimeout": //Unused or broken
    "Sentry_StartFireDelay": //Time before a sentry starts firing
    "Sentry_RotationSpeed": //Sentry rotation speed
    "Sentry_DetectionMaxRange": //Maximum distance a sentry can target enemies at
    "Sentry_DetectionMaxAngle": //Angle of the sentry's sweep in degrees
    "Sentry_FireTowardsTargetInsteadOfForward": //see ArchetypeDataBlock for details
    "Sentry_LongRangeThreshold": //Unused?
    "Sentry_ShortRangeThreshold": //Unused?
    "Sentry_LegacyEnemyDetection": //Use the new or old sentrygun targeting behavior
    "Sentry_FireTagOnly": //Only shoot at biotracker tagged enemies, True/False
    "Sentry_PrioTag": //Prioritize biotracked enemies, True/False
    "Sentry_StartFireDelayTagMulti": //Multipliers when firing at biotracked enemies,
    "Sentry_RotationSpeedTagMulti":  //see ArchetypeDataBlock for more details
    "Sentry_DamageTagMulti":         //...
    "Sentry_StaggerDamageTagMulti":  //...
    "Sentry_CostOfBulletTagMulti":   //...
    "Sentry_ShotDelayTagMulti":      //...
    "name": //The weapon’s internal name in the files, unused
    "internalEnabled": //Is weapon enabled in-game
    "persistentID": //Weapon’s ID for reference in other DataBlocks
    "PublicName": "", //In-game name for other gear, not used by weapons
    "Description": "", //Lobby description for other gear, not used by weapons
    "BaseItem": 108, //PersistentID in ItemDataBlock of this weapon's base item
    "HUDIcon": "", //Unused
    "FPSArmPoseName": "", //Unused
    "ThirdPersonFullbodyMovement": 0, //Animation set to use, see GearCategoryDataBlock
    "SemiArchetype": 1,         //0th archetype in this category
    "BurstArchetype": 3,	    //1st archetype in this category
    "AutoArchetype": 5,	    //2nd archetype in this category
    "SemiBurstArchetype": 16,   //3rd archetype in this category
    /*
    These refer to the PersistentIDs of gun behavior entries in ArchetypeDataBlock.
    You only need the correct PersistentID for the firemode your gun actually uses.
    Weapon firemode is selected in its PlayerOfflineGearDataBlock GearJSON.
    */
    "PartAlignPriority": [], //Determines how parts with conflicting aligns behave.
    "name": "Rifle", //Internal name, unused
    "internalEnabled": true, //Whether or not this category is enabled ingame
    "persistentID": 1 //Category ID for reference in other DataBlocks
    "PartAlignPriority": [
    {
        "AlignType": 7,
        "PartPrio": [
        12
        ]
    },
    {
        "AlignType": 8,
        "PartPrio": [
        12
        ]
    }
    ],
    "GearJSON":
    "{\"Ver\":1,\"Name\":\"Shelling S49\",
    \"Packet\":{\"Comps\":{\"Length\":16,
    \"a\":{\"c\":2,\"v\":8},
    \"b\":{\"c\":3,\"v\":108},
    \"c\":{\"c\":4,\"v\":8},
    \"d\":{\"c\":5,\"v\":1},
    \"e\":{\"c\":6,\"v\":1},
    \"f\":{\"c\":7,\"v\":1},
    \"g\":{\"c\":8,\"v\":16},
    \"h\":{\"c\":9,\"v\":15},
    \"i\":{\"c\":10,\"v\":27},
    \"j\":{\"c\":11,\"v\":27},
    \"k\":{\"c\":12,\"v\":38},
    \"l\":{\"c\":16,\"v\":1001},
    \"m\":{\"c\":19,\"v\":1002},
    \"n\":{\"c\":23,\"v\":8},
    \"o\":{\"c\":25,\"v\":3}},
    \"MatTrans\":{\"tDecalA\":{\"position\":{\"x\":-0.098,\"y\":-0.07},\"scale\":0.05},
    \"tDecalB\":{\"position\":{\"x\":-0.098,\"y\":-0.07},\"scale\":0.04},
    \"tPattern\":{\"position\":{\"x\":-0.09,\"y\":-0.03},\"angle\":-90.0,\"scale\":0.1}},
    \"publicName\":{\"data\":\"Shelling S49\"}}}",
    "General": {
        "Model": "Assets/AssetPrefabs/Items/Gear/Parts/Fronts/Front_Short_Shotgun_2.prefab",
        "Children": [],
        "GearCategoryFilter": 0,
        "LeftHandGripAnim": "Short_Shotgun_2_Player_Idle",
        "RightHandGripAnim": "Short_Shotgun_2_Player_Idle",
        "AssetBundle": 20,
        "BundleShard": 3
    },
    "Aligns": [
        {
            "AlignType": 0,
            "AlignName": "Receiver_M"
        },
        {
            "AlignType": 1,
            "AlignName": "Front_SE"
        },
        {
            "AlignType": 2,
            "AlignName": "Front_Mag"
        },
        {
            "AlignType": 5,
            "AlignName": "Front_Flash"
        },
        {
            "AlignType": 7,
            "AlignName": "LeftHand"
        },
        {
            "AlignType": 6,
            "AlignName": "Sight_Align"
        },
        {
            "AlignType": 4,
            "AlignName": "Receiver_Sight"
        }
    ],
    "ReloadSequence": [
        {
            "TriggerTime": 0.0,
            "Type": 0,
            "StringData": "ShotgunReload_bump"
        },
        {
            "TriggerTime": 0.0,
            "Type": 5,
            "StringData": "carbine_reload_3_foley"
        },
        {
            "TriggerTime": 0.95,
            "Type": 5,
            "StringData": "shotgun_reload_1_shell_in"
        },
        {
            "TriggerTime": 1.0,
            "Type": 6
        },
        {
            "TriggerTime": 1.5,
            "Type": 5,
            "StringData": "shotgun_reload_2_cock"
        },
        {
            "TriggerTime": 2.0,
            "Type": 7
        }
    ],
        "OfflineID": //PersistentID of the PlayerOfflineGear entry to customize
        "Name": //The name of the customization settings. (For organization, no effect)
        "InternalEnabled": //Whether or not to load this customization setting
        "Parts": //The list of parts to customize on this gear item.
        "PartHolderObject": //Property within the GearPartHolder to modify
        "PartType": //Component Type to modify. (Only used if PartHolderObject is unset)
        "Enabled": //Enable or disable this Part’s GameObject (True/False)
        "PartTransform": //Modify Part's position, rotation, and scale
        "Children": /* The list of children on this part to modify.
        Many gear parts contain children for additional models, aligns, animations, etc.
        If you don’t want to customize this Part's children, leave this list empty. */`
        "ChildName": //The name of the child object to modify.
        "Enabled": //Enable or disable this child's GameObject (True/False)
        "PartTransform": //Modify child's position, rotation, and scale.
        "Children": /* Any Children of this object that we want to modify.
        Many parts have nested children multiple levels deep,
        so you need to modify the children of children to access those. */
    "localPosHip": //Position of the weapon while hipfiring
    "localRotHip":	//Angle of the weapon while hipfiring
    "localPosRelaxed": //Position of the weapon while in the idle animation
    "localRotRelaxed": //Rotation of the weapon while in the idle animation
    "localPosZoom": //Position of the weapon when aiming
    "localRotZoom": //Rotation of the weapon when aiming
    "bodyOffsetLocal": //Root position; other positions are offset from this
    "bodyRotationOffsetLocal": //Root rotation; other rotations offset from this
    "ItemCameraFOVDefault": //Default FOV of the Item Camera (renders only weapons/tools)
    "ItemCameraFOVZoom": //Aimed FOV of the Item Camera (renders only weapons/tools)
    "LookCameraFOVZoom": //Aimed FOV of the Player Camera (renders only the world)
    "canAim": //Can this weapon enter the Aiming state, True/False
    "onlyStartAimOnPressed": //Unused
    "canRelax": //Can this weapon can play an idle animation?
    "customDelayUntilRelax": //Time until this weapon plays an idle animation
    "allowRotToAimPos": //Can weapon rotate when moving to the aimed position
    "rotToAimPosMinDis": //Unused
    "transitionToAim": //Speed of aim transition, 0 = quick, 1 = slow
    "idleAnimData": //Animation used when player is stationary (ItemMovementAnimation)
    "walkAnimData": //Animation used when player is walking (ItemMovementAnimation)
    "runAnimData": //Animation used when player is stationary (ItemMovementAnimation)
    "DofDefault": //The depth of field settings (camera blur) for hipfiring
    "DofAim": //The depth of field settings (camera blur) when aiming
    "name": //Internal name of these settings, unused
    "internalEnabled": //Is this group of settings enabled in-game
    "persistentID": //Unique ID of this ItemFPSSettings group

    Datablocks

    A list of every datablock in the game, their fields and if you're lucky, what they do!

    Datablocks are groups of fields that form all the customizable parts of rundowns, weapons, enemies, levels, waves, and more. Everything needed to create a custom rundown can be created utilizing datablocks. This reference will explain all of the fields within each datablock. Check out the guides for more information about how to use them.

    circle-exclamation

    hashtag
    Prerequisites

    To work with datablocks, you should be familiar with JSON.

    hashtag
    Datablocks Storage

    Datablocks and their change history is kept on .

    hashtag
    Common Fields

    All datablocks share 3 main fields, each of them has special meaning.

    hashtag
    persistentID - UInt32

    The ID of the block, used to reference by all other blocks. If you see any other field with type UInt32, chances are it's a reference to some other block (but that type is also used to reference wwise audio IDs).

    Must be unique.

    circle-exclamation

    Although persistentID type is UInt32, the actual value range is often much smaller because it is changed to other types in networking for example. Sticking to a safe range of 1-65535 is recommended, but datablocks with even smaller ranges do exist ( for example). If we notice any blocks with a range smaller than that, we will make a note about it in the relevant reference page.

    hashtag
    internalEnabled - Boolean

    Whether this block is enabled. Disabled blocks are ignored by the game.

    hashtag
    name - String

    The name of the block. This seems to be only for readability and is not used by the game, but it may be used by mods.

    Must be unique.

    hashtag
    Additional Fields

    hashtag
    Headers

    This field is only used by devs in their editor.

    hashtag
    LastPersistentID - UInt32

    The last persistentID found in datablocks. Serves no purpose but can clutter the logs if not set correctly.

    hashtag
    Types

    in all datablocks documentation, you see a specific format of fields: name - type or name - type (special meaning)

    The name is just that, the name of the field. The type is what data should be specified there.

    These are the most basic types:

    • - whole number from 0 to 4,294,967,295

    • - integer from -2,147,483,648 to 2,147,483,647

    • (aka float) - approximate real number of varying precision with values ranging from negative 3.402823e38 to positive 3.402823e38.

    hashtag
    Enumerator/Enum

    are a special type, representing named values. Here's an example ():

    • None - 0

    • Force_One - 1

    • Rel_Value - 2

    The underlying enum type here is Int32, and it has 3 named values. Enums usually have this underlying type, start from 0, and move up in sequence, but there are exceptions. You can check out the page to see all enums.

    In JSON, enums can be specified both as underlying type and as plain text.

    There are special cases where the enum values are combined, e.g. AnimationControllers, type .

    An example value you could see here is "EnemyRunner, EnemyLow, EnemyCrawl", or 84. This combines 3 values and the game processes it in a way that understands the value set as all 3.

    hashtag
    Nested type/Class/Object

    In datablocks reference, nested type refers to a class that's defined by the game. Each nested type has its own page to reduce clutter when the same type is referenced several times.

    In JSON, these are all , starting and ending with curly braces { }.

    Every datablock file defines one object containing several fields, including a list of objects - Blocks.

    hashtag
    List/Array and Dictionary

    All 3 of these never go by themselves, they contain other types (and sometimes can be nested).

    Lists and Arrays always start and end with [ ] symbols. For example, a "List Int32" looks like this: [ 1, 2, 3 ] instead of a plain Int32 value 1. a "List List Int32" follows the same principle: [ [ 1, 2, 3 ], [ 1, 2, 3 ] ]. Arrays look exactly the same as Lists in JSON.

    Dictionaries are a more complex type and are rarely found in datablocks. A dictionary is an object that maps 2 types, the first as key, the 2nd as value. In JSON, dictionaries look the same as nested objects.

    Here you can see a dictionary with 2 keys "Glue" and "Explosive" mapped to objects. In JSON, an object with 2 fields "Glue" and "Explosive" could look exactly the same.

    hashtag
    Empty values

    Sometimes you see fields set to seemingly invalid values such as an empty string or -1, or just not there at all. In these cases you can think of the fields as unset, which means the game provides some default value or behaviour for it.

    hashtag
    Additional notes

    hashtag
    Vector

    In datablocks, Vectors are messed up right now and generate with some fields that don't actually do anything:

    You can ignore or delete these.

    hashtag
    Time fields

    Fields related to time/length/duration are specified in seconds unless stated otherwise.

    ChainedPuzzle

    GameData_ChainedPuzzleDataBlock_bin.json (filled)

    Defines Chained Puzzle settings (e.g. Security Door alarm).

    hashtag
    Fields

    hashtag
    PublicAlarmName - String

    The Alarm name. For example, Class S Surge Alarm

    hashtag
    TriggerAlarmOnActivate - Boolean

    Whether to trigger alarm when the puzzle starts. Typically set to false for scans without an alarm and enemy wave.

    However, you can set this field to true even if you don't specify the enemy wave for the puzzle via the following fields. In that case, there will still be alarm sound but no enemy waves.

    hashtag
    SurvivalWaveSettings - UInt32 ()

    Determine how the wave spawns. You set this field to make the wave either a relatively regular, surge, diminished, or ://ERROR! alarm wave.

    You may take those wave settings already available in the vanilla datablocks into good use.

    hashtag
    SurvivalWavePopulation - UInt32 ()

    Determine what type(s) of enemy would spawn.

    hashtag
    SurvivalWaveAreaDistance - Int32

    How many areas away from players should enemies spawn, with 2 being the default value if left unset.

    Used in R7 to prevent enemy waves spawning too far away from the scan zone.

    hashtag
    DisableSurvivalWaveOnComplete - Boolean

    Specify whether to stop the wave after Chained Puzzle Completion. Typically set to false for ://ERROR! alarm.

    hashtag
    UseRandomPositions - Boolean

    Whether to use random position for each scan. Usually set to true.

    By setting this field to false, the scan position for each puzzle would be relatively static, i.e. it's not static all the time.

    hashtag
    WantedDistanceFromStartPos - Single

    As explained by the field name :)

    hashtag
    WantedDistanceBetweenPuzzleComponents - Single

    Also as explained by the field name :)

    hashtag
    ChainedPuzzle - (nested type)

    Determines the count and types of scans.

    hashtag
    OnlyShowHUDWhenPlayerIsClose - Boolean

    If set to true, the HUD won't show up if you are a certain distance (seems to be 25m) away from the scan.

    Typically set to false for regular scan, and true for extraction scan.

    hashtag
    AlarmSoundStart - UInt32

    Alarm sound when the puzzle starts. Changing the sound properly may give the scan a different impression.

    Usually this sound starts the alarm sound loop.

    Referenced to SoundID.

    hashtag
    AlarmSoundStop - UInt32

    Alarm sound when the puzzle stop. Could use this field to set the ambient ERROR alarm sound.

    Usually this sound stops the alarm sound loop. If not set correctly, the alarm sound can go on forever.

    Referenced to SoundID.

    Archetype

    GameData_ArchetypeDataBlock_bin.json (filled)

    Defines weapon stats and metadata, including sentries.

    This datablock is not referenced directly, but rather selected from PlayerOfflineGearDataBlock component firemode paired with specified component gear category from GearCategoryDataBlock. Sentry archetypes are hardcoded.

    hashtag
    Fields

    hashtag
    PublicName - (nested type)

    Weapons technically have 2 names. This is the one used as a more generic name, e.g. "Assault Rifle".

    The other name is specified in GearJSON in .

    hashtag
    Description - (nested type)

    Weapon description displayed in lobby.

    hashtag
    FireMode - (enum)

    Firing mode of this weapon. Can affect which other fields are used.

    SemiBurst is an unused but functional firemode. It's basically a semi auto where you can fire x shots before triggering a cooldown, unless your delay between any 2 shots is big enough for it to reset.

    hashtag
    RecoilDataID - UInt32 ()

    Recoil data ID of this weapon.

    hashtag
    DamageBoosterEffect - (enum)

    Which booster types should affect this weapon.

    Seems functional but currently unused.

    hashtag
    Damage - Single

    Base damage of this weapon.

    hashtag
    DamageFalloff - Vector2

    Linear damage falloff for this weapon.

    X determines where it starts, Y determines where it ends.

    Anywhere in-between X and Y the damage falls off linearly via a multiplier to 0, but there's a lowest value for the multiplier.

    Lowest value for the multiplier is currently 0.1.

    hashtag
    StaggerDamageMulti - Single

    Stagger damage multiplier for base damage.

    hashtag
    PrecisionDamageMulti - Single

    Precision damage multiplier for base damage. This multiplier is only applied when a weakspot is hit (back damage doesn't count).

    hashtag
    DefaultClipSize - Int32

    Default mag size.

    can affect this.

    hashtag
    DefaultReloadTime - Single

    Time in seconds for the reload animation to complete. Note that reload can be completed before the animation is done.

    can affect this.

    hashtag
    CostOfBullet - Single

    Used together with Ammo values to several weapon ammo values. For example for a weapon with a cost of 10 and these (currently game default) ammo values:

    We will have:

    • 30 initial (mag included) ammo when starting a level.

    • OnDropin seems unused.

    • 46 max reserve ammo.

    Note that for sentries there's another multiplier in called ClassAmmoCostFactor.

    hashtag
    ShotDelay - Single

    Time in seconds between shots.

    Sentries don't immediately detect that an enemy died so they're more likely to waste ammo on dead enemies with low delay.

    hashtag
    ShellCasingSize - Single

    Shell casing size multiplier.

    hashtag
    ShellCasingSpeedRange - Vector2

    Shell casing ejection speed range.

    hashtag
    PiercingBullets - Boolean

    Whether this weapon can pierce.

    Pierce is currently broken for the Shotgun sentries. It functions as intended for others.

    hashtag
    PiercingDamageCountLimit - Int32

    How many enemies can a piercing bullet hit. 1 means it will not pierce.

    5 is technically max, although in a roundabout way - for piercing weapons, a loop is performed a maximum of 5 times before exiting. Each collider hit consumes one iteration. It can often happen that the same enemy is hit several times (although damage is applied only once), making high pierce give diminishing returns. In practice, even with 4-5 pierce you'll most likely only hit up to 3 enemies.

    hashtag
    HipFireSpread - Single

    Hipfire random spread.

    Spread is hard to judge, but a weapon with 1 spread is fairly accurate even at mid-long range (~15m).

    Behind the scenes this is just a multiplier for a random point inside a unit circle.

    hashtag
    AimSpread - Single

    ADS random spread.

    hashtag
    EquipTransitionTime - Single

    How long equip animation takes. Also affects when it can be fired after selecting.

    hashtag
    EquipSequence - (nested type)

    Animation sequence to play when equipping a weapon.

    hashtag
    AimTransitionTime - Single

    How long ADS animation takes.

    hashtag
    AimSequence - (nested type)

    Animation sequence to play when aiming with a weapon.

    hashtag
    BurstDelay - Single

    For burst weapons, delay between separate bursts.

    hashtag
    BurstShotCount - Int32

    For burst weapons, how many shots a single burst fires.

    hashtag
    ShotgunBulletCount - Int32

    For shotguns, pellet count in a shot.

    hashtag
    ShotgunConeSize - Int32

    For shotguns, the cone size. Note that this value is Int32, only accepting whole numbers.

    Cone size affects pellet spread, but it is not random. It fires one pellet in the middle and the rest in a circle around the middle based on a sin/cos function.

    hashtag
    ShotgunBulletSpread - Int32

    Shotgun random pellet spread. Also a whole number.

    This doesn't scale well with cone size and can result in shots going way further from the middle than expected.

    hashtag
    SpecialChargetupTime - Single

    How long it takes for the weapon to charge before firing.

    hashtag
    SpecialCooldownTime - Single

    Delay before a weapon can charge up again when it stops firing.

    Currently broken for auto weapons.

    hashtag
    SpecialSemiBurstCountTimeout - Single

    Time for semiburst weapon shot count to reset.

    hashtag
    Sentry_StartFireDelay - Single

    Delay before a sentry starts firing when detecting an enemy.

    hashtag
    Sentry_RotationSpeed - Single

    Sentry rotation speed.

    hashtag
    Sentry_DetectionMaxRange - Single

    Sentry detection max range.

    Currently broken (sort of) - the noise range the sentry causes around itself directly depends on this value.

    hashtag
    Sentry_DetectionMaxAngle - Single

    Max angle to either side at which a sentry can detect enemies.

    Note that sentries can only cover 180 degrees (value 90) total as they physically cannot turn around.

    hashtag
    Sentry_FireTowardsTargetInsteadOfForward - Boolean

    By default sentries shoot where their barrel is aiming, which can cause them to miss when they shouldn't.

    Setting this to true will make them basically an aimbot, always shooting towards the target.

    Unfortunately, the target position is also currently broken on some enemies and so they can miss even as aimbot.

    hashtag
    Sentry_LongRangeThreshold - Single

    Distance for long range boosters.

    hashtag
    Sentry_ShortRangeThreshold - Single

    Distance for short range boosters.

    hashtag
    Sentry_LegacyEnemyDetection - Boolean

    Seems to determine how sentries should target enemies.

    Practical difference is unknown.

    hashtag
    Sentry_FireTagOnly - Boolean

    Should sentry only target biotracker-tagged enemies.

    hashtag
    Sentry_PrioTag - Boolean

    Should sentry prioritize targeting biotracker-tagged enemies.

    hashtag
    Sentry_StartFireDelayTagMulti - Single

    Start fire delay multiplier when targeting biotracker-tagged enemies.

    hashtag
    Sentry_RotationSpeedTagMulti - Single

    Rotation speed multiplier when targeting biotracker-tagged enemies.

    hashtag
    Sentry_DamageTagMulti - Single

    Damage multiplier when targeting biotracker-tagged enemies.

    hashtag
    Sentry_StaggerDamageTagMulti - Single

    Stagger damage multiplier when targeting biotracker-tagged enemies.

    hashtag
    Sentry_CostOfBulletTagMulti - Single

    CostOfBullet multiplier when targeting biotracker-tagged enemies.

    hashtag
    Sentry_ShotDelayTagMulti - Single

    Shot delay multiplier when targeting biotracker-tagged enemies.

    hashtag
    name - String

    Internal name string for this DataBlock entry.

    Not used in-game.

    BigPickupDistribution

    GameData_BigPickupDistributionDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    SpawnsPerZone - Int32

    No description provided.

    hashtag
    SpawnData - (nested type)

    No description provided.

    ConsumableDistribution

    GameData_ConsumableDistributionDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    SpawnsPerZone - Int32

    No description provided.

    hashtag
    ChanceToSpawnInResourceContainer - Single

    No description provided.

    hashtag
    SpawnData - (nested type)

    No description provided.

    Dimension

    GameData_DimensionDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    EnemyBehavior

    GameData_EnemyBehaviorDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    EnemyMovement

    GameData_EnemyMovementDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    EnemyBalancing

    GameData_EnemyBalancingDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    ComplexResourceSet

    GameData_ComplexResourceSetDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    Enemy

    GameData_EnemyDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    DimensionData - DimensionData (nested type)

    No description provided.

    MeleeAttackDistance - MinMaxValue (nested type)

    No description provided.

    hashtag
    RangedAttackDistance - MinMaxValue (nested type)

    No description provided.

    hashtag
    StrafeDistance - MinMaxValue (nested type)

    No description provided.

    hashtag
    HowOftenToStrafe - MinMaxValue (nested type)

    No description provided.

    hashtag
    DistanceToStrafeWithoutLOS - MinMaxValue (nested type)

    No description provided.

    hashtag
    DistanceToStrafeInTargetsLOS - MinMaxValue (nested type)

    No description provided.

    hashtag
    DistanceToStrafeWithoutTargetsLOS - MinMaxValue (nested type)

    No description provided.

    hashtag
    MoveCloserDelayAfterAttack - MinMaxValue (nested type)

    No description provided.

    hashtag
    MoveTowardsTargetDuration - MinMaxValue (nested type)

    No description provided.

    hashtag
    ClosestTargetDistance - MinMaxValue (nested type)

    No description provided.

    hashtag
    StartWalkDuration - MinMaxValue (nested type)

    No description provided.

    hashtag
    StartWalkTimeoutUntilNext - MinMaxValue (nested type)

    No description provided.

    hashtag
    ScreamStateDelay - MinMaxValue (nested type)

    No description provided.

    hashtag
    RushTargetDistance - Single

    No description provided.

    hashtag
    ChanceToPropagateOnDetection - Single

    No description provided.

    hashtag
    ChanceToPropagateOnDeath - Single

    No description provided.

    hashtag
    ChanceToPropagateToMastermind - Single

    No description provided.

    hashtag
    PropagationDistance - Single

    No description provided.

    hashtag
    DisableTargetPreferenceWeight - Boolean

    No description provided.

    hashtag
    IgnoreBotsTargeting - Boolean

    No description provided.

    hashtag
    IsFlyer - Boolean

    No description provided.

    hashtag
    Flyer_HibernateRemap - AgentMode (enum)

    No description provided.

    hashtag
    Flyer_PathingNodeMargin - Int32

    No description provided.

    hashtag
    PathingTargetOffsetY - MinMaxValue (nested type)

    No description provided.

    hashtag
    PathingTargetDistance - MinMaxValue (nested type)

    No description provided.

    hashtag
    StrafeVerticalDistance - MinMaxValue (nested type)

    No description provided.

    hashtag
    Flyer_Acceleration - Single

    No description provided.

    hashtag
    Flyer_Deceleration - Single

    No description provided.

    hashtag
    Flyer_SpeedMultipler - Single

    No description provided.

    hashtag
    Flyer_AttackChargeDuration - MinMaxValue (nested type)

    No description provided.

    hashtag
    Flyer_AttackDuration - MinMaxValue (nested type)

    No description provided.

    hashtag
    Flyer_BackToMovementAfterAttack - MinMaxValue (nested type)

    No description provided.

    hashtag
    Flyer_LightDamageForce - Single

    No description provided.

    hashtag
    Flyer_HeavyDamageForce - Single

    No description provided.

    hashtag
    Flyer_RecoilForce - MinMaxValue (nested type)

    No description provided.

    hashtag
    Flyer_RecoilTorque - MinMaxValue (nested type)

    No description provided.

    hashtag
    Flyer_RollThreshold - Single

    No description provided.

    hashtag
    Flyer_YawThreshold - Single

    No description provided.

    hashtag
    Flyer_PitchThreshold - Single

    No description provided.

    hashtag
    Flyer_DeathDealy - MinMaxValue (nested type)

    No description provided.

    hashtag
    Flyer_BossSpawnWaveID - UInt32 (SurvivalWavePopulationDataBlock)

    No description provided.

    hashtag
    Flyer_BossEnemyID - UInt32 (EnemyDataBlock)

    No description provided.

    hashtag
    Flyer_SpawnOutOfBossStateDuration - MinMaxValue (nested type)

    No description provided.

    hashtag
    Flyer_EstimatedDistanceFromBoss - MinMaxValue (nested type)

    No description provided.

    ForceDisableAnimator - Boolean

    No description provided.

    hashtag
    AnimationControllers - AnimatorControllerHandleName (enum)

    No description provided.

    hashtag
    MoveSlowerWhenInPlayerRoom - Boolean

    No description provided.

    hashtag
    MoveSlowerWithinTargetDistance - Single

    No description provided.

    hashtag
    GlobalAnimSpeedMulti - Single

    No description provided.

    hashtag
    PathMoveAnimSpeedMulti - Single

    No description provided.

    hashtag
    RotationLerp - Single

    No description provided.

    hashtag
    RotationLerpWhenNotMoving - Single

    No description provided.

    hashtag
    BlendIntoAttackAnim - Single

    No description provided.

    hashtag
    BlendIntoScreamAnim - Single

    No description provided.

    hashtag
    AllowMovmentBlendOutOfPathMove - Boolean

    No description provided.

    hashtag
    PathMoveAnimDampTime - Single

    No description provided.

    hashtag
    AllowClimbDownLadders - Boolean

    No description provided.

    hashtag
    LocomotionPathMove - ES_StateEnum (enum)

    No description provided.

    hashtag
    LocomotionHitReact - ES_StateEnum (enum)

    No description provided.

    hashtag
    LocomotionDead - ES_StateEnum (enum)

    No description provided.

    hashtag
    LocomotionShooterAttack - ES_StateEnum (enum)

    No description provided.

    hashtag
    LocomotionScream - ES_StateEnum (enum)

    No description provided.

    Health - HealthData (nested type)

    No description provided.

    hashtag
    GlueTolerance - Single

    No description provided.

    hashtag
    GlueFadeOutTime - Single

    No description provided.

    hashtag
    CanBePushed - Boolean

    No description provided.

    hashtag
    ForbidTwitchHit - Boolean

    No description provided.

    hashtag
    AllowDamgeBonusFromBehind - Boolean

    No description provided.

    hashtag
    UseTentacleTunnelCheck - Boolean

    No description provided.

    hashtag
    UseVisibilityRaycastDuringTentacleAttack - Boolean

    No description provided.

    hashtag
    TentacleAttackDamageRadiusIfNoTunnelCheck - Single

    No description provided.

    hashtag
    TentacleAttackDamage - Single

    No description provided.

    hashtag
    MeleeAttackDamage - Single

    No description provided.

    hashtag
    MeleeAttackDamageCheckRadius - Single

    No description provided.

    hashtag
    TagTime - Single

    No description provided.

    hashtag
    EnemyCollisionRadius - Single

    No description provided.

    hashtag
    EnemyCollisionPlayerMovementReduction - Single

    No description provided.

    hashtag
    EnemyCollisionMinimumMoveSpeedModifier - Single

    No description provided.

    ComplexType - Complex (enum)

    No description provided.

    hashtag
    PrimareSubComplexUsed - SubComplex (enum)

    No description provided.

    hashtag
    BundleName - AssetBundleName (enum)

    No description provided.

    hashtag
    LevelGenConfig - LevelGenConfig (nested type)

    No description provided.

    hashtag
    GeomorphTiles_1x1 - List ResourceData (nested type)

    No description provided.

    hashtag
    GeomorphTiles_2x1 - List ResourceData (nested type)

    No description provided.

    hashtag
    GeomorphTiles_2x2 - List ResourceData (nested type)

    No description provided.

    hashtag
    RandomizeGeomorphOrder - Boolean

    No description provided.

    hashtag
    SmallWeakGates - List ResourceData (nested type)

    No description provided.

    hashtag
    SmallSecurityGates - List ResourceData (nested type)

    No description provided.

    hashtag
    SmallApexGates - List ResourceData (nested type)

    No description provided.

    hashtag
    SmallBulkheadGates - List ResourceData (nested type)

    No description provided.

    hashtag
    SmallMainPathBulkheadGates - List ResourceData (nested type)

    No description provided.

    hashtag
    SmallWallCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    SmallDestroyedCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    SmallWallAndDestroyedCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    MediumWeakGates - List ResourceData (nested type)

    No description provided.

    hashtag
    MediumSecurityGates - List ResourceData (nested type)

    No description provided.

    hashtag
    MediumApexGates - List ResourceData (nested type)

    No description provided.

    hashtag
    MediumBulkheadGates - List ResourceData (nested type)

    No description provided.

    hashtag
    MediumMainPathBulkheadGates - List ResourceData (nested type)

    No description provided.

    hashtag
    MediumWallCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    MediumDestroyedCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    MediumWallAndDestroyedCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    LargeWeakGates - List ResourceData (nested type)

    No description provided.

    hashtag
    LargeSecurityGates - List ResourceData (nested type)

    No description provided.

    hashtag
    LargeApexGates - List ResourceData (nested type)

    No description provided.

    hashtag
    LargeBulkheadGates - List ResourceData (nested type)

    No description provided.

    hashtag
    LargeMainPathBulkheadGates - List ResourceData (nested type)

    No description provided.

    hashtag
    LargeWallCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    LargeDestroyedCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    LargeWallAndDestroyedCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    StraightPlugsNoGates - List ResourceData (nested type)

    No description provided.

    hashtag
    StraightPlugsWithGates - List ResourceData (nested type)

    No description provided.

    hashtag
    SingleDropPlugsNoGates - List ResourceData (nested type)

    No description provided.

    hashtag
    SingleDropPlugsWithGates - List ResourceData (nested type)

    No description provided.

    hashtag
    DoubleDropPlugsNoGates - List ResourceData (nested type)

    No description provided.

    hashtag
    DoubleDropPlugsWithGates - List ResourceData (nested type)

    No description provided.

    hashtag
    PlugCaps - List ResourceData (nested type)

    No description provided.

    hashtag
    ElevatorShafts_1x1 - List ResourceData (nested type)

    No description provided.

    hashtag
    CustomGeomorphs_Exit_1x1 - List ResourceData (nested type)

    No description provided.

    hashtag
    CustomGeomorphs_Objective_1x1 - List ResourceData (nested type)

    No description provided.

    hashtag
    CustomGeomorphs_Challenge_1x1 - List ResourceData (nested type)

    No description provided.

    hashtag
    Ladders_4m - List ResourceData (nested type)

    No description provided.

    hashtag
    Ladders_2m - List ResourceData (nested type)

    No description provided.

    hashtag
    Ladders_1m - List ResourceData (nested type)

    No description provided.

    hashtag
    Ladders_05m - List ResourceData (nested type)

    No description provided.

    hashtag
    Ladders_Bottom - List ResourceData (nested type)

    No description provided.

    hashtag
    Ladders_Top - List ResourceData (nested type)

    No description provided.

    EnemyType - eEnemyType (enum)

    No description provided.

    hashtag
    AssetBundle - AssetBundleName (enum)

    No description provided.

    hashtag
    BundleShard - AssetBundleShard (enum)

    No description provided.

    hashtag
    BasePrefabs - List String

    No description provided.

    hashtag
    ModelDatas - List ModelData (nested type)

    No description provided.

    hashtag
    DetectionDataId - UInt32 (EnemyDetectionDataBlock)

    No description provided.

    hashtag
    BehaviorDataId - UInt32 (EnemyBehaviorDataBlock)

    No description provided.

    hashtag
    MovementDataId - UInt32 (EnemyMovementDataBlock)

    No description provided.

    hashtag
    BalancingDataId - UInt32 (EnemyBalancingDataBlock)

    No description provided.

    hashtag
    SFXDataId - UInt32 (EnemySFXDataBlock)

    No description provided.

    hashtag
    ArenaDimensions - List UInt32 (DimensionDataBlock)

    No description provided.

    hashtag
    LinkedSlaveModels - List LinkedSlaveModelData (nested type)

    No description provided.

    hashtag
    InternalMaterial - MaterialType (enum)

    No description provided.

    hashtag
    isCoccoon - Boolean

    No description provided.

    hashtag
    EnemySpottedDialogId - UInt32 (PlayerDialogDataBlock)

    No description provided.

    hashtag
    AI_Abilities - List AbilityData (nested type)

    No description provided.

    SurvivalWaveSettingsDataBlock
    SurvivalWavePopulationDataBlock
    List ChainedPuzzleComponent
    List BigPickupSpawnData
    List ConsumableSpawnData

    Booleanarrow-up-right - data type with 2 values - "true" and "false".

  • Stringarrow-up-right - plain text.

  • GitHubarrow-up-right
    SurvivalWaveSettings
    UInt32arrow-up-right
    Int32arrow-up-right
    Singlearrow-up-right
    Enumsarrow-up-right
    eEnemyZoneDistribution
    enum types
    EnemyMovementDataBlockarrow-up-right
    AnimatorControllerHandleName
    objectsarrow-up-right
    Example dictionary
    Vectors fields that aren't supposed to be there

    EnemyDetection

    GameData_EnemyDetectionDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    weaponDetectionDistanceMin - Single

    No description provided.

    hashtag
    weaponDetectionDistanceMax - Single

    No description provided.

    hashtag
    detectionNodeDistanceMax - Single

    No description provided.

    hashtag
    movementDetectionDistance - Single

    No description provided.

    hashtag
    detectionBuildupSpeed - Single

    No description provided.

    hashtag
    detectionCooldownSpeed - Single

    No description provided.

    EnemySFX

    GameData_EnemySFXDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    SFX_ID_walk - UInt32

    No description provided.

    hashtag
    SFX_ID_run - UInt32

    No description provided.

    hashtag
    SFX_ID_climbLadder - UInt32

    No description provided.

    hashtag
    SFX_ID_heartbeatPulse - UInt32

    No description provided.

    hashtag
    SFX_ID_hibernateIdle - UInt32

    No description provided.

    hashtag
    hibernateIdleInterval - Vector2

    No description provided.

    hashtag
    SFX_ID_hibernateWakeUp - UInt32

    No description provided.

    hashtag
    SFX_ID_hibernateDie - UInt32

    No description provided.

    hashtag
    SFX_ID_hibernateDetectionStart - UInt32

    No description provided.

    hashtag
    SFX_ID_scream - UInt32

    No description provided.

    hashtag
    SFX_ID_stuckInGlue - UInt32

    No description provided.

    hashtag
    SFX_ID_releaseFromGlue - UInt32

    No description provided.

    hashtag
    SFX_ID_attackWindUp - UInt32

    No description provided.

    hashtag
    SFX_ID_attackWindUp_NotLocalTarget - UInt32

    No description provided.

    hashtag
    SFX_ID_attackFire - UInt32

    No description provided.

    hashtag
    SFX_ID_hurtSmall - UInt32

    No description provided.

    hashtag
    SFX_ID_hurtBig - UInt32

    No description provided.

    hashtag
    SFX_ID_die - UInt32

    No description provided.

    hashtag
    SFX_ID_JumpStart - UInt32

    No description provided.

    hashtag
    SFX_ID_JumpInAir - UInt32

    No description provided.

    hashtag
    SFX_ID_JumpLand - UInt32

    No description provided.

    hashtag
    SFX_ID_BigTentacleStart - UInt32

    No description provided.

    hashtag
    SFX_ID_BigTentacleTipLoop - UInt32

    No description provided.

    hashtag
    SFX_ID_BigTentacleEnd - UInt32

    No description provided.

    450 * 0.2 / 10 = 9 bullets per refill (0.2 comes from the fact that you use 0.2 of a refill at any given time (e.g. 4 uses of a refill is 0.8)
    LocalizedText
    PlayerOfflineGearDataBlock
    LocalizedText
    eWeaponFireMode
    RecoilDataBlock
    AgentModifier
    GearMagPartDataBlock
    GearMagPartDataBlock
    PlayerDataBlock
    ItemDataBlock
    List WeaponAnimSequenceItem
    List WeaponAnimSequenceItem
      "AmmoStandardInitial": 300,
      "AmmoStandardInitialOnDropin": 200,
      "AmmoStandardMaxCap": 460,
      "AmmoStandardResourcePackMaxCap": 450,

    EnemyGroup

    GameData_EnemyGroupDataBlock_bin.json (filled)

    This datablock is used for setting enemy spawns with a focus on randomization.

    circle-info

    Spawning enemies is explained in EnemySpawningData.

    circle-exclamation

    EnemyGroup blocks 37 and 38 are used by birther and birther boss respectively. This can only be changed with mods.

    hashtag
    Fields

    hashtag
    Type - (enum)

    Type match of this group.

    There are special types, explained in .

    hashtag
    Difficulty - (enum)

    Difficulty match of this group.

    hashtag
    SpawnPlacementType - (enum)

    Defines where enemies are placed in the selected area.

    hashtag
    MaxScore - Single

    The score (or population points/cost) of this group.

    hashtag
    ScoreInAreaPaddingMulti - Single

    Multiplier for MaxScore when adding to total placed score in area.

    The higher the area's score, the less likely it is to be picked for another enemy group.

    hashtag
    RelativeWeight - Single

    Relative weight of this group. Affects how likely it is to be selected when several are matched.

    hashtag
    Roles - (nested type)

    List of roles in this group. Each role will spawn one type of enemy when this group is selected.

    EnemyPopulation

    GameData_EnemyPopulationDataBlock_bin.json (filled)

    This datablock is used to select enemies by EnemyGroupDataBlock through filters.

    While technically you can have several population blocks, usually only the first block is used both in-game and by modders.

    circle-info

    Spawning enemies is explained in EnemySpawningData.

    hashtag
    Fields

    hashtag
    RoleDatas - (nested type)

    List of enemy role entries.

    ExpeditionBalance

    GameData_ExpeditionBalanceDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    HealthPerZone - Single

    No description provided.

    hashtag
    DisinfectionPerZone - Single

    No description provided.

    hashtag
    WeaponAmmoPerZone - Single

    No description provided.

    hashtag
    ToolAmmoPerZone - Single

    No description provided.

    hashtag
    CommodityValuePerZone - Single

    No description provided.

    hashtag
    ChanceToPutCommodityInResourceContainer - Single

    No description provided.

    hashtag
    ChanceToPutArtifactInResourceContainer - Single

    No description provided.

    hashtag
    ChanceToSpawnCommodityLargePack - Single

    No description provided.

    hashtag
    ChanceToSpawnCommodityMediumPack - Single

    No description provided.

    hashtag
    ChanceToReUseResourceContainer - Single

    No description provided.

    hashtag
    MaxPacksPerResourceContainer - Int32

    No description provided.

    hashtag
    EmptyWeakResourceContainersPerZone - Single

    No description provided.

    hashtag
    EmptySecureResourceContainersPerZone - Single

    No description provided.

    hashtag
    LootPerZone - Single

    No description provided.

    hashtag
    AirPerZone - Single

    No description provided.

    hashtag
    AirPerZoneInNoAir - Single

    No description provided.

    hashtag
    TerminalsPerZone - Single

    No description provided.

    hashtag
    TentacleTraps - (nested type)

    No description provided.

    hashtag
    ParasiteNests - (nested type)

    No description provided.

    hashtag
    EnemyPatrolGroupsPerZone - Int32

    No description provided.

    hashtag
    StaticEnemiesMaxPerZone - Int32

    No description provided.

    hashtag
    StaticEnemiesMaxSmallArea - Int32

    No description provided.

    hashtag
    StaticEnemiesMaxMediumArea - Int32

    No description provided.

    hashtag
    StaticEnemiesMaxLargeArea - Int32

    No description provided.

    hashtag
    StaticEnemiesMaxHugeArea - Int32

    No description provided.

    hashtag
    EnemyPopulationPerZone - Single

    No description provided.

    hashtag
    VoxelCoverageAreaMultiplier - Single

    No description provided.

    hashtag
    VoxelCoverageAreaScoringRandomMultiplier - Single

    No description provided.

    hashtag
    ArtifactsPerSegment - Int32

    No description provided.

    hashtag
    ArtifactsPerLayer - Int32

    No description provided.

    hashtag
    WeakDoor4x4Health - Single

    No description provided.

    hashtag
    WeakDoor8x4Health - Single

    No description provided.

    hashtag
    WeakDoorChanceLockWeightNoLock - Single

    No description provided.

    hashtag
    WeakDoorChanceLockWeightMeleeLock - Single

    No description provided.

    hashtag
    WeakDoorChanceLockWeightHackableLock - Single

    No description provided.

    hashtag
    WeakDoorUnlockedChanceForOpen - Single

    No description provided.

    hashtag
    WeakDoorOpenChanceForWallRemoverUsed - Single

    No description provided.

    hashtag
    WeakDoorLockHealth - Single

    No description provided.

    hashtag
    WeakResourceContainerWithPackChanceForLocked - Single

    No description provided.

    hashtag
    ResourcePackSizes - List Single

    No description provided.

    hashtag
    GlueVolumeToDoorHealthConversion - Single

    No description provided.

    hashtag
    GlueVolumeForDoorGlueMaxState - Single

    No description provided.

    FogSettings

    GameData_FogSettingsDataBlock_bin.json (filled)

    This datablock edits fog settings, which include fog's visual effects (color, opacity, etc.), height, and controls if the fog is flipped (inversed fog, like the one in R5E1), infectious, etc.

    As one of the most important features of the game, fog serves to occlude player's sight, limit zones' reachability and make decisions on whether to 'toss a Fog Repeller and combat amid' or to 'flee'. Also, colored fog (for example, Green Fog in R7C2, etc.) would affect lighting of the entire level, making your level able to give players impressions of tension, horror, anxiety, sound, and so on.

    hashtag
    Fields

    hashtag
    Enabled - Boolean

    Unused.

    hashtag
    FogColor - Color

    Determine the color of the fog. This can affect the lighting of the entire level and create some preferable visual effect.

    It seems that starting in Rundown 7, the way fog occludes sight and interacts with lights has changed. Colored fog may not block sight well, so it's best to use white fog for that purpose.

    For example, here's extremely dense red fog:

    hashtag
    FogDensity - Single

    The base fog density in the entire level.

    To create inversed fog (e.g. R5E1), you have to set FogDensity and DensityHeightMaxBoost such that FogDensity < DensityHeightMaxBoost

    hashtag
    FogAmbience - Single

    Unused.

    hashtag
    DensityNoiseDirection - Vector3

    Noise are those floating particles right above the fog plane. These particles make the fog plane resemble a tide.

    This field controls the floating direction of those particles / tide pattern of the fog plane.

    hashtag
    DensityNoiseSpeed - Single

    Controls how fast noise particles float / how uneven the tide pattern of the fog plane is.

    hashtag
    DensityNoiseScale - Single

    Seems to be the size of the noise particles. Higher values can make them look visibly separated, kind of like dust clouds.

    hashtag
    DensityHeightAltitude - Single

    The lowest point for the fog height. For non-inversed fog, everything with altitude lower than this value would be fully submerged by the fog.

    As a reference for zone altitude: Low : -4.0, Mid : 0.0, High: 4.0

    hashtag
    DensityHeightRange - Single

    Distance above lowest point for fog height, used in calculating the highest point for fog height.

    hashtag
    DensityHeightMaxBoost - Single

    This is the actual field for controlling the density of (non-inversed) fog. The larger, the more occluding.

    hashtag
    Infection - Single

    The maximum value for how fast infection accumulates from fog. For example, 0.1 would take you 10 seconds to get fully infected. 0.03 is a common, average value to set to.

    Note that how much infection you get depends on how deep in the fog you are with linear scaling, where the highest point of infection (and lowest actual infection gain rate) is at DensityHeightAltitude + DensityHeightRange and lowest point is DensityHeightAltitude

    FlashlightSettings

    GameData_FlashlightSettingsDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    ItemFPSSettings

    GameData_ItemFPSSettingsDataBlock_bin.json (filled)

    Determines Item location and camera settings for the first-person view.

    Note: GTFO uses 2 separate cameras in the First-Person view - the Look Camera renders the world, and the Item Camera renders the item held in the player's hands. These two cameras usually have differing FOVs in both the aimed and unaimed state of a weapon/tool.


    hashtag
    Fields

    Gear

    GameData_GearDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    range - Single

    No description provided.

    hashtag
    angle - Single

    No description provided.

    hashtag
    intensity - Single

    No description provided.

    hashtag
    cookie - String

    No description provided.

    hashtag
    color - Color

    No description provided.

    hashtag
    startupShard - AssetBundleShard (enum)

    No description provided.

    hashtag
    localPosHip - Vector3

    Position of weapon when hipfiring

    hashtag
    localRotHip - Vector3

    Rotation of weapon when hipfiring

    hashtag
    SwayAmount - Single

    No description provided.

    hashtag
    crouchTiltAngle - Single

    Angle the weapon tilts when player is crouched

    hashtag
    localPosRelaxed - Vector3

    Position of weapon when idle animation is playing

    hashtag
    localRotRelaxed - Vector3

    Rotation of weapon when idle animation is playing

    hashtag
    localPosZoom - Vector3

    Position of weapon when aiming

    hashtag
    localRotZoom - Vector3

    Rotation of weapon when aiming

    hashtag
    bodyOffsetLocal - Vector3

    Root position of weapon

    hashtag
    bodyRotationOffsetLocal - Vector3

    Root rotation of weapon

    hashtag
    ItemCameraFOVDefault - Int32

    FOV of camera that renders the weapon or tool

    hashtag
    ItemCameraFOVZoom - Int32

    FOV of camera that renders the weapon or tool, when aiming

    hashtag
    LookCameraFOVZoom - Int32

    FOV of camera that renders the world

    hashtag
    canAim - Boolean

    Can this weapon be aimed?

    hashtag
    onlyStartAimOnPressed - Boolean

    Identical across all base game Items (set to false), probably unused

    hashtag
    canRelax - Boolean

    Can this weapon play an idle animation?

    hashtag
    customDelayUntilRelax - Single

    Time until this weapon plays an idle animation

    hashtag
    allowRotToAimPos - Boolean

    Is the weapon allowed to rotate when moving to the aimed position?

    hashtag
    rotToAimPosMinDis - Single

    Identical across all base game Items (set to 1.0), probably unused

    hashtag
    transitionToAim - eFPISTransitionTime (enum)

    Speed of aim transition animation

    hashtag
    RecoilAnimation - UInt32 (ItemMovementAnimationDataBlock)

    Animation used when the weapon is recoiling

    hashtag
    IdleAnimation - UInt32 (ItemMovementAnimationDataBlock)

    Animation used when the player is stationary

    hashtag
    WalkAnimation - UInt32 (ItemMovementAnimationDataBlock)

    Animation used when the player is walking

    hashtag
    RunAnimation - UInt32 (ItemMovementAnimationDataBlock)

    Animation used when the player is sprinting

    hashtag
    JumpAnimation - UInt32 (ItemMovementAnimationDataBlock)

    Animation used when the player is jumping

    hashtag
    LandAnimation - UInt32 (ItemMovementAnimationDataBlock)

    Animation used when the player lands from a jump

    hashtag
    ChargeCancelAnimation - UInt32 (ItemMovementAnimationDataBlock)

    Animation used when the weapon is charged and the charge is aborted before completion

    hashtag
    DofDefault - DOFSettingsData (nested type)

    Default Depth of Field settings

    hashtag
    DofAim - DOFSettingsData (nested type)

    Depth of Field settings when weapon is aiming

    officialForRelease - Boolean

    No description provided.

    hashtag
    publicName - String

    No description provided.

    hashtag
    baseItemID - UInt32

    No description provided.

    hashtag
    weaponPersonalityID - UInt32

    No description provided.

    hashtag
    showAmmoInGUI - Boolean

    No description provided.

    hashtag
    archetypesAllowed - List GearArchetypeData (nested type)

    No description provided.

    hashtag
    ClassAmmoCostFactor - Single

    No description provided.

    hashtag
    PublicGearInfo - String

    No description provided.

    hashtag
    dropPeriodRange - List GearDropPeriodData (nested type)

    No description provided.

    hashtag
    structualModsAllowedGrip - List ItemPartData (nested type)

    No description provided.

    hashtag
    structualModsAllowedStock - List ItemPartData (nested type)

    No description provided.

    hashtag
    structualModsAllowedBarrel - List ItemPartData (nested type)

    No description provided.

    hashtag
    structualModsAllowedReceiver - List ItemPartData (nested type)

    No description provided.

    hashtag
    visualModsAllowed - List ItemPartData (nested type)

    No description provided.

    hashtag
    toolsAllowed - List ItemPartData (nested type)

    No description provided.

    hashtag
    sightsAllowed - List ItemPartData (nested type)

    No description provided.

    hashtag
    gripsAllowed - List ItemPartData (nested type)

    No description provided.

    hashtag
    muzzlesAllowed - List ItemPartData (nested type)

    No description provided.

    hashtag
    magazinesAllowed - List ItemPartData (nested type)

    No description provided.

    hashtag
    allowEmptyStructualModSlot - Boolean

    No description provided.

    hashtag
    allowEmptyVisualModSlot - Boolean

    No description provided.

    hashtag
    allowEmptyToolSlot - Boolean

    No description provided.

    hashtag
    allowEmptySightSlot - Boolean

    No description provided.

    hashtag
    allowEmptyGripSlot - Boolean

    No description provided.

    hashtag
    allowEmptyMuzzleSlot - Boolean

    No description provided.

    hashtag
    allowEmptyMagazineSlot - Boolean

    No description provided.

    eEnemyGroupType
    EnemySpawningData
    eEnemyRoleDifficulty
    eSpawnPlacementType
    List EnemyGroupCompositionData
    List EnemyRoleData
    StaticEnemyData
    StaticEnemyData
    Extremely dense red fog, looking from above fog
    Extremely dense red fog, looking from below fog

    Item

    GameData_ItemDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    publicName - String

    No description provided.

    hashtag
    LocalizedName - (nested type)

    No description provided.

    hashtag
    terminalItemShortName - String

    No description provided.

    hashtag
    terminalItemLongName - String

    No description provided.

    hashtag
    addSerialNumberToName - Boolean

    No description provided.

    hashtag
    registerInTerminalSystem - Boolean

    No description provided.

    hashtag
    DimensionWarpType - (enum)

    No description provided.

    hashtag
    Shard - (enum)

    No description provided.

    hashtag
    inventorySlot - (enum)

    No description provided.

    hashtag
    FPSSettings - UInt32 ()

    No description provided.

    hashtag
    crosshair - (enum)

    No description provided.

    hashtag
    HUDIcon - String

    No description provided.

    hashtag
    ShowCrosshairWhenAiming - Boolean

    No description provided.

    hashtag
    GUIShowAmmoClip - Boolean

    No description provided.

    hashtag
    GUIShowAmmoPack - Boolean

    No description provided.

    hashtag
    GUIShowAmmoTotalRel - Boolean

    No description provided.

    hashtag
    GUIShowAmmoInfinite - Boolean

    No description provided.

    hashtag
    canMoveQuick - Boolean

    No description provided.

    hashtag
    BlockToolAmmoRefill - Boolean

    No description provided.

    hashtag
    ClassAmmoCostFactor - Single

    No description provided.

    hashtag
    ConsumableAmmoMin - Int32

    No description provided.

    hashtag
    ConsumableAmmoMax - Int32

    No description provided.

    hashtag
    audioEventEquip - String

    No description provided.

    hashtag
    FirstPersonPrefabs - List String

    No description provided.

    hashtag
    ThirdPersonPrefabs - List String

    No description provided.

    hashtag
    PickupPrefabs - List String

    No description provided.

    hashtag
    InstancePrefabs - List String

    No description provided.

    hashtag
    EquipTransitionTime - Single

    No description provided.

    hashtag
    AimTransitionTime - Single

    No description provided.

    hashtag
    FPSArmsAnim - String

    No description provided.

    hashtag
    ThirdPersonFullbodyMovementSet - (enum)

    No description provided.

    hashtag
    LeftHandGripAlign - String

    No description provided.

    hashtag
    LeftHandGripAnim - String

    No description provided.

    hashtag
    RightHandGripAlign - String

    No description provided.

    hashtag
    RightHandGripAnim - String

    No description provided.

    hashtag
    SightLookAlign - String

    No description provided.

    hashtag
    MuzzleAlign - String

    No description provided.

    hashtag
    BackpackAlign - String

    No description provided.

    LevelLayout

    GameData_LevelLayoutDataBlock_bin.json (filled)

    Level layout is the main block defining what the level looks like and what you can find in it, including resources, enemies, terminals etc.

    hashtag
    Fields

    hashtag
    ZoneAliasStart - Int32

    The number of the first zone as seen in-game. The rest are derived from this and LocalIndex.

    hashtag
    Zones - (nested type)

    List containing the data of each zone. Each entry is one zone in the map. The first zone in the list is the entrance/elevator (NOT localindex 0).

    LightSettings

    GameData_LightSettingsDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    LightCategorySettings - (nested type)

    No description provided.

    MeleeArchetype

    GameData_MeleeArchetypeDataBlock_bin.json

    Defines melee weapon stats and metadata.

    This datablock is not referenced directly, but instead specified by the GearCategoryDataBlock given to a melee weapon.


    hashtag
    Fields

    hashtag
    PublicName - String

    Datablock name. Unused elsewhere.

    hashtag
    NoiseLevel - (enum)

    Normal: Wakes up sleepers in 7m from hitting locks or the ground. Quiet: Wakes up sleepers in 4m from hitting locks or the ground. Also has reduced chance to trigger long range aggro (i.e. glowing enemy wakes up far away from killing another enemy).

    hashtag
    ChargedAttackDamage - Single

    Damage dealt by fully charged attacks. Partial charge interpolates the damage from light to fully charged by the charge progress cubed.

    hashtag
    LightAttackDamage - Single

    Damage dealt by light attacks.

    hashtag
    LightStaggerMulti - Single

    Stagger damage multiplier for light attacks.

    hashtag
    ChargedStaggerMulti - Single

    Stagger damage multiplier for fully charged attacks. Partial charge interpolates the multiplier from light to fully charged by the charge progress cubed.

    hashtag
    LightPrecisionMulti - Single

    Precision damage multiplier for light attacks.

    hashtag
    ChargedPrecisionMulti - Single

    Precision damage multiplier for fully charged attacks. Partial charge interpolates the multiplier from light to fully charged by the charge progress cubed.

    hashtag
    LightEnvironmentMulti - Single

    Environment damage multiplier for light attacks (i.e. vs. locks and doors).

    hashtag
    ChargedEnvironmentMulti - Single

    Environment damage multiplier for fully charged attacks (i.e. vs. locks and doors). Partial charge interpolates the multiplier from light to fully charged by the charge progress cubed.

    hashtag
    LightBackstabberMulti - Single

    Backstab damage multiplier for light attacks. Stacks multiplicatively with the default backstab bonus. Does not apply to enemies without the default backstab bonus.

    hashtag
    ChargedBackstabberMulti - Single

    Backstab damage multiplier for light attacks. Stacks multiplicatively with the default backstab bonus. Does not apply to enemies without the default backstab bonus. Partial charge interpolates the multiplier from light to fully charged by the charge progress cubed.

    hashtag
    LightSleeperMulti - Single

    Damage multiplier to sleeping enemies for light attacks. Does not apply to Scouts.

    hashtag
    ChargedSleeperMulti - Single

    Damage multiplier to sleeping enemies for fully charged attacks. Does not apply to Scouts. Partial charge interpolates the multiplier from light to fully charged by the charge progress cubed.

    hashtag
    SkipLimbDestruction - Boolean

    Prevents the weapon from breaking enemy limbs.

    hashtag
    CameraDamageRayLength - Single

    Distance in meters that the weapon hits what is directly in view. Does not affect the model hitbox.

    hashtag
    AttackSphereRadius - Single

    Additional distance in meters around the model hitbox that hits can occur in. Does not affect wall collision. Remains inactive while something is directly in view. Appears to be twice as large as the value written in practice.

    hashtag
    PushDamageSphereRadius - Single

    Distance in meters around the player that pushes can affect targets in.

    hashtag
    CanHitMultipleEnemies - Boolean

    Allows the weapon to hit with both the forward damage ray (hitting a target directly in view) and the model hitbox. Also allows the weapon to hit additional targets after the first hit if the hit animation can deal damage. Can still damage multiple enemies simultaneously with the model hitbox even if set to false.

    hashtag
    EvaluateHoldBeforeAttack - Boolean

    If true, waits until the attack button is released to trigger a light attack. Otherwise, immediately begins the light attack animation on mouse click, though it can still transition to a charge attack.

    hashtag
    PlayImpactEffect - Boolean

    Should cause the impact particle effect when hitting terrain.

    hashtag
    AllowRunningWhenCharging - Boolean

    Allows the user to sprint while charging. If false, will stop and prevent sprinting while charging.

    hashtag
    PlayerRunSpeedMultiWhileCharging - Single

    Multiplier to user sprint speed while charging. Cannot cause the user to exceed their sprint speed, but can increase the diagonal sprint speed to match the forward sprint speed.

    hashtag
    MeleeAnimationSet - UInt32 ()

    Melee animation set ID of this weapon.

    hashtag
    MeleeSFXSet - UInt32 ()

    Melee SFX set ID of this weapon.

    hashtag
    ChargedAttackStaminaCost - ActionCost

    Stamina cost for fully charged attacks. Partial charge interpolates the multiplier from light to fully charged by the charge progress cubed.

    hashtag
    LightAttackStaminaCost - ActionCost

    Stamina cost for light attacks.

    hashtag
    PushStaminaCost - ActionCost

    Stamina cost for pushes.

    GearCategory

    GameData_GearCategoryDataBlock_bin.json (filled)

    This datablock collects several different DataBlock entries and types of metadata and integrates them into a single entry that can be referenced in the PlayerOfflineGearDatablock:

    • An ItemDataBlock entry (BaseItem, defining what kind of item something is)

    • 4 ArchetypeDataBlock fire modes (for projectile weapons)

    • A Melee attack mode (also from , for Melee weapons)

    • A priority list for Part alignments, used when a weapon is assembled in

    hashtag
    Fields

    hashtag
    PublicName - (nested type)

    In-game name, not used for weapons.

    hashtag
    Description - (nested type)

    Lobby description, not used by weapons.

    hashtag
    BaseItem - UInt32 ()

    PersistentID of an entry in ItemDataBlock.

    hashtag
    HUDIcon - String

    No description provided.

    hashtag
    IconRotationOffset - Single

    No description provided.

    hashtag
    IconZoomOffset - Single

    No description provided.

    hashtag
    FPSArmPoseName - String

    No description provided.

    hashtag
    ThirdPersonFullbodyMovement - (enum)

    Third-person animation set this item uses.

    hashtag
    SemiArchetype - UInt32 ()

    A reference to an entry, 0th field in fire mode selection.

    Does not determine a weapon's actual fire/usage mode, that determination is made in a weapon's GearJSON.

    hashtag
    BurstArchetype - UInt32 ()

    A reference to an entry, 1st field in fire mode selection.

    Does not determine a weapon's actual fire/usage mode, that determination is made in a weapon's GearJSON.

    hashtag
    AutoArchetype - UInt32 ()

    A reference to an entry, 2nd field in fire mode selection.

    Does not determine a weapon's actual fire/usage mode, that determination is made in a weapon's GearJSON.

    hashtag
    SemiBurstArchetype - UInt32 ()

    A reference to an entry, 3rd field in fire mode selection.

    Does not determine a weapon's actual fire/usage mode, that determination is made in a weapon's GearJSON.

    hashtag
    MeleeArchetype - UInt32 ()

    No description provided.

    hashtag
    PartAlignPriority - (nested type)

    Determines how parts with conflicting aligns behave.

    hashtag
    name - String

    Internal name string for this DataBlock entry.

    Not used in-game.

    SurvivalWavePopulation

    GameData_SurvivalWavePopulationDataBlock_bin.json (filled)

    This block is used for assigning types from to actual enemies using PersistentID from EnemyDataBlock.

    hashtag
    Fields

    Player

    GameData_PlayerDataBlock_bin.json (filled)

    Defines player stats.

    While this is a datablock, currently its only reference is hardcoded ID 1.

    hashtag
    Fields

    Recoil

    GameData_RecoilDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    Rundown

    GameData_RundownDataBlock_bin.json (filled)

    The rundown datablock defines everything within the entire rundown, including levels, weapons, enemies, and more. Only one rundown can be loaded at a time, and it is chosen in the datablock.

    hashtag
    Fields

    hashtag

    hashtag
    health - Single

    The max health of a player.

    hashtag
    healthRegenStartDelayAfterDamage - Single

    How long it takes for health to start regenerating after taking damage.

    hashtag
    healthRegenRelMax - Single

    Relative max hp to regenerate.

    E.g. 0.5 from 100 base would be 50.

    hashtag
    healthRegenDelay - Single

    Delay between health regeneration updates.

    hashtag
    healthRegenPerSecond - Single

    How much health is regenerated per second.

    hashtag
    friendlyFireMulti - Single

    Friendly fire damage multiplier.

    Currently broken for tools.

    hashtag
    fallDamageMinHeight - Single

    Minimum height a player has to fall to take fall damage.

    hashtag
    fallDamageMaxHeight - Single

    Falling height where a player takes maximum fall damage.

    hashtag
    fallDamageMin - Single

    Minimum fall damage a player can take.

    hashtag
    fallDamageMax - Single

    Maximum fall damage a player can take.

    Anywhere between min and max, fall damage scales linearly.

    hashtag
    nanoswarmShieldDamageMultiplierCurve - AnimationCurve

    Unknown, most likely related to the unreleased nanoswarm tool and likely to change.

    hashtag
    nanoswarmShieldResistanceCurve - AnimationCurve

    Unknown, most likely related to the unreleased nanoswarm tool and likely to change.

    hashtag
    nanoswarmNegativeResistanceCurve - AnimationCurve

    Unknown, most likely related to the unreleased nanoswarm tool and likely to change.

    hashtag
    battery - Int32

    Seems unused.

    hashtag
    smallBatteryConsumtionPerSec - Single

    Seems unused.

    hashtag
    mediumBatteryConsumtionPerSec - Single

    Seems unused.

    hashtag
    largeBatteryConsumtionPerSec - Single

    Seems unused.

    hashtag
    walkMoveSpeed - Single

    Player move speed while walking.

    hashtag
    runMoveSpeed - Single

    Player move speed when running/sprinting.

    hashtag
    airMoveSpeed - Single

    Affects move speed in the air. Seems to have little effect on slowing down and turning, mostly impacts speeding up. However, unless set to high values, makes no notable impact.

    hashtag
    crouchMoveSpeed - Single

    Player move speed while crouching.

    hashtag
    ladderMoveSpeed - Single

    Player move speed when going up and down ladders.

    hashtag
    walkFootstepLength - Single

    Only seems to have an impact on when player footstep audio is played.

    hashtag
    runFootstepLength - Single

    Only seems to have an impact on when player footstep audio is played.

    hashtag
    crouchFootstepLength - Single

    Only seems to have an impact on when player footstep audio is played.

    hashtag
    throttleSmoothAcc - Single

    Multiplier for smooth acceleration. At low values players will have trouble speeding up.

    hashtag
    throttleSmoothStop - Single

    Multiplier for smooth stopping. At low values players will have trouble stopping in place (can still reverse direction normally depending on acc value).

    hashtag
    throttleSmoothVertical - Single

    Seems to have no effect.

    hashtag
    jumpVelInitial - Single

    Initial vertical velocity gained from a jump.

    hashtag
    jumpGravityMulDefault - Single

    Gravity mults affect how fast falling accelerates (rising decelerates).

    Gravity mult when rising and holding the jump button.

    hashtag
    jumpGravityMulButtonReleased - Single

    Gravity mult when rising and not holding the jump button.

    hashtag
    jumpGravityMulAfterPeak - Single

    Gravity mult after jump peak.

    hashtag
    jumpGravityMulFalling - Single

    Gravity mult when falling without jumping.

    hashtag
    jumpVerticalVelocityMax - Single

    Maximum vertical movement speed.

    hashtag
    camPosDefault - Vector3

    Default player camera position offset from player's feet.

    hashtag
    camPosCrouch - Vector3

    Player camera position offset while crouched.

    hashtag
    camFovRunDif - Single

    Added fov while player is running.

    hashtag
    DofDefault - DOFSettingsData (nested type)

    Default depth of field settings.

    hashtag
    DofInElevator - DOFSettingsData (nested type)

    Depth of field settings in elevator.

    hashtag
    DofInTerminal - DOFSettingsData (nested type)

    Depth of field settings in terminal.

    hashtag
    ChromaticAbberationIntensityMax - Single

    Seems unused.

    hashtag
    mouselookAimScaleMinMax - Vector2

    Mouselook settings are probably something you shouldn't mess with.

    Seems to affect aim sensitivity when in sights.

    hashtag
    mouselookAimScaleFovRef - Vector2

    Seems to affect aim sensitivity when in sights.

    hashtag
    FPSArmsOffset - Vector3

    FPS settings are probably something you shouldn't mess with.

    FPS model setting.

    hashtag
    FPSBodyOffset - Vector3

    FPS model setting.

    hashtag
    AdditionalFPSBodyOffsetWhenRunning - Vector3

    FPS model setting.

    hashtag
    FPSBodyOffsetWhenNotFollowingCamera - Vector3

    FPS model setting.

    hashtag
    FPSBodyScale - Vector3

    FPS model setting.

    hashtag
    FPSBodyMoveNeckToFollowCamera - Boolean

    FPS model setting.

    hashtag
    FPSBodyWantedDisToNeck - Single

    FPS model setting.

    hashtag
    GearMaxSightHeightDiff - Single

    Affects maximum possible height above default of sights.

    hashtag
    AmmoStandardInitial - Int32

    Ammo settings are closely tied with Archetype cost of bullet settings and explained there.

    These settings are not literal bullet counts but rather a base value for calculations.

    Initial standard weapon ammo when starting the level.

    hashtag
    AmmoStandardInitialOnDropin - Int32

    Seems unused.

    hashtag
    AmmoStandardMaxCap - Int32

    Max reserve ammo for standard weapons.

    hashtag
    AmmoStandardResourcePackMaxCap - Int32

    Affects how much ammo you get from a refill pack.

    hashtag
    AmmoSpecialInitial - Int32

    Initial special weapon ammo when starting the level.

    hashtag
    AmmoSpecialInitialOnDropin - Int32

    Seems unused.

    hashtag
    AmmoSpecialMaxCap - Int32

    Max reserve ammo for special weapons.

    hashtag
    AmmoSpecialResourcePackMaxCap - Int32

    Affects how much ammo you get from a refill pack.

    hashtag
    AmmoClassInitial - Int32

    Initial tool ammo.

    hashtag
    AmmoClassInitialOnDropin - Int32

    Seems unused.

    hashtag
    AmmoClassMaxCap - Int32

    Max tool ammo.

    hashtag
    AmmoClassResourcePackMaxCap - Int32

    Affects how much ammo you get from a refill pack.

    There is an additional multiplier for sentries.

    hashtag
    implantSmallTriggerDelay - Single

    Seems unused.

    hashtag
    implantBigTriggerDelay - Single

    Seems unused.

    hashtag
    itemAnimWeight - Single

    circle-exclamation

    The following item settings seem to be either unused or have no impact worth editing for modders, therefore they have no descriptions.

    hashtag
    itemAnimAxisWeight - Vector3

    No description provided.

    hashtag
    itemLookatAimWeight - Single

    No description provided.

    hashtag
    itemLookSwayWeight - Single

    No description provided.

    hashtag
    itemLookSwayPosImpulseScale - Vector3

    No description provided.

    hashtag
    itemLookSwayPosStiffness - Single

    No description provided.

    hashtag
    itemLookSwayPosDamping - Single

    No description provided.

    hashtag
    itemLookSwayRotImpulseScale - Vector3

    No description provided.

    hashtag
    itemLookSwayRotXMulti - Vector2

    No description provided.

    hashtag
    itemLookSwayRotStiffness - Single

    No description provided.

    hashtag
    itemLookSwayRotDamping - Single

    No description provided.

    hashtag
    itemLookSwayWeightAiming - Single

    No description provided.

    hashtag
    itemLookSwayPosImpulseScaleAiming - Vector3

    No description provided.

    hashtag
    itemLookSwayRotImpulseScaleAiming - Vector3

    No description provided.

    hashtag
    itemAnimWeightAiming - Single

    No description provided.

    hashtag
    itemRecoilWeight - Single

    No description provided.

    hashtag
    itemFootstepWeight - Single

    No description provided.

    hashtag
    itemFootstepWeightAiming - Single

    No description provided.

    hashtag
    itemFootstepDelay - Single

    No description provided.

    hashtag
    itemFootstepImpulseScale - Vector3

    No description provided.

    hashtag
    itemFootstepStiffness - Single

    No description provided.

    hashtag
    itemFootstepDamping - Single

    No description provided.

    hashtag
    breathingEnabled - Boolean

    Determines whether audible breathing from stamina and infection is enabled.

    hashtag
    breathingStaminaEnabled - Boolean

    Determines whether audible breathing from stamina is enabled.

    hashtag
    breathingScaredEnabled - Boolean

    Seems unused or unknown.

    hashtag
    breathingDebugEnabled - Boolean

    When enabled, prints some additional debug logs regarding breathing.

    hashtag
    breathingVolume - Single

    Base audible breathing sound volume.

    hashtag
    breathingHealthLowLimit - Single

    Health limit for switching to low health breathing sound.

    hashtag
    StaminaTimeBeforeResting - Single

    Time without spending stamina before player starts resting.

    hashtag
    StaminaRegenRestingInCombat - Single

    Stamina regeneration rate when resting in combat.

    hashtag
    StaminaRegenNotRestingInCombat - Single

    Stamina regeneration rate when not resting in combat.

    hashtag
    StaminaRegenRestingOutOfCombat - Single

    Stamina regeneration rate when resting out of combat.

    hashtag
    StaminaRegenNotRestingOutOfCombat - Single

    Stamina regeneration rate when not resting out of combat.

    hashtag
    StaminaEnableAffectMoveSpeed - Boolean

    Whether stamina can affect movement speed.

    hashtag
    StaminaHighMovespeedModifier - Single

    Movement speed multiplier when stamina is high.

    hashtag
    StaminaLowMovespeedModifier - Single

    Movement speed multiplier when stamina is low.

    hashtag
    StaminaMoveSpeedCurveExponent - Single

    Stamina speed modifier is a lerp between high and low with tiredness (0 - full stamina, 1 - empty stamina) as the value used to interpolate.

    This value is the exponent for tiredness. Higher value means stamina will slow down players less.

    hashtag
    StaminaEnableAffectMeleeSpeed - Boolean

    Whether stamina should affect melee charge speed.

    hashtag
    StaminaHighMeleeSpeedModifier - Single

    Melee charge speed multiplier when stamina is high.

    hashtag
    StaminaLowMeleeSpeedModifier - Single

    Melee charge speed multiplier when stamina is low.

    hashtag
    StaminaMeleeSpeedCurveExponent - Single

    StaminaMoveSpeedCurveExponent equivalent for melee charge speed.

    hashtag
    StaminaExhaustedAudioThreshold - Single

    Sfx Audio threshold for stamina exhausted loop.

    hashtag
    StaminaWasTiredAudioThreshold - Single

    Threshold for setting an audio switch for playing was tired breathing audio later.

    hashtag
    StaminaRestedAudioThreshold - Single

    Stamina threshold for playing rested audio after player was tired.

    hashtag
    StaminaUsageAffectedByDrama - Boolean

    Effectively decides whether InCombat values will be used during combat.

    hashtag
    StaminaMinimumCapWhenNotInCombat - Single

    Minimum allowed stamina when not in combat.

    hashtag
    StaminaMaximumCapWhenInCombat - Single

    Maximum allowed stamina when in combat.

    hashtag
    StaminaMaximumCapWhenInCombatFallRate - Single

    How fast should stamina fall to combat maximum cap during combat.

    Default 0 in base game, which means stamina will not fall unless players use it.

    hashtag
    StaminaJumpCost - ActionCost

    Jump stamina action cost.

    hashtag
    StaminaSneakCost - ActionCost

    Crouching movement stamina action cost.

    hashtag
    StaminaWalkCost - ActionCost

    Walking stamina action cost.

    hashtag
    StaminaRunCost - ActionCost

    Running/sprinting stamina action cost.

    hashtag
    StaminaCrouchEnterCost - ActionCost

    Crouch enter stamina action cost.

    hashtag
    defaultDialogLineDelay - Single

    Delay between separate dialog lines.

    Dialog line fields seem mostly related to PlayerDialogDataBlock.

    circle-exclamation

    To our knowledge the rest of these fields are either unused or not useful for modders so most of them probably will not have useful descriptions.

    hashtag
    shortDialogCooldown - Single

    How long a short dialog is blocked after playing.

    hashtag
    mediumDialogCooldown - Single

    How long a medium dialog is blocked after playing.

    hashtag
    longDialogCooldown - Single

    How long a long dialog is blocked after playing.

    hashtag
    radioEnabledDefaultDistance - Single

    No description provided.

    hashtag
    radioQualityLowestAtDistance - Single

    No description provided.

    hashtag
    lowTensionMaxLimit - Single

    No description provided.

    hashtag
    mediumTensionMaxLimit - Single

    No description provided.

    hashtag
    dialogEnabledInSpectator - Boolean

    No description provided.

    hashtag
    radioQualityInSpectator - Single

    No description provided.

    hashtag
    radioDistortionInSpectator - Single

    No description provided.

    hashtag
    noAirTimeToEmpty - Single

    No description provided.

    hashtag
    noAirDamageRel - Single

    No description provided.

    hashtag
    noAirDamageDelay - Single

    No description provided.

    hashtag
    Regarding ActionCost

    A separate page for this struct was not generated because whoever made it is an idiot (but actually probably just a new person who doesn't know how datablocks are supposed to work).

    For rundown developers, ActionCost is essentially the same thing as any other nested type.

    hashtag
    baseStaminaCostInCombat - Single

    Stamina cost of this action in combat.

    hashtag
    baseStaminaCostOutOfCombat - Single

    Stamina cost of this action out of combat.

    hashtag
    resetRestingTimerInCombat - Boolean

    Whether this action should reset resting timer in combat.

    hashtag
    resetRestingTimerOutOfCombat - Boolean

    Whether this action should reset resting timer out of combat.

    power - MinMaxValue (nested type)

    No description provided.

    hashtag
    spring - Single

    No description provided.

    hashtag
    dampening - Single

    No description provided.

    hashtag
    hipFireCrosshairSizeDefault - Single

    No description provided.

    hashtag
    hipFireCrosshairRecoilPop - Single

    No description provided.

    hashtag
    hipFireCrosshairSizeMax - Single

    No description provided.

    hashtag
    horizontalScale - MinMaxValue (nested type)

    No description provided.

    hashtag
    verticalScale - MinMaxValue (nested type)

    No description provided.

    hashtag
    directionalSimilarity - Single

    No description provided.

    hashtag
    worldToViewSpaceBlendHorizontal - Single

    No description provided.

    hashtag
    worldToViewSpaceBlendVertical - Single

    No description provided.

    hashtag
    recoilPosImpulse - Vector3

    No description provided.

    hashtag
    recoilPosShift - Vector3

    No description provided.

    hashtag
    recoilPosShiftWeight - Single

    No description provided.

    hashtag
    recoilPosStiffness - Single

    No description provided.

    hashtag
    recoilPosDamping - Single

    No description provided.

    hashtag
    recoilPosImpulseWeight - Single

    No description provided.

    hashtag
    recoilCameraPosWeight - Single

    No description provided.

    hashtag
    recoilAimingWeight - Single

    No description provided.

    hashtag
    recoilRotImpulse - Vector3

    No description provided.

    hashtag
    recoilRotStiffness - Single

    No description provided.

    hashtag
    recoilRotDamping - Single

    No description provided.

    hashtag
    recoilRotImpulseWeight - Single

    No description provided.

    hashtag
    recoilCameraRotWeight - Single

    No description provided.

    hashtag
    concussionIntensity - Single

    No description provided.

    hashtag
    concussionFrequency - Single

    No description provided.

    hashtag
    concussionDuration - Single

    No description provided.

    LocalizedText
    ItemWarpType
    AssetBundleShard
    InventorySlot
    ItemFPSSettingsDataBlock
    Crosshair
    eFullbodyPlayerMovementSet
    List ExpeditionZoneData
    List LightCategorySetting
    DamageNoiseLevel
    MeleeAnimationSetDataBlock
    MeleeSFXDataBlock
    ArchetypeDataBlock
    PlayerOfflineGearDataBlock
    LocalizedText
    LocalizedText
    ItemDataBlock
    eFullbodyPlayerMovementSet
    ArchetypeDataBlock
    ArchetypeDataBlock
    PlayerOfflineGearDataBlock
    ArchetypeDataBlock
    ArchetypeDataBlock
    PlayerOfflineGearDataBlock
    ArchetypeDataBlock
    ArchetypeDataBlock
    PlayerOfflineGearDataBlock
    ArchetypeDataBlock
    ArchetypeDataBlock
    PlayerOfflineGearDataBlock
    MeleeArchetypeDataBlock
    List GearPartAlignPriority
    hashtag
    WaveRoleWeakling - UInt32 (EnemyDataBlock)

    EnemyDataBlock PersistentID of eEnemyType Weakling for this population.

    hashtag
    WaveRoleStandard - UInt32 (EnemyDataBlock)

    EnemyDataBlock PersistentID of eEnemyType Standard for this population.

    hashtag
    WaveRoleSpecial - UInt32 (EnemyDataBlock)

    EnemyDataBlock PersistentID of eEnemyType Special for this population.

    hashtag
    WaveRoleMiniBoss - UInt32 (EnemyDataBlock)

    EnemyDataBlock PersistentID of eEnemyType MiniBoss for this population.

    hashtag
    WaveRoleBoss - UInt32 (EnemyDataBlock)

    EnemyDataBlock PersistentID of eEnemyType Boss for this population.

    Note that Boss is currently broken in base game.

    eEnemyType
    SurvivalWaveSettingsDataBlock
    NeverShowRundownTree - Boolean

    No description provided.

    hashtag
    UseTierUnlockRequirements - Boolean

    Whether or not to use unlock requirements for this rundown.

    hashtag
    ReqToReachTierB - RundownTierProgressionData (nested type)

    Progression data to reach tier B of the rundown.

    hashtag
    ReqToReachTierC - RundownTierProgressionData (nested type)

    Progression data to reach tier C of the rundown.

    hashtag
    ReqToReachTierD - RundownTierProgressionData (nested type)

    Progression data to reach tier D of the rundown.

    hashtag
    ReqToReachTierE - RundownTierProgressionData (nested type)

    Progression data to reach tier E of the rundown.

    hashtag
    StorytellingData - RundownStorytellingData (nested type)

    Data for title, visuals, and description of the rundown.

    hashtag
    VanityItemLayerDropDataBlock - UInt32 (VanityItemsLayerDropsDataBlock)

    The id for the vanity item datablock for this rundown.

    hashtag
    TierA - List ExpeditionInTierData (nested type)

    Expedition data for all levels in tier A of this rundown.

    hashtag
    TierB - List ExpeditionInTierData (nested type)

    Expedition data for all levels in tier B of this rundown.

    hashtag
    TierC - List ExpeditionInTierData (nested type)

    Expedition data for all levels in tier C of this rundown.

    hashtag
    TierD - List ExpeditionInTierData (nested type)

    Expedition data for all levels in tier D of this rundown.

    hashtag
    TierE - List ExpeditionInTierData (nested type)

    Expedition data for all levels in tier E of this rundown.

    GameSetup

    VanityItemsTemplate

    GameData_VanityItemsTemplateDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    publicName - String

    No description provided.

    hashtag
    type - (enum)

    No description provided.

    hashtag
    prefab - String

    No description provided.

    hashtag
    DropWeight - Single

    No description provided.

    hashtag
    icon - String

    No description provided.

    PlayerOfflineGear

    GameData_PlayerOfflineGearDataBlock_bin.json (filled)

    Defines mostly various weapon parts (references to various gear datablocks) and some other data.

    Probably the worst datablock in the game.

    hashtag
    Fields

    hashtag
    Type - (enum)

    The only known use and difference here is "RundownSpecificInventory" which simply changes the text displayed in lobby.

    hashtag
    GearJSON - String

    This innocent little string here contains an absurd amount of information in an even more absurd format (it's JSON embedded into JSON). It's most likely this way because it's sent over the network to all other players, so the devs didn't make it more readable in a DataBlock.

    This JSON and its meaning (including various related DataBlocks) is covered in the .

    MeleeAnimationSet

    GameData_MeleeAnimationSetDataBlock_bin.json

    Defines melee weapon animation sets alongside several timings related to them.

    This datablock is referenced by a MeleeArchetypeDataBlock.


    hashtag
    Fields

    hashtag
    HoldToChargeTime - Single

    Time in seconds that attack must be held for the weapon to begin charging.

    hashtag
    MaxDamageChargeTime - Single

    Time in seconds to reach full charge.

    hashtag
    AutoAttackTime - Single

    Time in seconds after starting a charge at which the weapon will automatically swing.

    hashtag
    AutoAttackWarningTime - Single

    Time in seconds after starting a charge at which a sound effect plays and causes the reticle to blink red (to warn that the automatic attack will occur soon).

    hashtag
    FPIdleAnim - (nested type)

    No description provided.

    hashtag
    FPSettleAnim - (nested type)

    No description provided.

    hashtag
    FPWalkAnim - (nested type)

    No description provided.

    hashtag
    FPRunAnim - (nested type)

    No description provided.

    hashtag
    FPJumpAnim - (nested type)

    No description provided.

    hashtag
    FPLandAnim - (nested type)

    No description provided.

    hashtag
    FPChargeCancelAnimRight - (nested type)

    No description provided.

    hashtag
    FPChargeCancelAnimLeft - (nested type)

    No description provided.

    hashtag
    FPAttackMissRight - (nested type)

    Animation for the light attack that swings from the right (e.g. the first swing).

    hashtag
    FPAttackMissLeft - (nested type)

    Animation for the light attack that swings from the left (e.g. the second swing).

    hashtag
    FPAttackHitRight - (nested type)

    Animation that plays after hitting a light attack from the right.

    hashtag
    FPAttackHitLeft - (nested type)

    Animation that plays after hitting a light attack from the left.

    hashtag
    FPAttackPush - (nested type)

    Animation for pushing. Note: Pushes cannot normally be consecutively done faster than 1.2s. However, attacks reset this cooldown and allow two consecutive pushes to be performed afterwards, separated by push's combo time.

    hashtag
    FPAttackChargeUpRight - (nested type)

    Animation for charging an attack from the right.

    hashtag
    FPAttackChargeUpLeft - (nested type)

    Animation for charging an attack from the left.

    hashtag
    FPAttackChargeUpReleaseRight - (nested type)

    Animation for the charge attack that swings from the right.

    hashtag
    FPAttackChargeUpReleaseLeft - (nested type)

    Animation for the charge attack that swings from the left.

    hashtag
    FPAttackChargeUpHitRight - (nested type)

    Animation that plays after hitting a charge attack from the right.

    hashtag
    FPAttackChargeUpHitLeft - (nested type)

    Animation that plays after hitting a charge attack from the left.

    hashtag
    TPAnimHashIdle - (nested type)

    No description provided.

    hashtag
    TPAnimHashIdleCrouch - (nested type)

    No description provided.

    hashtag
    TPAnimHashAttackLeft - (nested type)

    No description provided.

    hashtag
    TPAnimHashAttackLeftCrouch - (nested type)

    No description provided.

    hashtag
    TPAnimHashAttackLeftCharge - (nested type)

    No description provided.

    hashtag
    TPAnimHashAttackLeftChargeCrouch - (nested type)

    No description provided.

    hashtag
    TPAnimHashAttackLeftRelease - (nested type)

    No description provided.

    hashtag
    TPAnimHashAttackLeftReleaseCrouch - (nested type)

    No description provided.

    Weapon

    GameData_WeaponDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    muzzleFlashFPS - String

    No description provided.

    hashtag
    muzzleFlash3RD - String

    No description provided.

    hashtag
    muzzleFlashFPSSpecial - String

    No description provided.

    hashtag
    muzzleFlash3RDSpecial - String

    No description provided.

    hashtag
    muzzleFeedback - String

    No description provided.

    hashtag
    shellType - (enum)

    No description provided.

    hashtag
    shellEjectFeedback - String

    No description provided.

    hashtag
    clipSize - Int32

    No description provided.

    hashtag
    hasRotatingCylinder - Boolean

    No description provided.

    hashtag
    reloadDuration - Single

    No description provided.

    hashtag
    EffectiveDamagePerSecond - String

    No description provided.

    hashtag
    recoilPosImpulse - Vector3

    No description provided.

    hashtag
    recoilPosShift - Vector3

    No description provided.

    hashtag
    recoilPosShiftWeight - Single

    No description provided.

    hashtag
    recoilPosStiffness - Single

    No description provided.

    hashtag
    recoilPosDamping - Single

    No description provided.

    hashtag
    recoilPosImpulseWeight - Single

    No description provided.

    hashtag
    recoilCameraPosWeight - Single

    No description provided.

    hashtag
    recoilRotImpulse - Vector3

    No description provided.

    hashtag
    recoilRotStiffness - Single

    No description provided.

    hashtag
    recoilRotDamping - Single

    No description provided.

    hashtag
    recoilRotImpulseWeight - Single

    No description provided.

    hashtag
    recoilCameraRotWeight - Single

    No description provided.

    hashtag
    recoilAimingWeight - Single

    No description provided.

    hashtag
    eventOnSemiFire2D - List String

    No description provided.

    hashtag
    eventOnBurstFire2D - List String

    No description provided.

    hashtag
    eventOnAutoFireStart2D - List String

    No description provided.

    hashtag
    eventOnAutoFireEnd2D - List String

    No description provided.

    hashtag
    eventOnSpecialSemiFire2D - List String

    No description provided.

    hashtag
    eventOnSpecialBurstFire2D - List String

    No description provided.

    hashtag
    eventOnSpecialAutoFireStart2D - List String

    No description provided.

    hashtag
    eventOnSpecialAutoFireEnd2D - List String

    No description provided.

    hashtag
    eventOnSpecialChargeup2D - List String

    No description provided.

    hashtag
    eventOnSpecialCooldown2D - List String

    No description provided.

    hashtag
    eventOnSpecialChargeupEnd2D - String

    No description provided.

    hashtag
    eventOnSpecialCooldownEnd2D - String

    No description provided.

    hashtag
    eventOnSemiFire3D - List String

    No description provided.

    hashtag
    eventOnBurstFire3D - List String

    No description provided.

    hashtag
    eventOnAutoFireStart3D - List String

    No description provided.

    hashtag
    eventOnAutoFireEnd3D - List String

    No description provided.

    hashtag
    eventOnSpecialSemiFire3D - List String

    No description provided.

    hashtag
    eventOnSpecialBurstFire3D - List String

    No description provided.

    hashtag
    eventOnSpecialAutoFireStart3D - List String

    No description provided.

    hashtag
    eventOnSpecialAutoFireEnd3D - List String

    No description provided.

    hashtag
    eventOnSpecialChargeup3D - List String

    No description provided.

    hashtag
    eventOnSpecialCooldown3D - List String

    No description provided.

    hashtag
    eventOnSpecialChargeupEnd3D - String

    No description provided.

    hashtag
    eventOnSpecialCooldownEnd3D - String

    No description provided.

    hashtag
    eventClick - String

    No description provided.

    hashtag
    eventReload - String

    No description provided.

    hashtag
    useSemiAudioForBurstShots - Boolean

    No description provided.

    SurvivalWaveSettings

    GameData_SurvivalWaveSettingsDataBlock_bin.json (filled)

    Provides the settings for alarms, scout waves and similar types of waves (all referred to as "alarm" in sections below).

    hashtag
    Fields

    circle-exclamation

    PersistentID value range is changed from default to 1-255

    All time-related settings are specified in seconds.

    hashtag
    m_pauseBeforeStart - Single

    Delay before waves start spawning after alarm start.

    hashtag
    m_pauseBetweenGroups - Single

    Delay between enemy groups.

    hashtag
    m_wavePauseMin_atCost - Single

    Minimum score boundary for pauses between waves.

    hashtag
    m_wavePauseMax_atCost - Single

    Maximum score boundary for pauses between waves.

    Above this threshold, the timer for a new wave doesn't move.

    Anywhere in-between min and max, the timer speed is lerped.

    hashtag
    m_wavePauseMin - Single

    Delay between waves at or below minimum score boundary.

    hashtag
    m_wavePauseMax - Single

    Delay between waves at maximum score boundary.

    hashtag
    m_populationFilter - (enum)

    List of enemy types in filter.

    hashtag
    m_filterType - (enum)

    Whether to spawn only, or spawn all but the types included in population filter.

    hashtag
    m_chanceToRandomizeSpawnDirectionPerWave - Single

    Chance for spawn direction to change between waves.

    hashtag
    m_chanceToRandomizeSpawnDirectionPerGroup - Single

    Change for spawn direction to change between groups.

    hashtag
    m_overrideWaveSpawnType - Boolean

    Whether to override spawn type set in code.

    hashtag
    m_survivalWaveSpawnType - (enum)

    The spawn type when override is set to true.

    hashtag
    m_populationPointsTotal - Single

    The total population points for waves. The alarm automatically stops if this runs out. -1 is infinite.

    hashtag
    m_populationPointsPerWaveStart - Single

    Population points for a wave at start ramp.

    hashtag
    m_populationPointsPerWaveEnd - Single

    Population points for a wave at end ramp.

    hashtag
    m_populationPointsMinPerGroup - Single

    Minimum required cost for a group to spawn. This setting is related to the soft cap of enemies.

    hashtag
    m_populationPointsPerGroupStart - Single

    Population points for a group at start ramp.

    hashtag
    m_populationPointsPerGroupEnd - Single

    Population points for a group at end ramp.

    hashtag
    m_populationRampOverTime - Single

    Lerp over time for start-end population point settings.

    hashtag
    Regarding population points and soft cap

    By default the game has some hardcoded values set that are used for score settings - cost of an enemy and soft cap.

    Enemy costs per type are the following: 0.75 1 1 2 2.

    Soft cap (MaxAllowedCost) is 25.

    All aggressive enemies count towards cap. If the remaining allowed cost is lower than the minimum required cost of a group, the group cannot spawn and the wave pauses until enough points are available. The enemy type here is determined in .

    The enemy type for wave population point cost is determined by wave settings.

    WardenObjective

    GameData_WardenObjectiveDataBlock_bin.json (filled)

    hashtag
    Fields

    hashtag
    Type - (enum)

    Text

    GameData_TextDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    Artifact

    GameData_ArtifactDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    ArtifactDistribution

    GameData_ArtifactDistributionDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    SkipLocalization - Boolean

    No description provided.

    hashtag
    MachineTranslation - Boolean

    No description provided.

    hashtag
    English - String

    No description provided.

    hashtag
    Description - String

    No description provided.

    hashtag
    CharacterMetaData - UInt32 (TextCharacterMetaDataBlock)

    No description provided.

    hashtag
    French - LanguageData (nested type)

    No description provided.

    hashtag
    Italian - LanguageData (nested type)

    No description provided.

    hashtag
    German - LanguageData (nested type)

    No description provided.

    hashtag
    Spanish - LanguageData (nested type)

    No description provided.

    hashtag
    Russian - LanguageData (nested type)

    No description provided.

    hashtag
    Portuguese_Brazil - LanguageData (nested type)

    No description provided.

    hashtag
    Polish - LanguageData (nested type)

    No description provided.

    hashtag
    Japanese - LanguageData (nested type)

    No description provided.

    hashtag
    Korean - LanguageData (nested type)

    No description provided.

    hashtag
    Chinese_Traditional - LanguageData (nested type)

    No description provided.

    hashtag
    Chinese_Simplified - LanguageData (nested type)

    No description provided.

    hashtag
    ExportVersion - Int32

    No description provided.

    hashtag
    ImportVersion - Int32

    No description provided.

    PublicName - String

    No description provided.

    hashtag
    ArtifactCategory - ArtifactCategory (enum)

    No description provided.

    hashtag
    PrefabPath - String

    No description provided.

    hashtag
    PrefabPaths - List String

    No description provided.

    hashtag
    TagsID - UInt32 (ArtifactTagDataBlock)

    No description provided.

    BasicWeight - Single

    No description provided.

    hashtag
    AdvancedWeight - Single

    No description provided.

    hashtag
    SpecializedWeight - Single

    No description provided.

    ClothesType
    eOfflineGearType
    Creating Custom Weapons guide
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    MeleeAttackData
    MeleeAttackData
    MeleeAttackData
    MeleeAttackData
    MeleeAttackData
    MeleeAttackData
    MeleeAttackData
    MeleeAttackData
    MeleeAttackData
    MeleeAttackData
    MeleeAttackData
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    AnimHash
    ShellTypes
    List eEnemyType
    eEnemyFilterType
    SurvivalWaveSpawnType
    EnemyDataBlock

    Rarely Edited

    List of datablocks that modders rarely edit

    No description provided.

    hashtag
    Header - LocalizedText (nested type)

    No description provided.

    hashtag
    MainObjective - LocalizedText (nested type)

    No description provided.

    hashtag
    WardenObjectiveSpecialUpdateType - eWardenObjectiveSpecialUpdateType (enum)

    No description provided.

    hashtag
    GenericItemFromStart - UInt32 (ItemDataBlock)

    No description provided.

    hashtag
    DoNotMarkPickupItemsAsWardenObjectives - Boolean

    No description provided.

    hashtag
    FindLocationInfo - LocalizedText (nested type)

    No description provided.

    hashtag
    FindLocationInfoHelp - LocalizedText (nested type)

    No description provided.

    hashtag
    GoToZone - LocalizedText (nested type)

    No description provided.

    hashtag
    GoToZoneHelp - LocalizedText (nested type)

    No description provided.

    hashtag
    InZoneFindItem - LocalizedText (nested type)

    No description provided.

    hashtag
    InZoneFindItemHelp - LocalizedText (nested type)

    No description provided.

    hashtag
    SolveItem - LocalizedText (nested type)

    No description provided.

    hashtag
    SolveItemHelp - LocalizedText (nested type)

    No description provided.

    hashtag
    GoToWinCondition_Elevator - LocalizedText (nested type)

    No description provided.

    hashtag
    GoToWinConditionHelp_Elevator - LocalizedText (nested type)

    No description provided.

    hashtag
    GoToWinCondition_CustomGeo - LocalizedText (nested type)

    No description provided.

    hashtag
    GoToWinConditionHelp_CustomGeo - LocalizedText (nested type)

    No description provided.

    hashtag
    GoToWinCondition_ToMainLayer - LocalizedText (nested type)

    No description provided.

    hashtag
    GoToWinConditionHelp_ToMainLayer - LocalizedText (nested type)

    No description provided.

    hashtag
    ShowHelpDelay - Single

    No description provided.

    hashtag
    WavesOnElevatorLand - List GenericEnemyWaveData (nested type)

    No description provided.

    hashtag
    EventsOnElevatorLand - List WardenObjectiveEventData (nested type)

    No description provided.

    hashtag
    WaveOnElevatorWardenIntel - LocalizedText (nested type)

    No description provided.

    hashtag
    FogTransitionDataOnElevatorLand - UInt32 (FogSettingsDataBlock)

    No description provided.

    hashtag
    FogTransitionDurationOnElevatorLand - Single

    No description provided.

    hashtag
    OnActivateOnSolveItem - Boolean

    No description provided.

    hashtag
    WavesOnActivate - List GenericEnemyWaveData (nested type)

    No description provided.

    hashtag
    EventsOnActivate - List WardenObjectiveEventData (nested type)

    No description provided.

    hashtag
    StopAllWavesBeforeGotoWin - Boolean

    No description provided.

    hashtag
    WavesOnGotoWin - List GenericEnemyWaveData (nested type)

    No description provided.

    hashtag
    WaveOnGotoWinTrigger - eRetrieveExitWaveTrigger (enum)

    No description provided.

    hashtag
    EventsOnGotoWin - List WardenObjectiveEventData (nested type)

    No description provided.

    hashtag
    EventsOnGotoWinTrigger - eRetrieveExitWaveTrigger (enum)

    No description provided.

    hashtag
    FogTransitionDataOnGotoWin - UInt32 (FogSettingsDataBlock)

    No description provided.

    hashtag
    FogTransitionDurationOnGotoWin - Single

    No description provided.

    hashtag
    ChainedPuzzleToActive - UInt32 (ChainedPuzzleDataBlock)

    No description provided.

    hashtag
    ChainedPuzzleMidObjective - UInt32 (ChainedPuzzleDataBlock)

    No description provided.

    hashtag
    ChainedPuzzleAtExit - UInt32 (ChainedPuzzleDataBlock)

    No description provided.

    hashtag
    ChainedPuzzleAtExitScanSpeedMultiplier - Single

    No description provided.

    hashtag
    Gather_RequiredCount - Int32

    No description provided.

    hashtag
    Gather_ItemId - UInt32 (ItemDataBlock)

    No description provided.

    hashtag
    Gather_SpawnCount - Int32

    No description provided.

    hashtag
    Gather_MaxPerZone - Int32

    No description provided.

    hashtag
    Retrieve_Items - List UInt32 (ItemDataBlock)

    No description provided.

    hashtag
    ReactorWaves - List ReactorWaveData (nested type)

    No description provided.

    hashtag
    LightsOnFromBeginning - Boolean

    No description provided.

    hashtag
    LightsOnDuringIntro - Boolean

    No description provided.

    hashtag
    LightsOnWhenStartupComplete - Boolean

    No description provided.

    hashtag
    DoNotSolveObjectiveOnReactorComplete - Boolean

    No description provided.

    hashtag
    SpecialTerminalCommand - String

    No description provided.

    hashtag
    SpecialTerminalCommandDesc - LocalizedText (nested type)

    No description provided.

    hashtag
    PostCommandOutput - List String

    No description provided.

    hashtag
    SpecialCommandRule - TERM_CommandRule (enum)

    No description provided.

    hashtag
    PowerCellsToDistribute - Int32

    No description provided.

    hashtag
    Uplink_NumberOfVerificationRounds - Int32

    No description provided.

    hashtag
    Uplink_NumberOfTerminals - Int32

    No description provided.

    hashtag
    Uplink_WaveSpawnType - SurvivalWaveSpawnType (enum)

    No description provided.

    hashtag
    CentralPowerGenClustser_NumberOfGenerators - Int32

    No description provided.

    hashtag
    CentralPowerGenClustser_NumberOfPowerCells - Int32

    No description provided.

    hashtag
    CentralPowerGenClustser_FogDataSteps - List GeneralFogDataStep (nested type)

    No description provided.

    hashtag
    ActivateHSU_ItemFromStart - UInt32 (ItemDataBlock)

    No description provided.

    hashtag
    ActivateHSU_ItemAfterActivation - UInt32 (ItemDataBlock)

    No description provided.

    hashtag
    ActivateHSU_BringItemInElevator - Boolean

    No description provided.

    hashtag
    ActivateHSU_MarkItemInElevatorAsWardenObjective - Boolean

    No description provided.

    hashtag
    ActivateHSU_StopEnemyWavesOnActivation - Boolean

    No description provided.

    hashtag
    ActivateHSU_ObjectiveCompleteAfterInsertion - Boolean

    No description provided.

    hashtag
    ActivateHSU_RequireItemAfterActivationInExitScan - Boolean

    No description provided.

    hashtag
    ActivateHSU_Events - List WardenObjectiveEventData (nested type)

    No description provided.

    hashtag
    Survival_TimeToActivate - Single

    No description provided.

    hashtag
    Survival_TimeToSurvive - Single

    No description provided.

    hashtag
    Survival_TimerTitle - LocalizedText (nested type)

    No description provided.

    hashtag
    Survival_TimerToActivateTitle - LocalizedText (nested type)

    No description provided.

    hashtag
    GatherTerminal_SpawnCount - Int32

    No description provided.

    hashtag
    GatherTerminal_RequiredCount - Int32

    No description provided.

    hashtag
    GatherTerminal_Command - String

    No description provided.

    hashtag
    GatherTerminal_CommandHelp - LocalizedText (nested type)

    No description provided.

    hashtag
    GatherTerminal_DownloadingText - LocalizedText (nested type)

    No description provided.

    hashtag
    GatherTerminal_DownloadCompleteText - LocalizedText (nested type)

    No description provided.

    hashtag
    GatherTerminal_DownloadTime - Single

    No description provided.

    hashtag
    TimedTerminalSequence_NumberOfRounds - Int32

    No description provided.

    hashtag
    TimedTerminalSequence_NumberOfTerminals - Int32

    No description provided.

    hashtag
    TimedTerminalSequence_TimePerRound - Single

    No description provided.

    hashtag
    TimedTerminalSequence_TimeForConfirmation - Single

    No description provided.

    hashtag
    TimedTerminalSequence_UseFilterForSourceTerminalPicking - Boolean

    No description provided.

    hashtag
    TimedTerminalSequence_SourceTerminalWorldEventObjectFilter - String

    No description provided.

    hashtag
    TimedTerminalSequence_EventsOnSequenceStart - List List WardenObjectiveEventData (nested type)

    No description provided.

    hashtag
    TimedTerminalSequence_EventsOnSequenceDone - List List WardenObjectiveEventData (nested type)

    No description provided.

    hashtag
    TimedTerminalSequence_EventsOnSequenceFail - List List WardenObjectiveEventData (nested type)

    No description provided.

    hashtag
    Additional docs

    All expeditions require at least 1 Warden Objective (for Main specifically), which determines if the objective for the level (or one of the layers within the level) is Reactor Startup, Central Generator Cluster and all that.

    To begin with, you can find any of the DBs in GameData_WardenObjectiveDatablock.json as your base reference.

    At first glance it looks quite intimidating, right? Don’t worry. Let’s do some categorizations and split those fields up. To make it more succinct, I will use one of the datablock copy-pasted from GameData_WardenObjectiveDatablock.json, but remove some redundant parts and add some comments where necessary.

    hashtag
    General fields

    hashtag
    Waves / Events / Fog / Chained Puzzle fields

    These fields tells the objective manager to spawn enemy waves and execute events at given point.

    hashtag
    On Elevator Land

    Literally on elevator land (upon cage drop). The fields are all self-clarifying.

    hashtag
    On Activate

    At first glance it's rather perplexing that what is "On Activate". Sadly, I have no idea how to describe it clearly ; )

    For now, you may refer to its usage in different objective type get some hints. "WavesOnActivate" and "EventsOnActivate" are not used as frequently as "WavesOnGotoWin" and "EventsOnGotoWin"; in addition, the first part, which is the explanation for field "OnActivateOnSolveItem", is quite long. So if you feel hard to understand this part, I suggest you skip this part and read "On Goto Win" first

    hashtag
    On Goto Win

    By "Goto Win", it means objective completion.

    hashtag
    Objective Chained Puzzle

    hashtag
    Objective-specific fields

    The following fields are all Objective Specific. You can remove those irrelevant fields given your objective type.

    Some objective types don't have their own objective-specific fields.

    Some may require you to spawn certain item(s) in certain zone(s) in LevelLayoutDatablock to make the objective work properly.

    hashtag
    3 - Gather Small Item

    Objective Type for R6C1 and R6D4.

    hashtag
    6 - Retrieve Big Item

    Objective Type for R6A1 and R6C2 Secondary.

    Note: for zones that spawn those Big Pickup Items (no matter if they are objective item or not), don't forget to set "BigPickupDistribution" in LevelLayoutDatablock to "true"

    hashtag
    1/2 - Reactor Startup/Shutdown

    Geomorph-tied objective type. To make a Reactor Startup / Shutdown work properly, you must set certain geomorph in the level.

    Here's a list of the name of Reactor geomorph (use Ctrl + F in the doc 'All Geomorph' to see what they look like):

    • Mining Reactor Open HA 1 ****"Assets/AssetPrefabs/Complex/Mining/Geomorphs/geo_64x64_mining_reactor_open_HA_01.prefab"

    • Mining Reactor HA 2 ****"Assets/AssetPrefabs/Complex/Mining/Geomorphs/geo_64x64_mining_reactor_HA_02.prefab"

    • Lab Reactor HA 1 ****"Assets/AssetPrefabs/Complex/Tech/Geomorphs/geo_64x64_lab_reactor_HA_01.prefab"

    • Lab Reactor HA 2 ****"Assets/AssetPrefabs/Complex/Tech/Geomorphs/geo_64x64_lab_reactor_HA_02.prefab"

    Note: For Reactor Shutdown, you can only use the Mining Reactor HA 2 as your Reactor Geomorph. Without aid of a plugin, Reactor Shutdown would be broken if using the other 3 geomorphs.

    Finally, there's no Floodway Reactor so far.

    hashtag
    5 - Special Terminal Command

    The most phenomenal use of this objective type is probably R5C2 Overload, in which "WavesOnActivate", "EventsOnActivate", "ChainedPuzzleMidObjective" are all well used.

    Also R5B3 Secondary (or Extreme) is an example for how to use this objective type.

    hashtag
    7 - Distribute Powercell

    R6C2 Main Objective.

    Note:

    1. If you are using this objective type as your Main Layer objective, the required number of powercells will be given in the elevator cargo container.

    2. Otherwise (you are using it as your Secondary/Overload objective), the powercells will spawn in the first zone of the layer. Don't forget to set those zones' "ForceBigpickupDistribution" to "true"

    3. If you don't want the powercell to be given in the elevator cargo, you will need the help of Tweaker, a plugin that enables you to manipulate your elevator cargo.

    In addition, you need to spawn the required number of PowerGenerator(s) in LevelLayoutDatablock in the desired zone(s). The objective manager would choose one of the unselected PowerGenerator(s) spawned in the zone as the objective generator.

    hashtag
    8/13 - Terminal Uplink / Corrupted Uplink

    R6B2 Secondary / R6D2 Secondary

    To use this objective types, you need to spawn required number of terminals for each uplink in LevelLayoutDatablock.

    Also, for Corrupted Uplink, sadly, for each Uplink, you CAN'T spawn the 2 terminals for the uplink in 2 different zone.

    hashtag
    9 - Central Generator Cluster

    Geomorph-tied objective type (same as Reactor Startup/Shutdown).

    Here's a list of the name of valid generator geomorph (in which you can spawn a generator cluster) . Use Ctrl + F in the doc 'All Geomorph' to see what they look like:

    • Digsite hub HA 1 ****"Assets/AssetPrefabs/Complex/Mining/Geomorphs/Digsite/geo_64x64_mining_dig_site_hub_HA_01.prefab"

    • Digsite hub HA 2 ****"Assets/AssetPrefabs/Complex/Mining/Geomorphs/Digsite/geo_64x64_mining_dig_site_hub_HA_02.prefab"

    • Lab hub HA 2 ****"Assets/AssetPrefabs/Complex/Tech/Geomorphs/geo_64x64_tech_lab_hub_HA_02.prefab"

    • Lab HA 2 [Standard Geomorph] ****"Assets/AssetPrefabs/Complex/Tech/Geomorphs/geo_64x64_tech_lab_HA_02.prefab"

    • Lab HA 3 [Standard Geomorph] "Assets/AssetPrefabs/Complex/Tech/Geomorphs/geo_64x64_tech_lab_HA_03.prefab"

    Note that I've marked the last 2 geomorph with [Standard Geomorph]. If you directly copy-paste them into "CustomGeomorph" in LevelLayoutDatablock, your console will flood with Errors. Without editing ComplexResourceSetDatablock, if you want to use the 2 standard geomorphs, you will need to roll subseed to change the Zone's layout and MarkerSubseed to finally get a Generator Cluster. I suggest you read the 'All Geomorph' doc to find out why.

    Oh, finally, in LevelLayoutDatablock, don't forget to set "GeneratorClustersInZone" to 1 in the desired zone.

    hashtag
    10 - Activate Neonate_HSU / Datasphere. Unseal Hi-Sec Cargo Crate.

    Geomorph-tied objective type (same as Reactor Startup/Shutdown).

    Here's a list of the name of available geomorph. Use Ctrl + F in the doc 'All Geomorph' to see what they look like:

    • Lab Dead End Room 1 ****"Assets/AssetPrefabs/Complex/Tech/Geomorphs/geo_64x64_Lab_dead_end_room_02.prefab"

    • Lab Dead End Room 2 ****"Assets/AssetPrefabs/Complex/Tech/Geomorphs/geo_64x64_Lab_dead_end_room_01.prefab"

    • Refinery Dead End HA 1 ****"Assets/AssetPrefabs/Complex/Mining/Geomorphs/Refinery/geo_64x64_mining_refinery_dead_end_HA_01.prefab"

    hashtag
    11 - Survival

    This type of objective begins upon entering the layer.

    For example, if you set the Secondary objective as Survival, the timer won't starts until any of your teammates pace into the Secondary Bulkhead Door.

    The objective completes upon the timer ends.

    You can end the timer in advance by using a "ForceWin" event.

    After the "prepare time" ends, the objective manager will start executing events in "EventsOnActivate", and spawn waves in "WavesOnActivate".

    hashtag
    12 - Gather Terminal

    hashtag
    How to write an Event?

    First, let's take a look at an event copy-pasted from the vanilla datablock:

    A bit intimidating, right? Luckily, for a certain event type only few fields are used, which means we can remove unused fields to make our file look cleaner.

    Here's a list of EventType:

    • 0 - None

    • 1 - OpenSecurityDoor

    • 2 - UnlockSecurityDoor

    • 3 - AllLightsOff

    • 4 - AllLightsOn

    • 5 - PlaySound

    • 6 - SetFogSetting

    • 7 - DimensionFlashTeam

    • 8 - DimensionWarpTeam

    • 9 - SpawnEnemyWave

    • 10 - StopEnemyWaves

    • 11 - UpdateCustomSubObjective

    • 12 - ForceCompleteObjective

    • 999 - EventBreak

    In the following I will try to explain what each event type does, and which fields are used. Also an example is provided for you to refer to and copy-paste.

    hashtag
    0 - None

    Does nothing. You can use it to display Warden Intel.

    hashtag
    1 - OpenSecurityDoor

    Open a given Sec-Door, even the door is locked with a security alarm.

    Note: Without aid of a plugin, you can't open a sec-door that has already been "approached".

    hashtag
    2 - UnlockSecurityDoor

    Works similarly as OpenSecurityDoor.

    hashtag
    3 - AllLightsOff

    Shutdown all lights in the current level.

    hashtag
    4 - AllLightsOn

    Turn on all lights in the current level.

    hashtag
    5 - PlaySound

    Play certain sound in/from specific zone. You will need to collect the sound ID from vanilla data.

    hashtag
    6 - SetFogSettings

    Changed the fog for the entire level.

    hashtag
    7 - DimensionFlashTeam

    [Not 100% sure if my explanation is correct. Rectify if anywhere wrong]

    Teleport your team to a given dimension, and teleport back after a certain duration.

    This event is used in R6A1 and R6C1.

    hashtag
    8 - DimensionWarpTeam

    [Not 100% sure if my explanation is correct. Rectify if anywhere wrong]

    Teleport your team to a given dimension. You need to execute another "DimensionWarpTeam" event in the dimension to teleport either to another dimension or back to reality.

    This event is used in R6D1 and R6D4.

    hashtag
    9 - SpawnEnemyWave

    Like the name said.

    Note: What's the difference between "WardenIntel" and "IntelMessage"?

    I'm not pretty sure...

    "WardenIntel" display intel message after "Delay" timer ends.

    "IntelMessage" won't change [ZONE_4] into actual zone name, and is displayed after "SpawnDelay" timer ends.

    hashtag
    10 - StopEnemyWave

    Stop all waves. For example, scout wave, reactor wave, uplink wave... everything.

    hashtag
    11 - UpdateCustomSubObjective

    What's "Custom SubObjective"? It's the "[PROGRESSION]" shown in the upper left of your hud, right below the objective description text.

    What's the difference between "CustomSubObjectiveHeader" and "CustomSubObjective"? I don't know how to explain this. It is used in R6D3 Overload, which tells you to shutdown the Error alarm in Zone 292.

    Note: unlike "WardenIntel", "CustomSubObjectiveHeader" and "CustomSubObjective" only accept reference to datablock. Do not use string.

    hashtag
    12 - ForceCompleteObjective

    Used in R6D1 to make the Main objective complete after the boss death.

    Use "Layer" to specify which layer to force win.

    hashtag
    999 - EventBreak

    Used in "EventsOnActivate"with "OnActivateOnSolveItem" set to true. Split up the event sequence to several parts and execute each on solving objective item.

    Take R6C1, R6C2 Main, R6D4 as example.

    eWardenObjectiveType
    // The following are common fields used by all objective types.
    // Enum that determines what type of the objective is. 
    // All objective types are listed above. 
    "Type": 6,
    
    // Probably a useless field :)
    "Header": "Retrieve Essential Items", 
    
    // Text that describes the objective. Here it’s simply a string, but for most WardenObjective in Rundown 6 it is reference to DB in TextDatablock. 
    "MainObjective": "Find the reactor for the floor and make sure it is back online.", 
    
    // Not quite sure… awaiting supplements :)
    "WardenObjectiveSpecialUpdateType": 0,
    
    // The following fields are all Text fields 
    // that work analogously as "MainObjective".
    "FindLocationInfo": 0, 
    "FindLocationInfoHelp": 0, 
    "GoToZone": 0,
    "GoToZoneHelp": 0,
    "InZoneFindItem": 0,
    "InZoneFindItemHelp": 0,
    "SolveItem": 0,
    "SolveItemHelp": 0,
    
    // The following Text fields will be displayed upon objective completion. 
    // Fields ending with "_Elevator" and "_CustomGeo" are 
    // typically  used by Main Objective. If you make the 
    // extraction point in the elevator zone, the former ones 
    // will be applied, otherwise (implying that you 
    // are using forward exit) the latter ones.
    // Fields ending with "_ToMainLayer" are typically 
    // used by Secondary or Overload. 
    // However, for the case of forward exit being set 
    // in either Secondary or Overload, 
    // I’m not pretty sure… awaiting supplements :)
    "GoToWinCondition_Elevator": 0,
    "GoToWinConditionHelp_Elevator": 0,
    "GoToWinCondition_CustomGeo": 0,
    "GoToWinConditionHelp_CustomGeo": 0,
    "GoToWinCondition_ToMainLayer": 0,
    "GoToWinConditionHelp_ToMainLayer": 0,
    "ShowHelpDelay": 180.0,
    "WavesOnElevatorLand": [],
    "WaveOnElevatorWardenIntel": 0,
    "EventsOnElevatorLand": [],
    
    // Firstly used in R4E1, which combos with Tank Error Alarm. 
    // This 2 fields could be easily replaced 
    // by a "SetFogSettings" Event in "EventsOnElevatorLand"
    "FogTransitionDataOnElevatorLand": 0,
    "FogTransitionDurationOnElevatorLand": 0.0, 
    // The following explanation is copy-pasted from @FlowAria's message in 
    // channel "modding-general". I'll do some extension basing on this.
    //
    // OnActivateOnSolveItem tells ObjectiveManager to trigger EventsOnActivate 
    // for each objective item "solved", this include:
    // 1. Picking up Objective gather item (Once for each) 
    // 2. Retrieve Item (Once for each, have some checkpoint bug)
    // 3. Input gather terminal command (Could be triggered as you want per single terminal, buggy)
    // 4. Plug powercell to objective generator (Generator Distribution / Generator Cluster)
    // 5. Established Uplink (per each terminals)
    // 6. Collected DNA from HSU
    // 7. Fully finish generator cluster
    // 8. Fully startup/shutdown reactor
    // 9. Finished Special command objective terminal 
    // 
    // The followings are my opinions, feel free to correct them if they are wrong.
    // -> Considering 4. and 7., you could find that "OnActivateOnSolveItem"
    //    works awkwardly on Generator-Cluster. 
    //    To my knowledge, Modulation C3 Secondary has taken this into good use, 
    //    you may use that as an example.
    // -> For 8., by setting the field below "DoNotSolveObjectiveOnReactorComplete",
    //    to "false", it is possible that you set multiple Reactors all in the same 
    //    layer of the level and trigger different sequences of events upon
    //    finishing each startup/shutdown, and finally use 
    //    a "ForceWin" event to complete the layer.
    "OnActivateOnSolveItem": false,
    
    // "WavesOnActivate" is only used by several objective types. 
    // -> Terminal Uplink / Corrupted Uplink 
    //    (spawn enemy wave on uplink establishment 
    //     and end them on verifications complete)
    // -> Special terminal commands 
    //    (after the activation scan, spawn enemy waves at given points.)
    // -> Survival 
    //    (spawn enemy waves at given points.)
    // -> Activate HSU 
    //    (not sure)
    "WavesOnActivate": [],
    
    // If "OnActivateOnSolveItem" is set to "true", refer to the doc above.
    // Otherwise, refer to the following.
    // "EventsOnActivate" is only used by several objective types.
    // -> Special terminal commands 
    //    (after the activation scan, execute events at given points.)
    // -> Survival 
    //    (execute events at given points.)
    "EventsOnActivate": [],
    
    // R5B3 Main and R5C2 Overload are good examples for good 
    // use of "WavesOnActivate" and "EventsOnActivate"
    // Stop all waves upon objective completion.
    // This can be replaced by a "StopEnemyWave" event 
    // in "EventsOnGotoWin"
    "StopAllWavesBeforeGotoWin": false,
    
    // For "WaveOnGotoWinTrigger" and "EventsOnGotoWinTrigger",
    // they are both enum that acceot the following 2 values. 
    // 0 - OnObjectiveCompleted,
    // 1 - WhenExitScanMakesProgress
    // Note: I'm not sure if "EventsOnGotoWinTrigger" works properly. 
    //       Awaiting confirmation :) 
    "WavesOnGotoWin": [],
    "WaveOnGotoWinTrigger": 0,
    "EventsOnGotoWin": [],
    "EventsOnGotoWinTrigger": 0,
    
    // Set Fog transition upon objective completion. 
    // This can be replaced by a "SetFogSetting" event in "EventsOnGotoWin"
    "FogTransitionDataOnGotoWin": 0,
    "FogTransitionDurationOnGotoWin": 0.0,
    // Used by: 
    // -> HSU_CollectDNASample 
    // -> Reactor Startup/Shutdown (to initiate their verification sequences)
    // -> Special Terminal Command 
    // -> Terminal Uplink (after CONNECT, before VERIFY)
    // This chained puzzle is usually a Security Scan without alarm,
    // but of course, you can make it an alarm if you want :)
    "ChainedPuzzleToActive": 0, // typical value: 4, 10
    
    // Used by CentralGeneratorCluster, ReactorShutdown and SpecialTerminalCommand
    // This is the chained puzzle the team would be required to complete
    // after plugging in all powercell / input shutdown verification code / input special terminal command 
    "ChainedPuzzleMidObjective": 0,   
    
    // Extraction scan. If the objective you are editing is 
    // not a Main layer objective, and does not require retrieving Big Pickup Item(s)  
    // to the extraction scan, feel free to left this field unchanged.
    "ChainedPuzzleAtExit": 11, // typical value: 11.
    
    // All vanilla levels use the same extraction scan puzzle.
    // So changing the multiplier below could 
    // change the extraction scan speed for different levels.
    "ChainedPuzzleAtExitScanSpeedMultiplier": 1.0,
    // Gather Small Item
    "Gather_RequiredCount": -1,
    // reference to ItemDataBlock
    "Gather_ItemId": 133, 
    "Gather_SpawnCount": 0,
    "Gather_MaxPerZone": 0,
    // Retrieve Big Item 
    "Retrieve_Items": [ 
      // references to ItemDatablock. 
      133,
      133
    ],
    // -------------------------------------
    // Reactor Startup/Shutdown
    
    // Note that if it is Reactor Shutdown, you need to 
    // leave at least 1 empty wave data in "ReactorWaves" to make the objective 
    // work properly (otherwise there will be 
    // no verification code for the shutdown)
    
    // Probably the most complicated, long field. 
    // Used by both Reactor Startup and Shutdown.
    // For Reactor Shutdown, it's used only for verification code generation.
    // This field serves mostly for Reactor Startup.
    "ReactorWaves": [
    // Array of wave information.
    // For conciseness, the example here only contains 1 wave. 
    // To create multiple waves, copy-pasted the first wave and edit 
    // the fields as needed. 
    
    { // 1st reactor wave.
        "Warmup": 30.0,        // First Warmup time
        "WarmupFail": 30.0,    // Warmup time if last wave faild to verify
        "Wave": 120.0,         // Defense time
        "Verify": 285.0,       // First Verify time
        "VerifyFail": 60.0,    // Verify time if last wave faild to verify
        
        // Is the code put in other zone? 
        // If set to true, don't forget to spawn a terminal / terminals 
        // in the corresponding zone.
        // 
        // If set to false, the code will be given on the HUD.
        "VerifyInOtherZone": true,
        
        // Works only when "VerifyInOtherZone" is set to true.
        // Specifies the zone to put the code.
        // One of the terminals in the zone will be selected (randomly).
        "ZoneForVerification": 13,
        
        // Defense Wave.
        "EnemyWaves": [
            {
                "WaveSettings": 23,     // reference to SurvivalWaveSettings
                                        // Search the word "Reactor" in SurvivalWaveSettings,
                                        // there are already some wave settings written by 10cc,
                                        // take them into good use.
                                        
                "WavePopulation": 6,    // reference to SurvivalWavePopulation
                
                "SpawnTimeRel": 0.0,    // Spawn time relative.
                                        // The exact spawn time = SpawnTimeRel * Wave
                                           
                "SpawnType": 1        // Enums. 
                                      // 0 - ClosestToReactorNoPlayerBetween
                                      // 1 - InElevatorZone
                                      
                                      // Note: This spawn type can be overriden
                                      // by m_overrideWaveSpawnType in SurvivalWaveSettings.
                                      // This is how flyers are spawned in R6D1 reactor
            }
        ],
        "Events": [
           // For reactor wave events,
           // "Trigger" plays a role in "when to execute this event".
           // It is an enum that accepts the following values:
           // 0 - None
           // 1 - OnStart
           // 2 - OnMid
           // 3 - OnEnd
           // Use the below one as an example, 
           // and don't miss the comments after "Trigger"
            {
                "Trigger": 1, // Executed before wave defense
                "Type": 2,
                "Layer": 0,
                "LocalIndex": 13,
                "Delay": 5.0,
                "WardenIntel": 1369, //"Door to [ZONE_13] unlocked by startup sequence.",
            },
            {
                "Trigger": 2, // Executed after wave defense 
                "Type": 11,
                "Layer": 0,
                "Delay": 12.0,
                "WardenIntel": 1370, //"Auxiliary temrinal located in [ZONE_13]",
                "CustomSubObjectiveHeader": 0,
                "CustomSubObjective": 99999 // "Find the verification code in [ZONE_13]"
            },
            {  
                "Trigger": 3, // Executed after verification for this wave completed.   
                "Type": 11,
                "Layer": 0,
                "LocalIndex": 0,
                "Delay": 0.0,
                "WardenIntel": 0,
                "CustomSubObjectiveHeader": 0,
                "CustomSubObjective": 0
            }
            // Note: For Trigger OnEnd (3) reactor wave events, 
            // They are only executed on host side, which means:
            // It works fine. But, on client side, the Warden Intel
            // for the events won't be displayed. 
        ]
    }, // First reactor wave ended
    {
    // the second reactor wave
    },
    {
    // the third reactor wave
    },
    // etc...
    ],
    
    // Determine if the Light is all on upon cage drop. 
    // To my knowledge this field is broken in R6 
    // - You need to add a “AllLightsOff” 
    // in "EventsOnElevatorLand" to make it work as expected
    "LightsOnFromBeginning": false, 
    
    // Determine if the Light is all on during 
    // when the current wave is in warm-up phase
    "LightsOnDuringIntro": false,
    
    // Determine if the Light is all on after startup complete
    // when the current wave is in warm-up phase
    "LightsOnWhenStartupComplete": false,
    
    // If set to true, the Reactor Startup / Shutdown objective 
    // will be deemed un-completed after Startup/Shutdown completed.
    // You need to use a ForceObjectiveComplete event
    // somewhere in the expedition.
    // In Vanilla this field is only used in R6D1, 
    // in which the ForceObjectiveComplete event 
    // is executed upon boss death
    // On the other hand, with "OnActivateOnSolveItem" set to true, 
    // you can use "EventsOnActivate" in place of "EventsOnGotoWin"
    // Probably you can use this field to create a expedition 
    // in which you need to initiate multiple Startup/Shutdown sequences :)
    "DoNotSolveObjectiveOnReactorComplete": true, 
    // Special Terminal Command
    // Surpassed by terminal "UniqueCommands" 
    // Awaiting supplements :)
    "SpecialTerminalCommand": "",
    "SpecialTerminalCommandDesc": "",
    "PostCommandOutput": [],
    "SpecialCommandRule": 0,
    // The number of powercell to distribute..
    "PowerCellsToDistribute": 0,
    "Uplink_NumberOfVerificationRounds": 0,
    "Uplink_NumberOfTerminals": 1,
    
    // Enum that determine wave spawn type.
    // Not sure how this field works, 
    // To my knowledge: 
    // 0 - In the nearby zone (like most sec-door alarm)
    // 1 - In the current zone 
    //     (which means the current zone should contain 
    //      multiple rooms (areas) to make the enemies spawn as expected)
    // 
    // -> Not sure if the spawn type can be override 
    //    by "m_overrideWaveSpawnType" in SurvivalWaveSettings
    // Awaiting supplements :)
    "Uplink_WaveSpawnType": 1,
    // Central Generator Cluster 
    "CentralPowerGenClustser_NumberOfGenerators": 4,
    "CentralPowerGenClustser_NumberOfPowerCells": 4,
    // You can change the fog upon plugging in each cell
    // This field is not used in Rundown 6. 
    // Take the following format as example.
    "CentralPowerGenClustser_FogDataSteps": [
        { // Fog changes upon plugging in the 1st powercell
          "m_fogDataId": 80, // reference to FogSettingsDatablock
          "m_transitionToTime": 1.0
        },
        { // Fog changes upon plugging in the 2nd powercell
          // If you don't want the fog to change at this point, 
          // set "m_fogDataId" to the same as the one before. 
          "m_fogDataId": 80, 
          "m_transitionToTime": 1.0
        },
        { // Upon plugging in the 3rd powercell
          "m_fogDataId": 81, 
          "m_transitionToTime": 60.0
        },
        { // Upon plugging in the 4th powercell
          "m_fogDataId": 82, 
          "m_transitionToTime": 360.0
        },
        { // Fog changes upon completing the ChainedPuzzleMidObjective.
          // Awaitng supplement: I'm not sure what would happen 
          //                     if "ChainedPuzzleMidObjective" is 0.
          "m_fogDataId": 83, 
          "m_transitionToTime": 10.0
        }
    ],
    // -------------------------------------
    // Activate Neonate_HSU / Datasphere. Unseal Hi-Sec cargo crate.
    // -> Neonate_HSU (which has 4 variants) and Datasphere are all Big pickup Item. 
    // -> Vanilla levels for reference: R3A1, R3B2, R3D1, R4C1, R5B3
    
    // Speaking of that you set Activate Neonate_HSU as you Main layer objective,
    // -> "ActivateHSU_ItemFromStart" specifies the Big Pickup item that will be placed 
    //    in the elevator cargo container upon cage drop,
    // -> "ActivateHSU_ItemAfterActivation" specifies the Big Pickup item will
    //    be replaced by another Big Pickup item after it's inserted.
    // Both of them are references to ItemDatablock    
    "ActivateHSU_ItemFromStart": 0,
    "ActivateHSU_ItemAfterActivation": 0,
    "ActivateHSU_StopEnemyWavesOnActivation": false,
    
    // Works analogously as "DoNotSolveObjectiveOnReactorComplete".
    "ActivateHSU_ObjectiveCompleteAfterInsertion": false,
    "ActivateHSU_RequireItemAfterActivationInExitScan": false,
    "ActivateHSU_Events": [],
    // The time for the players to "get prepared"
    "Survival_TimeToActivate": 0.0, 
    
    // The "Timer"
    "Survival_TimeToSurvive": 0.0, 
    
    // The titles. You can use either a string or a reference to TextDatablock
    "Survival_TimerTitle": "", 
    "Survival_TimerToActivateTitle": "",
    // Gather Terminal (R6D2 Main), works analogously as Gather Small Item. 
    "GatherTerminal_SpawnCount": 0, 
    "GatherTerminal_RequiredCount": 0, 
    "GatherTerminal_Command": "", 
    "GatherTerminal_CommandHelp": "", 
    "GatherTerminal_DownloadingText": "", 
    "GatherTerminal_DownloadCompleteText": "", 
    "GatherTerminal_DownloadTime": -1.0, 
    {
        "Trigger": 0,
        
        // set up chained puzzle for a certain command on a terminal
        // can only be used in "UniqueCommands" in LevelLayoutDatablock
        "ChainPuzzle": 0,   
        "UseStaticBioscanPoints": false,
        
        "Type": 0,
        "Layer": 0,
        "DimensionIndex": 0,
        "LocalIndex": 0,
        "Delay": 0.0,
        "Duration": 0.0,
        "ClearDimension": false,
        "WardenIntel": 0,
        "CustomSubObjectiveHeader": 0,
        "CustomSubObjective": 0,
        "SoundID": 0,
        "DialogueID": 0,
        "FogSetting": 0,
        "FogTransitionDuration": 0.0,
        "EnemyWaveData": {
            "WaveSettings": 0,
            "WavePopulation": 0,
            "SpawnDelay": 0.0,
            "TriggerAlarm": false,
            "IntelMessage": 0
        }
    }
    {
        "Trigger": 0,
        "Type": 0,
        "LocalIndex": 0,
        "Delay": 0.0,
        "WardenIntel": 1345 // "Door to [ZONE_5] unlocked"
    }
    {
        "Trigger": 0,
        "Type": 1,
        "Layer": 1,          // Specify layer in Reality (cannot be in dimension).  
        "DimensionIndex": 0, // Specify dimension if you are unlocking a door in dimension
        "LocalIndex": 2,     // Specify the door to unlock 
        "Delay": 0.0,
        "WardenIntel": 1345 // "Door to [ZONE_2] opened"
    }
    {
        "Trigger": 0,
        "Type": 2,
        "Layer": 1,          // Specify layer in Reality (cannot be in dimension).  
        "DimensionIndex": 0, // Specify dimension if you are unlocking a door in dimension
        "LocalIndex": 2,     // Specify the door to unlock 
        "Delay": 0.0,
        "WardenIntel": 1345 // "Door to [ZONE_2] unlocked"
    }
    {
        "Trigger": 0,
        "Type": 3,
        "Delay": 0.0,
        "WardenIntel": 1345 // "://SUPPROT SYSTEM OFFLINE"
    }
    {
        "Trigger": 0,
        "Type": 4,
        "Delay": 0.0,
        "WardenIntel": 1345 // "://SUPPROT SYSTEM RESTORED"
    }
    {
        "Trigger": 0,
        "Type": 5,
        "Layer": 1,
        "DimensionIndex": 0,
        "LocalIndex": 2,
        "Delay": 0.0,
        "WardenIntel": 1345, // "Birther Scream"
        "SoundID": 55555555, // Don't use this as your sound id :)
        "DialogueID": 0 // I'm not sure if this is also used. 
    }
    {
        "Trigger": 0,
        "Type": 6,
        "Delay": 0.0,
        "FogSetting": 87,
        "WardenIntel": 1345, // "Malfunction in air purification system."
        "FogTransitionDuration": 5400.0
    }
    {
        "Trigger": 0,
        "Type": 7,
        "DimensionIndex": 1,     // Dimension to teleport to
        "LocalIndex": 0,
        "Delay": 0.0,
        "Duration": 120.0,       // Teleport back after 120 seconds.
        "ClearDimension": true, // Removed all enemies in the dimension after teleporting back
        "WardenIntel": 1345
    }
    {
        "Trigger": 0,
        "Type": 8,
        "DimensionIndex": 1,     // Dimension to teleport to
        "LocalIndex": 0,
        "Delay": 0.0,
        "ClearDimension": true, // Removed all enemies in previous the dimension
        "WardenIntel": 1345
    }
    {
        "Trigger": 0,
        "Type": 9,
        "Delay": 0.0,
        "WardenIntel": 0,
        "EnemyWaveData": {
            "WaveSettings": 23,
            "WavePopulation": 7,
            "SpawnDelay": 0.0,
            "TriggerAlarm": false,
            "IntelMessage": 0
        }
    }
    {
        "Trigger": 0,
        "Type": 10,
        "Delay": 0.0,
        "WardenIntel": 0,
    }
    {    
        "Trigger": 0,
        "Type": 11,
        "Layer": 0,
        "Delay": 0.0,
        "WardenIntel": 0,
        "CustomSubObjectiveHeader": 1344,
        "CustomSubObjective": 1345
    }
    {    
        "Trigger": 0,
        "Type": 12,
        "Layer": 1,
        "Delay": 0.0,
        "WardenIntel": 0
    }
    {    
        "Trigger": 0,
        "Type": 999
    }

    BoosterImplantEffect

    GameData_BoosterImplantEffectDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    Effect - (enum)

    No description provided.

    hashtag
    PublicShortName - (nested type)

    No description provided.

    hashtag
    PublicName - (nested type)

    No description provided.

    hashtag
    Description - (nested type)

    No description provided.

    hashtag
    DescriptionNegative - (nested type)

    No description provided.

    hashtag
    BoosterEffectCategory - (enum)

    No description provided.

    ArtifactTag

    GameData_ArtifactTagDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    Tags - (enum)

    No description provided.

    ChainedPuzzleType

    GameData_ChainedPuzzleTypeDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    BoosterImplantTemplate

    GameData_BoosterImplantTemplateDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    BoosterImplantCondition

    GameData_BoosterImplantConditionDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    Clouds

    GameData_CloudsDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    Atmosphere

    GameData_AtmosphereDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    Prefab - String

    No description provided.

    Deprecated - Boolean

    No description provided.

    hashtag
    PublicName - LocalizedText (nested type)

    No description provided.

    hashtag
    Description - LocalizedText (nested type)

    No description provided.

    hashtag
    DurationRange - Vector2

    No description provided.

    hashtag
    DropWeight - Single

    No description provided.

    hashtag
    Conditions - List UInt32 (BoosterImplantConditionDataBlock)

    No description provided.

    hashtag
    RandomConditions - List UInt32 (BoosterImplantConditionDataBlock)

    No description provided.

    hashtag
    Effects - List BoosterImplantEffectInstance (nested type)

    No description provided.

    hashtag
    RandomEffects - List List BoosterImplantEffectInstance (nested type)

    No description provided.

    hashtag
    ImplantCategory - BoosterImplantCategory (enum)

    No description provided.

    hashtag
    MainEffectType - BoosterEffectCategory (enum)

    No description provided.

    Condition - BoosterCondition (enum)

    No description provided.

    hashtag
    PublicShortName - LocalizedText (nested type)

    No description provided.

    hashtag
    PublicName - LocalizedText (nested type)

    No description provided.

    hashtag
    Description - LocalizedText (nested type)

    No description provided.

    hashtag
    IconPath - String

    No description provided.

    CoverageTexture - String

    No description provided.

    hashtag
    CoverageSize - Single

    No description provided.

    hashtag
    Altitude - Single

    No description provided.

    hashtag
    Height - Single

    No description provided.

    hashtag
    Center - Single

    No description provided.

    hashtag
    Belly - Single

    No description provided.

    hashtag
    Crown - Single

    No description provided.

    hashtag
    Anvil - Single

    No description provided.

    hashtag
    Softness - Single

    No description provided.

    hashtag
    NoiseTexture - String

    No description provided.

    hashtag
    NoiseScale1 - Single

    No description provided.

    hashtag
    NoiseIntensity1 - Single

    No description provided.

    hashtag
    NoiseScale2 - Single

    No description provided.

    hashtag
    NoiseIntensity2 - Single

    No description provided.

    hashtag
    AmbientOcclusion - Single

    No description provided.

    hashtag
    startupShard - AssetBundleShard (enum)

    No description provided.

    LightColor - Color

    No description provided.

    hashtag
    PlanetAlbedo - Color

    No description provided.

    AgentModifier
    LocalizedText
    LocalizedText
    LocalizedText
    LocalizedText
    BoosterEffectCategory
    List ArtifactTags

    EnvironmentFeedback

    GameData_EnvironmentFeedbackDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    audioData - (nested type)

    No description provided.

    hashtag
    effectData - (nested type)

    No description provided.

    GearCategoryFilter

    GameData_GearCategoryFilterDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    AllowedCategories - (nested type)

    No description provided.

    CustomAssetShard

    GameData_CustomAssetShardDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    BundleName - (enum)

    No description provided.

    hashtag
    Assets - (nested type)

    No description provided.

    GearMagPart

    GameData_GearMagPartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    ClipSizeMultiplier - Single

    No description provided.

    hashtag
    ReloadTimeMultiplier - Single

    No description provided.

    hashtag
    ReloadLeftHandGripAnim - String

    No description provided.

    hashtag
    DropSoundType - (enum)

    No description provided.

    hashtag
    General - (nested type)

    No description provided.

    hashtag
    Aligns - (nested type)

    No description provided.

    GearMeleeHeadPart

    GameData_GearMeleeHeadPartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    Feedback

    GameData_FeedbackDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    GearFrontPart

    GameData_GearFrontPartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    GameSetup

    GameData_GameSetupDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    GearFlashlightPart

    GameData_GearFlashlightPartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    GearMeleeNeckPart

    GameData_GearMeleeNeckPartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag

    General - GearPartGeneralData (nested type)

    No description provided.

    hashtag
    Aligns - List GearPartAlignData (nested type)

    No description provided.

    audioData - List FeedbackAudioCompData (nested type)

    No description provided.

    hashtag
    effectData - List FeedbackEffectCompData (nested type)

    No description provided.

    General - GearPartGeneralData (nested type)

    No description provided.

    hashtag
    Aligns - List GearPartAlignData (nested type)

    No description provided.

    hashtag
    FireSequence - List WeaponAnimSequenceItem (nested type)

    No description provided.

    hashtag
    ReloadSequence - List WeaponAnimSequenceItem (nested type)

    No description provided.

    RundownIdsToLoad - List UInt32 (RundownDataBlock)

    No description provided.

    hashtag
    StartupScreenToLoad - eStartupScreenKey (enum)

    No description provided.

    General - GearPartGeneralData (nested type)

    No description provided.

    hashtag
    Aligns - List GearPartAlignData (nested type)

    No description provided.

    General - GearPartGeneralData (nested type)

    No description provided.

    hashtag
    Aligns - List GearPartAlignData (nested type)

    No description provided.

    List FeedbackAudioCompData
    List FeedbackEffectCompData
    List GearCategoryFilterData
    AssetBundleName
    List AssetData
    MagazineDropSoundType
    GearPartGeneralData
    List GearPartAlignData

    GearPartAttachment

    GameData_GearPartAttachmentDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    AttachToAlign - (enum)

    No description provided.

    hashtag
    General - (nested type)

    No description provided.

    hashtag
    Aligns - (nested type)

    No description provided.

    GearMeleeHandlePart

    GameData_GearMeleeHandlePartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    General - (nested type)

    No description provided.

    hashtag
    Aligns - (nested type)

    No description provided.

    GearMeleePommelPart

    GameData_GearMeleePommelPartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    General - (nested type)

    No description provided.

    hashtag
    Aligns - (nested type)

    No description provided.

    GearSightPart

    GameData_GearSightPartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    General - (nested type)

    No description provided.

    hashtag
    Aligns - (nested type)

    No description provided.

    hashtag
    SightProperties - (nested type)

    No description provided.

    eGearPartAlign
    GearPartGeneralData
    List GearPartAlignData
    GearPartGeneralData
    List GearPartAlignData
    GearPartGeneralData
    List GearPartAlignData
    GearPartGeneralData
    List GearPartAlignData
    GearSightPartProperties

    GearStockPart

    GameData_GearStockPartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    General - (nested type)

    No description provided.

    hashtag
    Aligns - (nested type)

    No description provided.

    hashtag
    FireSequence - (nested type)

    No description provided.

    hashtag
    ReloadSequence - (nested type)

    No description provided.

    GearReceiverPart

    GameData_GearReceiverPartDataBlock_bin.json

    No description provided.


    hashtag
    Fields

    hashtag
    General - (nested type)

    No description provided.

    hashtag
    Aligns - (nested type)

    No description provided.

    hashtag
    FireSequence - (nested type)

    No description provided.

    GearPartGeneralData
    List GearPartAlignData
    List WeaponAnimSequenceItem
    List WeaponAnimSequenceItem
    GearPartGeneralData
    List GearPartAlignData
    List WeaponAnimSequenceItem
    GitHub - UntiIted/GTFO-NewbieLevelGuideGitHubchevron-right
    Logo
    Audacity ® | Downloadswww.audacityteam.orgchevron-right
    Logo
    https://www.audiokinetic.com/download/www.audiokinetic.comchevron-right