XML Configuration Files

While vanilla BLT mods are defined using JSON stored in mod.txt, SuperBLT also allows you to define hooks (and only allows you to use XML for the additional functionality added by SuperBLT) in XML format. This has the advantage of being significantly more concise.

The structure of the XML files is extremely flexible. You write a file called supermod.xml in your mod folder (the name can be changed using the supermod_definition entry in mod.txt, however this will not affect the XML Tweaker - it will always load from supermod.xml). This file contains a <mod> tag, which everything else goes inside.

Note that in the XML files read by SuperBLT, you should start them with an XML declaration. This is optional but recomended for the files only read by the Lua section of SuperBLT, howver they are mandatory for the parts read by Wren (supermod.xml, and any other files used by the XML Tweaker).

Inside of it, you can include other files using the <:include src="..." /> tag. This specifies another XML file (relative to your mod root directory) to load. The root-level tag from that XML file will replace the <:include/> tag. This also works inside included XML files, not just the root ones.

Attribute system

Each XML tag has a set of attributes - these can be set by using normal XML attributes (<tag attribute1="value" attribute2="value2">), however unlike normal XML each tag inherets these attributes from it's parent, and so on. This means that if you want to set a parameter on a lot of tags at once, and don't want to have to copy that parameter out to all the tags you wish to set it on, you just need to put it in a parent tag somewhere up the line.

If you don't want to replace the entire attribute, but instead want to modify the attribute you would have inherited, you can do so by prepending a : onto the name of your attribute (<tag :attr="value">). This appends the value you have selected onto the value inherited from parent tags.

These parameters are used for the inputs to the tags later on in this document - you never have to specify an attribute directly inside a tag like you do in standard XML.


If you want to have a parent tag used to set attributes at detailed above, but don't want that tag to do anything else, you can use a <group> tag. These serve as containers, and can be positioned anywhere in your document to group together child tags.

Let's take an example of this. We want to hook a bunch of files using XML, at detailed later in this document.

    <post script_path="lua/loc.lua" hook_id="lib/managers/localizationmanager"/>
    <post script_path="lua/cop/copbrain.lua" hook_id="lib/units/enemies/cop/copbrain"/>
    <post script_path="lua/cop/copmovement.lua" hook_id="lib/units/enemies/cop/copmovement"/>
    <post script_path="lua/cop/copinventory.lua" hook_id="lib/units/enemies/cop/copinventory"/>
    <post script_path="lua/cop/copdamage.lua" hook_id="lib/units/enemies/cop/copdamage"/>
    <post script_path="lua/cop/copbase.lua" hook_id="lib/units/enemies/cop/copbase"/>

Here, you can see there is a lot of repetition in the path names shown above. Firstly, all the files we're hooking are inside the lib directory in PAYDAY 2, and the files we are running in responce are all in the lua folder. By putting the base values for these attributes into a parent tag (in this case, the <hooks> tag), and then extending them by prepending the attribute names with a :, we can shorten these lines.

<hooks script_path="lua/" hook_id="lib/">
    <post :script_path="loc.lua" :hook_id="managers/localizationmanager"/>
    <post :script_path="cop/copbrain.lua" :hook_id="units/enemies/cop/copbrain"/>
    <post :script_path="cop/copmovement.lua" :hook_id="units/enemies/cop/copmovement"/>
    <post :script_path="cop/copinventory.lua" :hook_id="units/enemies/cop/copinventory"/>
    <post :script_path="cop/copdamage.lua" :hook_id="units/enemies/cop/copdamage"/>
    <post :script_path="cop/copbase.lua" :hook_id="units/enemies/cop/copbase"/>

This is certainly better, however there's still a lot of duplication in the cop hooks. There's no tag that's the parent of the cop hooks, but not of the localization hook which we want to leave alone. However, we can safely insert a group tag anywhere, which allows us to set the parent parameters for these tags.

<hooks script_path="lua/" hook_id="lib/">
    <post :script_path="loc.lua" :hook_id="managers/localizationmanager"/>

    <group :script_path="cop/" :hook_id="units/enemies/cop/">
        <post :script_path="copbrain.lua" :hook_id="copbrain"/>
        <post :script_path="copmovement.lua" :hook_id="copmovement"/>
        <post :script_path="copinventory.lua" :hook_id="copinventory"/>
        <post :script_path="copdamage.lua" :hook_id="copdamage"/>
        <post :script_path="copbase.lua" :hook_id="copbase"/>

Much cleaner!

Note that if on any of the above attributes, we could omit the : and specify a full path, rather than relative to the path set on any parent tags.

Also note that we are responsible for putting slashes on the end of our paths - SuperBLT does not (and this will not change in the future) do this automatically (this also lets you prefix everything).

Also note that we could move the <post/> tags into a seperate file, and then <:include/> it in - there are no limitations on where you can put include and post tags.

XML Tweaker tags

<tweak/> and <wren> tags belong to the XML Tweaker. They must be on the root level of the main file, and so cannot be <:include/>ed or placed inside <group> tags.


You can use the XML Tweaker to define hooks, instead of doing so in mod.txt. This can be a lot cleaner, given the use of attributes as demonstrated above. To do so, you need a <hooks> tag. This tag does not use any attributes. Note you can safely have multiple <hooks> tags, if it helps you lay stuff out.

Inside the hooks tag you can have three types of tags - post, pre and (currently unimplemented) wildcard. These correspond to posthooks, prehooks and wildcard hooks (for those not familier with this, posthooks are the ordinary and by far the most commonly used type of hook).

Each of these nodes takes the script_path attribute, which is the location (relative to your mod) of the Lua file you want run. With the exception of the wildcard hook, which runs on every file, the tag also takes the hook_id attribute, which is the path of the PAYDAY Lua file you want to hook, same as in mod.xml.


SuperBLT supports loading custom assets into the game. While this is easy to do yourself (using DB:create_entry), SuperBLT supports registering your custom units with the package system, making them usable in-game.

Currently, the support is very basic, and only allows you to supply a list of assets you want loaded. First create a <assets> tag (same as <hooks>, you can create as many of these as you want), and then put <file/> tags inside.

Each <file/> tag takes a name attribute, which is the name (including extension) of what you want the virtual file inside PAYDAY 2 to be. It also takes either a path or base_path attribute - if you supply path, this is the path of the physical file (relative to your mod folder) that you want to load. If this attribute is missing, instead the base_path attribute is used. The name attribute is appended to this, and the result is used as the path.

Currently, all assets are automatically loaded when the game starts. This will certainly change in an update, and there will be the ability to load groups of assets when a basegame package is loaded, or from the host mod via Lua.

To ensure compatibility with future versions in this regard, set the load parameter of the <file/> node to startup until this is implemented.