With the A17 update we have a wonderful new patching feature to help with mod compatability. It looks to be a brilliant idea, but it requires xpathing. This may be a new idea to some people. I know it was to me.
https://gist.github.com/Zhentar/4a1b71cea45b9337f70b30a21d868782 Zhentar's guide on patching is helpful, but it doesn't tell us how xpathing works and only gives us a few examples. So I'll give a few more examples here, and explain xpathing.
If you are like me you had no idea what xpathing was. Well I have good news, it's actually pretty simple! You can think of it like selecting a path for a texture, or any other folder path. Here's an example:
If you wanted to use a custom texture for your custom gun you would do:
<texPath>Weapons/Ranged/CustomGun</texPath>
Well that's how you'd do it for selecting a texture, but what about xpaths?
Let's say you wanted to change the warm up of the pistol from 0.3 to 5.2. We shouldn't be editing the defs if we can patch it in, so how would we do it? Well if we want to change the warm up of the pistol we can use the class "PatchOperationReplace". Which as the name suggests we can use to replace something, it looks like this
<Patch>
<Operation Class="PatchOperationReplace">
<xpath>/ThingDefs/ThingDef[defName = "Gun_Pistol"]/verbs/li/warmupTime</xpath>
<value>
<WarmupTime>5.2</WarmupTime>
</value>
</Operation>
</Patch>
This code goes down the designated xpath until it finds the pistols warm up time. It then replaces it with the set value.
Now let me explain exactly how the xpath works. First of all, everything in the xml could be described as a node.
<ThingDef> is a node and so is <defName>, <warmupTime>, <verbs>, and <description>. Every different tag you see is a node. All xpathing is, is just inputting the correct sequence of nodes.
We start with /ThingDefs, you may be wondering what the slash at the beginning means. This selects all root nodes with that name. It is the beginning of the thingdefs for the gun so it is the beginning of our xpath
Next is /Thingdef. This specifies what we want to grab from the thingdefs. But /ThingDef is grabbing every <ThingDef> it can find. This is why we narrow it down with the next part.
Alternitively we could have done //ThingDef, but this is less optimized and slows down the patching process because it selects the root node and all it's children.
After /ThingDef we attach the defname, so it looks like this /ThingDef[defName = "Gun_Pistol". Now instead of trying to search everything with the <ThingDef> tag, it will only look for the one with the <defName> tag of Gun_Pistol.
We have now told the code to look for the correct ThingDef, but it doesn't know where warmupTime is. So we add more nodes to the xpath, now it's /ThingDef[defName = "Gun_Pistol"]/verbs.
The single slash here looks for all the children of our ThingDef for the pistol named "verbs".
If you look at the code for the pistol you'll see that <warmupTime> is indeed under the verbs, but it's nestled in the <li> tag. Our xpath doesn't know this, so we'll just get errors or replace the verbs tag with <warmupTime>, which will cause errors.
So now we add "li" to our path so it looks like this //ThingDef[defName = "Gun_Pistol"]/verbs/li. You might think this is the end, but we still haven't directed it to the correct place. Now it's gonna replace "li" which will cause errors.
So we want to go one step further and make it /ThingDef[defName = "Gun_Pistol"]/verbs/li/warmupTime. Now our code is looking for the ThingDef named Gun_Pistol, then it looks for any children of that def called verbs. After that any children of verbs called "li", and then any children of li called "warmupTime".
That will finally replace the pistols warm up time.
But what if there were more than one child named "li", like in the hediff for blood loss. Then we could do this
<Patch>
<Operation Class="PatchOperationReplace">
<xpath>/Defs/HediffDef[defName = "BloodLoss"]/stages/li[2]/capMods/li/offset</xpath>
<value>
<offset>-0.15</offset>
</value>
</Operation>
</Patch>
This code will look for the HediffDef named "BloodLoss", it'll then look for a child named stages. Stages has multiple <li> children so I've specified that I want it to look for the second <li> tag. Then once its found the second <li> tag it'll follow the path just like it did with the pistol.
Of course you can have multiple operations in the same patch too. There's also more PatchOperations than just replace. You should check out Zhentar's Guide for those.
If you want more information about the xpath syntax I'd recommend going here:
https://www.w3schools.com/xml/xpath_syntax.aspHere's a tool to help you figure out the xpath:
http://xmltoolbox.appspot.com/xpath_generator.htmlI hope this helps anyone who had trouble with it.
Thanks to Shinzy and kaptain_kavern for pointing out some optimizations, and thanks to NoImageAvalible for showing the right way to use the optmizations.