The XML Tweaker allows you to modify any base-game XML file. As many of the file you're likely interested in are loaded before Lua is set up, the XML tweaker isn't written in Lua. Instead, it's written in Wren. However, unless you're doing unusually complicated stuff, you can just specify your changes in XML.
Note that the API documentation for using Wren does not currently exist. If you're sure you need it, nag me (ZNix/ZNixian) and I'll hurry up and write it for you.
The first thing you'll need to do to use the XML Tweaker is to write a SuperBLT definiton. This is an XML file that specifies what tweaks and/or Wren files should be loaded. For the purposes of explanation, let's write a simple mod that changes the title of the PAYDAY 2 window.
We can do this by modifying context.xml. While there isn't really much point in doing so using a tweak, as it would be much easier to just modify this file by hand. Nevertheless, it's a good example of how to use XML tweaks.
First, create a new mod folder (you don't have to write a mod.txt file if you don't want to). Inside
supermod.xml, and insert the following:
<?xml version="1.0"?> <mod> <!-- Use the tweak defined in game_name_tweak.xml - if you have a lot of these, you should probably put them in their own directory --> <tweak definition="game_name_tweak.xml" /> </mod>
Do not omit the XML declaration - they should be present with all XML files you write for the tweaker.
This tells the tweaker to load a tweak contained inside
game_name_tweak.xml. Create that file now.
<tweak name="#8db63936938575bf" extension="#8db63936938575bf"> <search> <!-- search for a game_name tag inside a context tag --> <context /> <game_name short_name="PAYDAY 2" /> <!-- Make sure the game_name tag contains the short_name attribute, with it set to "PAYDAY 2" --> </search> <!-- With the mode set to "replace", it deletes the old tag and subsitiutes this one. Normally, it adds the target tags inside the searched tag. --> <target mode="attributes"> <!-- <game_name short_name="PAYDAY 2" long_name="Hello, World!" full_name="PAYDAY 2" /> --> <attr name="long_name" value="Hello, Attributes!" /> </target> </tweak>
Let's break this down. In this file we're only declaring a single tweak (you can have multiple tweaks in a single
XML file by using a
<tweaks> root node, and putting multiple
<tweak> nodes inside that).
As context.xml isn't loaded from the bundle DB like other XML files are, we're using the name and extension of the file loaded directly before it was loaded (which isn't an XML file). Normally, you'd specify the name and extension of the file you're trying to tweak, like so:
<tweak name="settings/network" extension="network_settings">
If you don't know the textual name of the file, and it's not contained in whatever hashlist you're using, you can directly
use hashes by prefixing them with a
# symbol. Please note that the XML Tweaker represents hashes in hexidecimal, and padded
out to 16 charactors long using
0s. This is important if you're using a hash you got out of Bundle Modder, as it doesn't pad
Next, there's the search tag. This tells the tweaker what tag in the target file we're trying to modify. Each entry in the search tag is an empty element with the same name as the target element in the XML file, no children, and any attributes the target element has (if you don't have an attribute in the search element, it will still match target elements with that attribute).
Each element in the search tag represents a element in the target file, which is the child of the previous element in the search tag, starting with the root node. That may be a little hard to understand, so here's an example:
The file we want to tweak:
<a> <b abc="def"> <c id="a"> <f/> </c> <c id="b"> <f/> <g/> </c> </b> </a>
Let's say we want to insert a
<helloworld/> node as a child of the second
<f/> node. Here's our required
<search> node for that:
<search> <a/> <b/> <c id="b"/> <f/> </search>
Lastly, you have your
<target> tag. This contains the block of XML you want to inject into the XML file. This can be set to
one of several modes, by setting the
For example, to insert a
<helloworld> node somewhere in the document:
<target mode="insertmodehere"> <helloworld greeting="Hello" subject="XML Tweaker" /> </target>
Please note all modes must be in lower case.
attach mode (default)
attach mode (which you get if you omit the
mode attribute), the contents of the target node are attached onto the
node found by search. To use the above example, the result in attach mode would be:
<a> <b abc="def"> <c id="a"> <f/> </c> <c id="b"> <f> <helloworld greeting="Hello" subject="XML Tweaker" /> </f> <g/> </c> </b> </a>
Append mode inserts the target node after (but on the same level as) the node found by search. Example from above:
<a> <b abc="def"> <c id="a"> <f/> </c> <c id="b"> <f/> <helloworld greeting="Hello" subject="XML Tweaker" /> <g/> </c> </b> </a>
Replace mode works the same way as append mode, but also removes the node found by search:
<a> <b abc="def"> <c id="a"> <f/> </c> <c id="b"> <helloworld greeting="Hello" subject="XML Tweaker" /> <g/> </c> </b> </a>
Attributes mode works quite differently from the other modes. While in other modes you're inserting an arbitary piece of
XML somewhere in the target document, in attributes mode you're modifying the node you found. Using the
target used above with attributes mode would result in a crash.
Attributes mode is very useful if you want to change some attributes on a tag that has a lot of children, and you don't want to have to duplicate them (which would require you to update your mod whenever a PAYDAY 2 update came out that modified those children).
<target mode="attributes"> <attr greeting="Hello" subject="XML Tweaker" /> </target>
<a> <b abc="def"> <c id="a"> <f/> </c> <c id="b"> <f greeting="Hello" subject="XML Tweaker" /> <g/> </c> </b> </a>